1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Copyright 2001-2004 The Apache Software Foundation.
   7  *
   8  * Licensed under the Apache License, Version 2.0 (the "License");
   9  * you may not use this file except in compliance with the License.
  10  * You may obtain a copy of the License at
  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 
  21 package com.sun.org.apache.xerces.internal.impl.xs.traversers;
  22 
  23 import java.util.Locale;
  24 import java.util.Vector;
  25 
  26 import com.sun.org.apache.xerces.internal.impl.dv.InvalidDatatypeValueException;
  27 import com.sun.org.apache.xerces.internal.impl.dv.XSFacets;
  28 import com.sun.org.apache.xerces.internal.impl.dv.XSSimpleType;
  29 import com.sun.org.apache.xerces.internal.impl.validation.ValidationState;
  30 import com.sun.org.apache.xerces.internal.impl.xs.SchemaGrammar;
  31 import com.sun.org.apache.xerces.internal.impl.xs.SchemaSymbols;
  32 import com.sun.org.apache.xerces.internal.impl.xs.XSAnnotationImpl;
  33 import com.sun.org.apache.xerces.internal.impl.xs.XSAttributeGroupDecl;
  34 import com.sun.org.apache.xerces.internal.impl.xs.XSAttributeUseImpl;
  35 import com.sun.org.apache.xerces.internal.impl.xs.XSComplexTypeDecl;
  36 import com.sun.org.apache.xerces.internal.impl.xs.XSElementDecl;
  37 import com.sun.org.apache.xerces.internal.impl.xs.XSParticleDecl;
  38 import com.sun.org.apache.xerces.internal.impl.xs.XSWildcardDecl;
  39 import com.sun.org.apache.xerces.internal.impl.xs.util.XInt;
  40 import com.sun.org.apache.xerces.internal.impl.xs.util.XSObjectListImpl;
  41 import com.sun.org.apache.xerces.internal.util.DOMUtil;
  42 import com.sun.org.apache.xerces.internal.util.NamespaceSupport;
  43 import com.sun.org.apache.xerces.internal.util.SymbolTable;
  44 import com.sun.org.apache.xerces.internal.xni.QName;
  45 import com.sun.org.apache.xerces.internal.xs.XSAttributeUse;
  46 import com.sun.org.apache.xerces.internal.xs.XSObjectList;
  47 import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition;
  48 import org.w3c.dom.Element;
  49 
  50 /**
  51  * Class <code>XSDAbstractTraverser</code> serves as the base class for all
  52  * other <code>XSD???Traverser</code>s. It holds the common data and provide
  53  * a unified way to initialize these data.
  54  *
  55  * @xerces.internal
  56  *
  57  * @author Elena Litani, IBM
  58  * @author Rahul Srivastava, Sun Microsystems Inc.
  59  * @author Neeraj Bajaj, Sun Microsystems Inc.
  60  *
  61  */
  62 abstract class XSDAbstractTraverser {
  63 
  64     protected static final String NO_NAME      = "(no name)";
  65 
  66     // Flags for checkOccurrences to indicate any special
  67     // restrictions on minOccurs and maxOccurs relating to "all".
  68     //    NOT_ALL_CONTEXT    - not processing an <all>
  69     //    PROCESSING_ALL_EL  - processing an <element> in an <all>
  70     //    GROUP_REF_WITH_ALL - processing <group> reference that contained <all>
  71     //    CHILD_OF_GROUP     - processing a child of a model group definition
  72     //    PROCESSING_ALL_GP  - processing an <all> group itself
  73 
  74     protected static final int NOT_ALL_CONTEXT    = 0;
  75     protected static final int PROCESSING_ALL_EL  = 1;
  76     protected static final int GROUP_REF_WITH_ALL = 2;
  77     protected static final int CHILD_OF_GROUP     = 4;
  78     protected static final int PROCESSING_ALL_GP  = 8;
  79 
  80     //Shared data
  81     protected XSDHandler            fSchemaHandler = null;
  82     protected SymbolTable           fSymbolTable = null;
  83     protected XSAttributeChecker    fAttrChecker = null;
  84     protected boolean               fValidateAnnotations = false;
  85 
  86     // used to validate default/fixed attribute values
  87     ValidationState fValidationState = new ValidationState();
  88 
  89     XSDAbstractTraverser (XSDHandler handler,
  90             XSAttributeChecker attrChecker) {
  91         fSchemaHandler = handler;
  92         fAttrChecker = attrChecker;
  93     }
  94 
  95     void reset(SymbolTable symbolTable, boolean validateAnnotations, Locale locale) {
  96         fSymbolTable = symbolTable;
  97         fValidateAnnotations = validateAnnotations;
  98         fValidationState.setExtraChecking(false);
  99         fValidationState.setSymbolTable(symbolTable);
 100         fValidationState.setLocale(locale);
 101     }
 102 
 103     // traverse the annotation declaration
 104     // REVISIT: how to pass the parentAttrs? as DOM attributes?
 105     //          as name/value pairs (string)? in parsed form?
 106     // @return XSAnnotationImpl object
 107     XSAnnotationImpl traverseAnnotationDecl(Element annotationDecl, Object[] parentAttrs,
 108             boolean isGlobal, XSDocumentInfo schemaDoc) {
 109         // General Attribute Checking
 110         Object[] attrValues = fAttrChecker.checkAttributes(annotationDecl, isGlobal, schemaDoc);
 111         fAttrChecker.returnAttrArray(attrValues, schemaDoc);
 112 
 113         String contents = DOMUtil.getAnnotation(annotationDecl);
 114         Element child = DOMUtil.getFirstChildElement(annotationDecl);
 115         if (child != null) {
 116             do {
 117                 String name = DOMUtil.getLocalName(child);
 118 
 119                 // the only valid children of "annotation" are
 120                 // "appinfo" and "documentation"
 121                 if (!((name.equals(SchemaSymbols.ELT_APPINFO)) ||
 122                         (name.equals(SchemaSymbols.ELT_DOCUMENTATION)))) {
 123                     reportSchemaError("src-annotation", new Object[]{name}, child);
 124                 }
 125                 else {
 126                     // General Attribute Checking
 127                     // There is no difference between global or local appinfo/documentation,
 128                     // so we assume it's always global.
 129                     attrValues = fAttrChecker.checkAttributes(child, true, schemaDoc);
 130                     fAttrChecker.returnAttrArray(attrValues, schemaDoc);
 131                 }
 132 
 133                 child = DOMUtil.getNextSiblingElement(child);
 134             }
 135             while (child != null);
 136         }
 137         // if contents was null, must have been some kind of error;
 138         // nothing to contribute to PSVI
 139         if (contents == null) return null;
 140 
 141         // find the grammar; fSchemaHandler must be known!
 142         SchemaGrammar grammar = fSchemaHandler.getGrammar(schemaDoc.fTargetNamespace);
 143         // fish out local attributes passed from parent
 144         Vector annotationLocalAttrs = (Vector)parentAttrs[XSAttributeChecker.ATTIDX_NONSCHEMA];
 145         // optimize for case where there are no local attributes
 146         if(annotationLocalAttrs != null && !annotationLocalAttrs.isEmpty()) {
 147             StringBuffer localStrBuffer = new StringBuffer(64);
 148             localStrBuffer.append(" ");
 149             // Vector should contain rawname value pairs
 150             int i = 0;
 151             while (i < annotationLocalAttrs.size()) {
 152                 String rawname = (String)annotationLocalAttrs.elementAt(i++);
 153                 int colonIndex = rawname.indexOf(':');
 154                 String prefix, localpart;
 155                 if (colonIndex == -1) {
 156                     prefix = "";
 157                     localpart = rawname;
 158                 }
 159                 else {
 160                     prefix = rawname.substring(0,colonIndex);
 161                     localpart = rawname.substring(colonIndex+1);
 162                 }
 163                 String uri = schemaDoc.fNamespaceSupport.getURI(fSymbolTable.addSymbol(prefix));
 164                 if (annotationDecl.getAttributeNS(uri, localpart).length() != 0) {
 165                     i++; // skip the next value, too
 166                     continue;
 167                 }
 168                 localStrBuffer.append(rawname)
 169                 .append("=\"");
 170                 String value = (String)annotationLocalAttrs.elementAt(i++);
 171                 // search for pesky "s and <s within attr value:
 172                 value = processAttValue(value);
 173                 localStrBuffer.append(value)
 174                 .append("\" ");
 175             }
 176             // and now splice it into place; immediately after the annotation token, for simplicity's sake
 177             StringBuffer contentBuffer = new StringBuffer(contents.length() + localStrBuffer.length());
 178             int annotationTokenEnd = contents.indexOf(SchemaSymbols.ELT_ANNOTATION);
 179             // annotation must occur somewhere or we're in big trouble...
 180             if(annotationTokenEnd == -1) return null;
 181             annotationTokenEnd += SchemaSymbols.ELT_ANNOTATION.length();
 182             contentBuffer.append(contents.substring(0,annotationTokenEnd));
 183             contentBuffer.append(localStrBuffer.toString());
 184             contentBuffer.append(contents.substring(annotationTokenEnd, contents.length()));
 185             final String annotation = contentBuffer.toString();
 186             if (fValidateAnnotations) {
 187                 schemaDoc.addAnnotation(new XSAnnotationInfo(annotation, annotationDecl));
 188             }
 189             return new XSAnnotationImpl(annotation, grammar);
 190         } else {
 191             if (fValidateAnnotations) {
 192                 schemaDoc.addAnnotation(new XSAnnotationInfo(contents, annotationDecl));
 193             }
 194             return new XSAnnotationImpl(contents, grammar);
 195         }
 196 
 197     }
 198 
 199     XSAnnotationImpl traverseSyntheticAnnotation(Element annotationParent, String initialContent,
 200             Object[] parentAttrs, boolean isGlobal, XSDocumentInfo schemaDoc) {
 201 
 202         String contents = initialContent;
 203 
 204         // find the grammar; fSchemaHandler must be known!
 205         SchemaGrammar grammar = fSchemaHandler.getGrammar(schemaDoc.fTargetNamespace);
 206         // fish out local attributes passed from parent
 207         Vector annotationLocalAttrs = (Vector)parentAttrs[XSAttributeChecker.ATTIDX_NONSCHEMA];
 208         // optimize for case where there are no local attributes
 209         if (annotationLocalAttrs != null && !annotationLocalAttrs.isEmpty()) {
 210             StringBuffer localStrBuffer = new StringBuffer(64);
 211             localStrBuffer.append(" ");
 212             // Vector should contain rawname value pairs
 213             int i = 0;
 214             while (i < annotationLocalAttrs.size()) {
 215                 String rawname = (String)annotationLocalAttrs.elementAt(i++);
 216                 int colonIndex = rawname.indexOf(':');
 217                 String prefix, localpart;
 218                 if (colonIndex == -1) {
 219                     prefix = "";
 220                     localpart = rawname;
 221                 }
 222                 else {
 223                     prefix = rawname.substring(0,colonIndex);
 224                     localpart = rawname.substring(colonIndex+1);
 225                 }
 226                 String uri = schemaDoc.fNamespaceSupport.getURI(fSymbolTable.addSymbol(prefix));
 227                 localStrBuffer.append(rawname)
 228                 .append("=\"");
 229                 String value = (String)annotationLocalAttrs.elementAt(i++);
 230                 // search for pesky "s and <s within attr value:
 231                 value = processAttValue(value);
 232                 localStrBuffer.append(value)
 233                 .append("\" ");
 234             }
 235             // and now splice it into place; immediately after the annotation token, for simplicity's sake
 236             StringBuffer contentBuffer = new StringBuffer(contents.length() + localStrBuffer.length());
 237             int annotationTokenEnd = contents.indexOf(SchemaSymbols.ELT_ANNOTATION);
 238             // annotation must occur somewhere or we're in big trouble...
 239             if(annotationTokenEnd == -1) return null;
 240             annotationTokenEnd += SchemaSymbols.ELT_ANNOTATION.length();
 241             contentBuffer.append(contents.substring(0,annotationTokenEnd));
 242             contentBuffer.append(localStrBuffer.toString());
 243             contentBuffer.append(contents.substring(annotationTokenEnd, contents.length()));
 244             final String annotation = contentBuffer.toString();
 245             if (fValidateAnnotations) {
 246                 schemaDoc.addAnnotation(new XSAnnotationInfo(annotation, annotationParent));
 247             }
 248             return new XSAnnotationImpl(annotation, grammar);
 249         } else {
 250             if (fValidateAnnotations) {
 251                 schemaDoc.addAnnotation(new XSAnnotationInfo(contents, annotationParent));
 252             }
 253             return new XSAnnotationImpl(contents, grammar);
 254         }
 255     }
 256 
 257     // the QName simple type used to resolve qnames
 258     private static final XSSimpleType fQNameDV = (XSSimpleType)SchemaGrammar.SG_SchemaNS.getGlobalTypeDecl(SchemaSymbols.ATTVAL_QNAME);
 259     // Temp data structures to be re-used in traversing facets
 260     private StringBuffer fPattern = new StringBuffer();
 261     private final XSFacets xsFacets = new XSFacets();
 262 
 263     static final class FacetInfo {
 264 
 265         final XSFacets facetdata;
 266         final Element nodeAfterFacets;
 267         final short fPresentFacets;
 268         final short fFixedFacets;
 269 
 270         FacetInfo(XSFacets facets, Element nodeAfterFacets, short presentFacets, short fixedFacets) {
 271             facetdata = facets;
 272             this.nodeAfterFacets = nodeAfterFacets;
 273             fPresentFacets = presentFacets;
 274             fFixedFacets = fixedFacets;
 275         }
 276     }
 277 
 278     FacetInfo traverseFacets(Element content,
 279             XSSimpleType baseValidator,
 280             XSDocumentInfo schemaDoc) {
 281 
 282         short facetsPresent = 0 ;
 283         short facetsFixed = 0; // facets that have fixed="true"
 284         String facet;
 285         boolean hasQName = containsQName(baseValidator);
 286         Vector enumData = null;
 287         XSObjectListImpl enumAnnotations = null;
 288         XSObjectListImpl patternAnnotations = null;
 289         Vector enumNSDecls = hasQName ? new Vector() : null;
 290         int currentFacet = 0;
 291         xsFacets.reset();
 292         while (content != null) {
 293             // General Attribute Checking
 294             Object[] attrs = null;
 295             facet = DOMUtil.getLocalName(content);
 296             if (facet.equals(SchemaSymbols.ELT_ENUMERATION)) {
 297                 attrs = fAttrChecker.checkAttributes(content, false, schemaDoc, hasQName);
 298                 String enumVal = (String)attrs[XSAttributeChecker.ATTIDX_VALUE];
 299                 // The facet can't be used if the value is missing. Ignore
 300                 // this facet element.
 301                 if (enumVal == null) {
 302                     reportSchemaError("s4s-att-must-appear", new Object[]{SchemaSymbols.ELT_ENUMERATION, SchemaSymbols.ATT_VALUE}, content);
 303                     fAttrChecker.returnAttrArray (attrs, schemaDoc);
 304                     content = DOMUtil.getNextSiblingElement(content);
 305                     continue;
 306                 }
 307 
 308                 NamespaceSupport nsDecls = (NamespaceSupport)attrs[XSAttributeChecker.ATTIDX_ENUMNSDECLS];
 309 
 310                 // for NOTATION types, need to check whether there is a notation
 311                 // declared with the same name as the enumeration value.
 312                 if (baseValidator.getVariety() == XSSimpleType.VARIETY_ATOMIC &&
 313                         baseValidator.getPrimitiveKind() == XSSimpleType.PRIMITIVE_NOTATION) {
 314                     // need to use the namespace context returned from checkAttributes
 315                     schemaDoc.fValidationContext.setNamespaceSupport(nsDecls);
 316                     Object notation = null;
 317                     try{
 318                         QName temp = (QName)fQNameDV.validate(enumVal, schemaDoc.fValidationContext, null);
 319                         // try to get the notation decl. if failed, getGlobalDecl
 320                         // reports an error, so we don't need to report one again.
 321                         notation = fSchemaHandler.getGlobalDecl(schemaDoc, XSDHandler.NOTATION_TYPE, temp, content);
 322                     }catch(InvalidDatatypeValueException ex){
 323                         reportSchemaError(ex.getKey(), ex.getArgs(), content);
 324                     }
 325                     if (notation == null) {
 326                         // Either the QName value is invalid, or it doens't
 327                         // resolve to a notation declaration.
 328                         // Ignore this facet, to avoid instance validation problems
 329                         fAttrChecker.returnAttrArray (attrs, schemaDoc);
 330                         content = DOMUtil.getNextSiblingElement(content);
 331                         continue;
 332                     }
 333                     // restore to the normal namespace context
 334                     schemaDoc.fValidationContext.setNamespaceSupport(schemaDoc.fNamespaceSupport);
 335                 }
 336                 if (enumData == null){
 337                     enumData = new Vector();
 338                     enumAnnotations = new XSObjectListImpl();
 339                 }
 340                 enumData.addElement(enumVal);
 341                 enumAnnotations.addXSObject(null);
 342                 if (hasQName)
 343                     enumNSDecls.addElement(nsDecls);
 344                 Element child = DOMUtil.getFirstChildElement( content );
 345 
 346                 if (child != null &&
 347                     DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION)) {
 348                     // traverse annotation if any
 349                     enumAnnotations.addXSObject(enumAnnotations.getLength()-1,traverseAnnotationDecl(child, attrs, false, schemaDoc));
 350                     child = DOMUtil.getNextSiblingElement(child);
 351                 }
 352                 else {
 353                     String text = DOMUtil.getSyntheticAnnotation(content);
 354                     if (text != null) {
 355                         enumAnnotations.addXSObject(enumAnnotations.getLength()-1, traverseSyntheticAnnotation(content, text, attrs, false, schemaDoc));
 356                     }
 357                 }
 358                 if (child !=null) {
 359                     reportSchemaError("s4s-elt-must-match.1", new Object[]{"enumeration", "(annotation?)", DOMUtil.getLocalName(child)}, child);
 360                 }
 361             }
 362             else if (facet.equals(SchemaSymbols.ELT_PATTERN)) {
 363                 facetsPresent |= XSSimpleType.FACET_PATTERN;
 364                 attrs = fAttrChecker.checkAttributes(content, false, schemaDoc);
 365                 String patternVal = (String)attrs[XSAttributeChecker.ATTIDX_VALUE];
 366                 // The facet can't be used if the value is missing. Ignore
 367                 // this facet element.
 368                 if (patternVal == null) {
 369                     reportSchemaError("s4s-att-must-appear", new Object[]{SchemaSymbols.ELT_PATTERN, SchemaSymbols.ATT_VALUE}, content);
 370                     fAttrChecker.returnAttrArray (attrs, schemaDoc);
 371                     content = DOMUtil.getNextSiblingElement(content);
 372                     continue;
 373                 }
 374 
 375                 if (fPattern.length() == 0) {
 376                     fPattern.append(patternVal);
 377                 } else {
 378                     // ---------------------------------------------
 379                     //datatypes: 5.2.4 pattern: src-multiple-pattern
 380                     // ---------------------------------------------
 381                     fPattern.append("|");
 382                     fPattern.append(patternVal);
 383                 }
 384                 Element child = DOMUtil.getFirstChildElement( content );
 385                 if (child != null &&
 386                         DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION)) {
 387                     // traverse annotation if any
 388                     if (patternAnnotations == null){
 389                         patternAnnotations = new XSObjectListImpl();
 390                     }
 391                     patternAnnotations.addXSObject(traverseAnnotationDecl(child, attrs, false, schemaDoc));
 392                     child = DOMUtil.getNextSiblingElement(child);
 393                 }
 394                 else {
 395                     String text = DOMUtil.getSyntheticAnnotation(content);
 396                     if (text != null) {
 397                         if (patternAnnotations == null){
 398                             patternAnnotations = new XSObjectListImpl();
 399                         }
 400                         patternAnnotations.addXSObject(traverseSyntheticAnnotation(content, text, attrs, false, schemaDoc));
 401                     }
 402                 }
 403                 if (child !=null) {
 404                     reportSchemaError("s4s-elt-must-match.1", new Object[]{"pattern", "(annotation?)", DOMUtil.getLocalName(child)}, child);
 405                 }
 406             }
 407             else {
 408                 if (facet.equals(SchemaSymbols.ELT_MINLENGTH)) {
 409                     currentFacet = XSSimpleType.FACET_MINLENGTH;
 410                 }
 411                 else if (facet.equals(SchemaSymbols.ELT_MAXLENGTH)) {
 412                     currentFacet = XSSimpleType.FACET_MAXLENGTH;
 413                 }
 414                 else if (facet.equals(SchemaSymbols.ELT_MAXEXCLUSIVE)) {
 415                     currentFacet = XSSimpleType.FACET_MAXEXCLUSIVE;
 416                 }
 417                 else if (facet.equals(SchemaSymbols.ELT_MAXINCLUSIVE)) {
 418                     currentFacet = XSSimpleType.FACET_MAXINCLUSIVE;
 419                 }
 420                 else if (facet.equals(SchemaSymbols.ELT_MINEXCLUSIVE)) {
 421                     currentFacet = XSSimpleType.FACET_MINEXCLUSIVE;
 422                 }
 423                 else if (facet.equals(SchemaSymbols.ELT_MININCLUSIVE)) {
 424                     currentFacet = XSSimpleType.FACET_MININCLUSIVE;
 425                 }
 426                 else if (facet.equals(SchemaSymbols.ELT_TOTALDIGITS)) {
 427                     currentFacet = XSSimpleType.FACET_TOTALDIGITS;
 428                 }
 429                 else if (facet.equals(SchemaSymbols.ELT_FRACTIONDIGITS)) {
 430                     currentFacet = XSSimpleType.FACET_FRACTIONDIGITS;
 431                 }
 432                 else if (facet.equals(SchemaSymbols.ELT_WHITESPACE)) {
 433                     currentFacet = XSSimpleType.FACET_WHITESPACE;
 434                 }
 435                 else if (facet.equals(SchemaSymbols.ELT_LENGTH)) {
 436                     currentFacet = XSSimpleType.FACET_LENGTH;
 437                 }
 438                 else {
 439                     break;   // a non-facet
 440                 }
 441 
 442                 attrs = fAttrChecker.checkAttributes(content, false, schemaDoc);
 443 
 444                 // check for duplicate facets
 445                 if ((facetsPresent & currentFacet) != 0) {
 446                     // Ignore this facet, to avoid corrupting the previous facet
 447                     reportSchemaError("src-single-facet-value", new Object[]{facet}, content);
 448                     fAttrChecker.returnAttrArray (attrs, schemaDoc);
 449                     content = DOMUtil.getNextSiblingElement(content);
 450                     continue;
 451                 }
 452 
 453                 // The facet can't be used if the value is missing. Ignore
 454                 // this facet element.
 455                 if (attrs[XSAttributeChecker.ATTIDX_VALUE] == null) {
 456                     // Report an error if the "value" attribute is missing.
 457                     // If it's not missing, then its value is invalid, and an
 458                     // error should have already been reported by the
 459                     // attribute checker.
 460                     if (content.getAttributeNodeNS(null, "value") == null) {
 461                         reportSchemaError("s4s-att-must-appear", new Object[]{content.getLocalName(), SchemaSymbols.ATT_VALUE}, content);
 462                     }
 463                     fAttrChecker.returnAttrArray (attrs, schemaDoc);
 464                     content = DOMUtil.getNextSiblingElement(content);
 465                     continue;
 466                 }
 467 
 468                 facetsPresent |= currentFacet;
 469                 // check for fixed facet
 470                 if (((Boolean)attrs[XSAttributeChecker.ATTIDX_FIXED]).booleanValue()) {
 471                     facetsFixed |= currentFacet;
 472                 }
 473                 switch (currentFacet) {
 474                 case XSSimpleType.FACET_MINLENGTH:
 475                     xsFacets.minLength = ((XInt)attrs[XSAttributeChecker.ATTIDX_VALUE]).intValue();
 476                     break;
 477                 case XSSimpleType.FACET_MAXLENGTH:
 478                     xsFacets.maxLength = ((XInt)attrs[XSAttributeChecker.ATTIDX_VALUE]).intValue();
 479                     break;
 480                 case XSSimpleType.FACET_MAXEXCLUSIVE:
 481                     xsFacets.maxExclusive = (String)attrs[XSAttributeChecker.ATTIDX_VALUE];
 482                     break;
 483                 case XSSimpleType.FACET_MAXINCLUSIVE:
 484                     xsFacets.maxInclusive = (String)attrs[XSAttributeChecker.ATTIDX_VALUE];
 485                     break;
 486                 case XSSimpleType.FACET_MINEXCLUSIVE:
 487                     xsFacets.minExclusive = (String)attrs[XSAttributeChecker.ATTIDX_VALUE];
 488                     break;
 489                 case XSSimpleType.FACET_MININCLUSIVE:
 490                     xsFacets.minInclusive = (String)attrs[XSAttributeChecker.ATTIDX_VALUE];
 491                     break;
 492                 case XSSimpleType.FACET_TOTALDIGITS:
 493                     xsFacets.totalDigits = ((XInt)attrs[XSAttributeChecker.ATTIDX_VALUE]).intValue();
 494                     break;
 495                 case XSSimpleType.FACET_FRACTIONDIGITS:
 496                     xsFacets.fractionDigits = ((XInt)attrs[XSAttributeChecker.ATTIDX_VALUE]).intValue();
 497                     break;
 498                 case XSSimpleType.FACET_WHITESPACE:
 499                     xsFacets.whiteSpace = ((XInt)attrs[XSAttributeChecker.ATTIDX_VALUE]).shortValue();
 500                     break;
 501                 case XSSimpleType.FACET_LENGTH:
 502                     xsFacets.length = ((XInt)attrs[XSAttributeChecker.ATTIDX_VALUE]).intValue();
 503                     break;
 504                 }
 505 
 506                 Element child = DOMUtil.getFirstChildElement( content );
 507                 XSAnnotationImpl annotation = null;
 508                 if (child != null &&
 509                     DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION)) {
 510                     // traverse annotation if any
 511                     annotation = traverseAnnotationDecl(child, attrs, false, schemaDoc);
 512                     child = DOMUtil.getNextSiblingElement(child);
 513                 }
 514                 else {
 515                     String text = DOMUtil.getSyntheticAnnotation(content);
 516                     if (text != null) {
 517                         annotation = traverseSyntheticAnnotation(content, text, attrs, false, schemaDoc);
 518                     }
 519                }
 520                 switch (currentFacet) {
 521                 case XSSimpleType.FACET_MINLENGTH:
 522                     xsFacets.minLengthAnnotation = annotation;
 523                 break;
 524                 case XSSimpleType.FACET_MAXLENGTH:
 525                     xsFacets.maxLengthAnnotation = annotation;
 526                 break;
 527                 case XSSimpleType.FACET_MAXEXCLUSIVE:
 528                     xsFacets.maxExclusiveAnnotation = annotation;
 529                 break;
 530                 case XSSimpleType.FACET_MAXINCLUSIVE:
 531                     xsFacets.maxInclusiveAnnotation = annotation;
 532                 break;
 533                 case XSSimpleType.FACET_MINEXCLUSIVE:
 534                     xsFacets.minExclusiveAnnotation = annotation;
 535                 break;
 536                 case XSSimpleType.FACET_MININCLUSIVE:
 537                     xsFacets.minInclusiveAnnotation = annotation;
 538                 break;
 539                 case XSSimpleType.FACET_TOTALDIGITS:
 540                     xsFacets.totalDigitsAnnotation = annotation;
 541                 break;
 542                 case XSSimpleType.FACET_FRACTIONDIGITS:
 543                     xsFacets.fractionDigitsAnnotation = annotation;
 544                 break;
 545                 case XSSimpleType.FACET_WHITESPACE:
 546                     xsFacets.whiteSpaceAnnotation = annotation;
 547                 break;
 548                 case XSSimpleType.FACET_LENGTH:
 549                     xsFacets.lengthAnnotation = annotation;
 550                 break;
 551                 }
 552                 if (child != null) {
 553                     reportSchemaError("s4s-elt-must-match.1", new Object[]{facet, "(annotation?)", DOMUtil.getLocalName(child)}, child);
 554                 }
 555             }
 556             fAttrChecker.returnAttrArray (attrs, schemaDoc);
 557             content = DOMUtil.getNextSiblingElement(content);
 558         }
 559         if (enumData !=null) {
 560             facetsPresent |= XSSimpleType.FACET_ENUMERATION;
 561             xsFacets.enumeration = enumData;
 562             xsFacets.enumNSDecls = enumNSDecls;
 563             xsFacets.enumAnnotations = enumAnnotations;
 564         }
 565         if ((facetsPresent & XSSimpleType.FACET_PATTERN) != 0) {
 566             xsFacets.pattern = fPattern.toString();
 567             xsFacets.patternAnnotations = patternAnnotations;
 568         }
 569 
 570         fPattern.setLength(0);
 571 
 572         return new FacetInfo(xsFacets, content, facetsPresent, facetsFixed);
 573     }
 574 
 575 
 576     // return whether QName/NOTATION is part of the given type
 577     private boolean containsQName(XSSimpleType type) {
 578         if (type.getVariety() == XSSimpleType.VARIETY_ATOMIC) {
 579             short primitive = type.getPrimitiveKind();
 580             return (primitive == XSSimpleType.PRIMITIVE_QNAME ||
 581                     primitive == XSSimpleType.PRIMITIVE_NOTATION);
 582         }
 583         else if (type.getVariety() == XSSimpleType.VARIETY_LIST) {
 584             return containsQName((XSSimpleType)type.getItemType());
 585         }
 586         else if (type.getVariety() == XSSimpleType.VARIETY_UNION) {
 587             XSObjectList members = type.getMemberTypes();
 588             for (int i = 0; i < members.getLength(); i++) {
 589                 if (containsQName((XSSimpleType)members.item(i)))
 590                     return true;
 591             }
 592         }
 593         return false;
 594     }
 595 
 596     //
 597     // Traverse a set of attribute and attribute group elements
 598     // Needed by complexType and attributeGroup traversal
 599     // This method will return the first non-attribute/attrgrp found
 600     //
 601     Element traverseAttrsAndAttrGrps(Element firstAttr, XSAttributeGroupDecl attrGrp,
 602             XSDocumentInfo schemaDoc, SchemaGrammar grammar,
 603             XSComplexTypeDecl enclosingCT) {
 604 
 605         Element child=null;
 606         XSAttributeGroupDecl tempAttrGrp = null;
 607         XSAttributeUseImpl tempAttrUse = null;
 608         XSAttributeUse otherUse = null;
 609         String childName;
 610 
 611         for (child=firstAttr; child!=null; child=DOMUtil.getNextSiblingElement(child)) {
 612             childName = DOMUtil.getLocalName(child);
 613             if (childName.equals(SchemaSymbols.ELT_ATTRIBUTE)) {
 614                 tempAttrUse = fSchemaHandler.fAttributeTraverser.traverseLocal(child,
 615                         schemaDoc,
 616                         grammar,
 617                         enclosingCT);
 618                 if (tempAttrUse == null) continue;
 619                 if (tempAttrUse.fUse == SchemaSymbols.USE_PROHIBITED) {
 620                     attrGrp.addAttributeUse(tempAttrUse);
 621                     continue;
 622                 }
 623                 otherUse = attrGrp.getAttributeUseNoProhibited(
 624                         tempAttrUse.fAttrDecl.getNamespace(),
 625                         tempAttrUse.fAttrDecl.getName());
 626                 if (otherUse==null) {
 627                     String idName = attrGrp.addAttributeUse(tempAttrUse);
 628                     if (idName != null) {
 629                         String code = (enclosingCT == null) ? "ag-props-correct.3" : "ct-props-correct.5";
 630                         String name = (enclosingCT == null) ? attrGrp.fName : enclosingCT.getName();
 631                         reportSchemaError(code, new Object[]{name, tempAttrUse.fAttrDecl.getName(), idName}, child);
 632                     }
 633                 }
 634                 else if (otherUse != tempAttrUse) {
 635                     String code = (enclosingCT == null) ? "ag-props-correct.2" : "ct-props-correct.4";
 636                     String name = (enclosingCT == null) ? attrGrp.fName : enclosingCT.getName();
 637                     reportSchemaError(code, new Object[]{name, tempAttrUse.fAttrDecl.getName()}, child);
 638                 }
 639             }
 640             else if (childName.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) {
 641                 //REVISIT: do we need to save some state at this point??
 642                 tempAttrGrp = fSchemaHandler.fAttributeGroupTraverser.traverseLocal(
 643                         child, schemaDoc, grammar);
 644                 if(tempAttrGrp == null ) continue;
 645                 XSObjectList attrUseS = tempAttrGrp.getAttributeUses();
 646                 XSAttributeUseImpl oneAttrUse;
 647                 int attrCount = attrUseS.getLength();
 648                 for (int i=0; i<attrCount; i++) {
 649                     oneAttrUse = (XSAttributeUseImpl)attrUseS.item(i);
 650                     if (oneAttrUse.fUse == SchemaSymbols.USE_PROHIBITED) {
 651                         attrGrp.addAttributeUse(oneAttrUse);
 652                         continue;
 653                     }
 654                     otherUse = attrGrp.getAttributeUseNoProhibited(
 655                             oneAttrUse.fAttrDecl.getNamespace(),
 656                             oneAttrUse.fAttrDecl.getName());
 657                     if (otherUse==null) {
 658                         String idName = attrGrp.addAttributeUse(oneAttrUse);
 659                         if (idName != null) {
 660                             String code = (enclosingCT == null) ? "ag-props-correct.3" : "ct-props-correct.5";
 661                             String name = (enclosingCT == null) ? attrGrp.fName : enclosingCT.getName();
 662                             reportSchemaError(code, new Object[]{name, oneAttrUse.fAttrDecl.getName(), idName}, child);
 663                         }
 664                     }
 665                     else if (oneAttrUse != otherUse) {
 666                         String code = (enclosingCT == null) ? "ag-props-correct.2" : "ct-props-correct.4";
 667                         String name = (enclosingCT == null) ? attrGrp.fName : enclosingCT.getName();
 668                         reportSchemaError(code, new Object[]{name, oneAttrUse.fAttrDecl.getName()}, child);
 669                     }
 670                 }
 671 
 672                 if (tempAttrGrp.fAttributeWC != null) {
 673                     if (attrGrp.fAttributeWC == null) {
 674                         attrGrp.fAttributeWC = tempAttrGrp.fAttributeWC;
 675                     }
 676                     // perform intersection of attribute wildcard
 677                     else {
 678                         attrGrp.fAttributeWC = attrGrp.fAttributeWC.
 679                         performIntersectionWith(tempAttrGrp.fAttributeWC, attrGrp.fAttributeWC.fProcessContents);
 680                         if (attrGrp.fAttributeWC == null) {
 681                             String code = (enclosingCT == null) ? "src-attribute_group.2" : "src-ct.4";
 682                             String name = (enclosingCT == null) ? attrGrp.fName : enclosingCT.getName();
 683                             reportSchemaError(code, new Object[]{name}, child);
 684                         }
 685                     }
 686                 }
 687             }
 688             else
 689                 break;
 690         } // for
 691 
 692         if (child != null) {
 693             childName = DOMUtil.getLocalName(child);
 694             if (childName.equals(SchemaSymbols.ELT_ANYATTRIBUTE)) {
 695                 XSWildcardDecl tempAttrWC = fSchemaHandler.fWildCardTraverser.
 696                 traverseAnyAttribute(child, schemaDoc, grammar);
 697                 if (attrGrp.fAttributeWC == null) {
 698                     attrGrp.fAttributeWC = tempAttrWC;
 699                 }
 700                 // perform intersection of attribute wildcard
 701                 else {
 702                     attrGrp.fAttributeWC = tempAttrWC.
 703                     performIntersectionWith(attrGrp.fAttributeWC, tempAttrWC.fProcessContents);
 704                     if (attrGrp.fAttributeWC == null) {
 705                         String code = (enclosingCT == null) ? "src-attribute_group.2" : "src-ct.4";
 706                         String name = (enclosingCT == null) ? attrGrp.fName : enclosingCT.getName();
 707                         reportSchemaError(code, new Object[]{name}, child);
 708                     }
 709                 }
 710                 child = DOMUtil.getNextSiblingElement(child);
 711             }
 712         }
 713 
 714         // Success
 715         return child;
 716 
 717     }
 718 
 719     void reportSchemaError (String key, Object[] args, Element ele) {
 720         fSchemaHandler.reportSchemaError(key, args, ele);
 721     }
 722 
 723     /**
 724      * Element/Attribute traversers call this method to check whether
 725      * the type is NOTATION without enumeration facet
 726      */
 727     void checkNotationType(String refName, XSTypeDefinition typeDecl, Element elem) {
 728         if (typeDecl.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE &&
 729                 ((XSSimpleType)typeDecl).getVariety() == XSSimpleType.VARIETY_ATOMIC &&
 730                 ((XSSimpleType)typeDecl).getPrimitiveKind() == XSSimpleType.PRIMITIVE_NOTATION) {
 731             if ((((XSSimpleType)typeDecl).getDefinedFacets() & XSSimpleType.FACET_ENUMERATION) == 0) {
 732                 reportSchemaError("enumeration-required-notation", new Object[]{typeDecl.getName(), refName, DOMUtil.getLocalName(elem)}, elem);
 733             }
 734         }
 735     }
 736 
 737     // Checks constraints for minOccurs, maxOccurs
 738     protected XSParticleDecl checkOccurrences(XSParticleDecl particle,
 739             String particleName, Element parent,
 740             int allContextFlags,
 741             long defaultVals) {
 742 
 743         int min = particle.fMinOccurs;
 744         int max = particle.fMaxOccurs;
 745         boolean defaultMin = (defaultVals & (1 << XSAttributeChecker.ATTIDX_MINOCCURS)) != 0;
 746         boolean defaultMax = (defaultVals & (1 << XSAttributeChecker.ATTIDX_MAXOCCURS)) != 0;
 747 
 748         boolean processingAllEl = ((allContextFlags & PROCESSING_ALL_EL) != 0);
 749         boolean processingAllGP = ((allContextFlags & PROCESSING_ALL_GP) != 0);
 750         boolean groupRefWithAll = ((allContextFlags & GROUP_REF_WITH_ALL) != 0);
 751         boolean isGroupChild    = ((allContextFlags & CHILD_OF_GROUP) != 0);
 752 
 753         // Neither minOccurs nor maxOccurs may be specified
 754         // for the child of a model group definition.
 755         if (isGroupChild) {
 756             if (!defaultMin) {
 757                 Object[] args = new Object[]{particleName, "minOccurs"};
 758                 reportSchemaError("s4s-att-not-allowed", args, parent);
 759                 min = 1;
 760             }
 761             if (!defaultMax) {
 762                 Object[] args = new Object[]{particleName, "maxOccurs"};
 763                 reportSchemaError("s4s-att-not-allowed", args, parent);
 764                 max = 1;
 765             }
 766         }
 767 
 768         // If minOccurs=maxOccurs=0, no component is specified
 769         if (min == 0 && max== 0) {
 770             particle.fType = XSParticleDecl.PARTICLE_EMPTY;
 771             return null;
 772         }
 773 
 774         // For the elements referenced in an <all>, minOccurs attribute
 775         // must be zero or one, and maxOccurs attribute must be one.
 776         // For a complex type definition that contains an <all> or a
 777         // reference a <group> whose model group is an all model group,
 778         // minOccurs and maxOccurs must be one.
 779         if (processingAllEl) {
 780             if (max != 1) {
 781                 reportSchemaError("cos-all-limited.2", new Object[]{
 782                         (max == SchemaSymbols.OCCURRENCE_UNBOUNDED) ? SchemaSymbols.ATTVAL_UNBOUNDED : Integer.toString(max),
 783                         ((XSElementDecl)particle.fValue).getName()}, parent);
 784                 max = 1;
 785                 if (min > 1)
 786                     min = 1;
 787             }
 788         }
 789         else if (processingAllGP || groupRefWithAll) {
 790             if (max != 1) {
 791                 reportSchemaError("cos-all-limited.1.2", null, parent);
 792                 if (min > 1)
 793                     min = 1;
 794                 max = 1;
 795             }
 796         }
 797 
 798         particle.fMinOccurs = min;
 799         particle.fMaxOccurs = max;
 800 
 801         return particle;
 802     }
 803 
 804     private static String processAttValue(String original) {
 805         final int length = original.length();
 806         // normally, nothing will happen
 807         for (int i = 0; i < length; ++i) {
 808             char currChar = original.charAt(i);
 809             if (currChar == '"' || currChar == '<' || currChar == '&' ||
 810                     currChar == 0x09 || currChar == 0x0A || currChar == 0x0D) {
 811                 return escapeAttValue(original, i);
 812             }
 813         }
 814         return original;
 815     }
 816 
 817     // this is not terribly performant!
 818     private static String escapeAttValue(String original, int from) {
 819         int i;
 820         final int length = original.length();
 821         StringBuffer newVal = new StringBuffer(length);
 822         newVal.append(original.substring(0, from));
 823         for (i = from; i < length; ++i) {
 824             char currChar = original.charAt(i);
 825             if (currChar == '"') {
 826                 newVal.append("&quot;");
 827             }
 828             else if (currChar == '<') {
 829                 newVal.append("&lt;");
 830             }
 831             else if (currChar == '&') {
 832                 newVal.append("&amp;");
 833             }
 834             // Must escape 0x09, 0x0A and 0x0D if they appear in attribute
 835             // value so that they may be round-tripped. They would otherwise
 836             // be transformed to a 0x20 during attribute value normalization.
 837             else if (currChar == 0x09) {
 838                 newVal.append("&#x9;");
 839             }
 840             else if (currChar == 0x0A) {
 841                 newVal.append("&#xA;");
 842             }
 843             else if (currChar == 0x0D) {
 844                 newVal.append("&#xD;");
 845             }
 846             else {
 847                 newVal.append(currChar);
 848             }
 849         }
 850         return newVal.toString();
 851     }
 852 }