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