src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDAbstractTraverser.java
changeset 47216 71c04702a3d5
parent 44797 8b3b3b911b8a
child 47359 e1a6c0168741
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDAbstractTraverser.java	Tue Sep 12 19:03:39 2017 +0200
@@ -0,0 +1,853 @@
+/*
+ * reserved comment block
+ * DO NOT REMOVE OR ALTER!
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.sun.org.apache.xerces.internal.impl.xs.traversers;
+
+import java.util.Locale;
+import java.util.Vector;
+
+import com.sun.org.apache.xerces.internal.impl.dv.InvalidDatatypeValueException;
+import com.sun.org.apache.xerces.internal.impl.dv.XSFacets;
+import com.sun.org.apache.xerces.internal.impl.dv.XSSimpleType;
+import com.sun.org.apache.xerces.internal.impl.validation.ValidationState;
+import com.sun.org.apache.xerces.internal.impl.xs.SchemaGrammar;
+import com.sun.org.apache.xerces.internal.impl.xs.SchemaSymbols;
+import com.sun.org.apache.xerces.internal.impl.xs.XSAnnotationImpl;
+import com.sun.org.apache.xerces.internal.impl.xs.XSAttributeGroupDecl;
+import com.sun.org.apache.xerces.internal.impl.xs.XSAttributeUseImpl;
+import com.sun.org.apache.xerces.internal.impl.xs.XSComplexTypeDecl;
+import com.sun.org.apache.xerces.internal.impl.xs.XSElementDecl;
+import com.sun.org.apache.xerces.internal.impl.xs.XSParticleDecl;
+import com.sun.org.apache.xerces.internal.impl.xs.XSWildcardDecl;
+import com.sun.org.apache.xerces.internal.impl.xs.util.XInt;
+import com.sun.org.apache.xerces.internal.impl.xs.util.XSObjectListImpl;
+import com.sun.org.apache.xerces.internal.util.DOMUtil;
+import com.sun.org.apache.xerces.internal.util.NamespaceSupport;
+import com.sun.org.apache.xerces.internal.util.SymbolTable;
+import com.sun.org.apache.xerces.internal.xni.QName;
+import com.sun.org.apache.xerces.internal.xs.XSAttributeUse;
+import com.sun.org.apache.xerces.internal.xs.XSObjectList;
+import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition;
+import org.w3c.dom.Element;
+
+/**
+ * Class <code>XSDAbstractTraverser</code> serves as the base class for all
+ * other <code>XSD???Traverser</code>s. It holds the common data and provide
+ * a unified way to initialize these data.
+ *
+ * @xerces.internal
+ *
+ * @author Elena Litani, IBM
+ * @author Rahul Srivastava, Sun Microsystems Inc.
+ * @author Neeraj Bajaj, Sun Microsystems Inc.
+ *
+ */
+abstract class XSDAbstractTraverser {
+
+    protected static final String NO_NAME      = "(no name)";
+
+    // Flags for checkOccurrences to indicate any special
+    // restrictions on minOccurs and maxOccurs relating to "all".
+    //    NOT_ALL_CONTEXT    - not processing an <all>
+    //    PROCESSING_ALL_EL  - processing an <element> in an <all>
+    //    GROUP_REF_WITH_ALL - processing <group> reference that contained <all>
+    //    CHILD_OF_GROUP     - processing a child of a model group definition
+    //    PROCESSING_ALL_GP  - processing an <all> group itself
+
+    protected static final int NOT_ALL_CONTEXT    = 0;
+    protected static final int PROCESSING_ALL_EL  = 1;
+    protected static final int GROUP_REF_WITH_ALL = 2;
+    protected static final int CHILD_OF_GROUP     = 4;
+    protected static final int PROCESSING_ALL_GP  = 8;
+
+    //Shared data
+    protected XSDHandler            fSchemaHandler = null;
+    protected SymbolTable           fSymbolTable = null;
+    protected XSAttributeChecker    fAttrChecker = null;
+    protected boolean               fValidateAnnotations = false;
+
+    // used to validate default/fixed attribute values
+    ValidationState fValidationState = new ValidationState();
+
+    XSDAbstractTraverser (XSDHandler handler,
+            XSAttributeChecker attrChecker) {
+        fSchemaHandler = handler;
+        fAttrChecker = attrChecker;
+    }
+
+    void reset(SymbolTable symbolTable, boolean validateAnnotations, Locale locale) {
+        fSymbolTable = symbolTable;
+        fValidateAnnotations = validateAnnotations;
+        fValidationState.setExtraChecking(false);
+        fValidationState.setSymbolTable(symbolTable);
+        fValidationState.setLocale(locale);
+    }
+
+    // traverse the annotation declaration
+    // REVISIT: how to pass the parentAttrs? as DOM attributes?
+    //          as name/value pairs (string)? in parsed form?
+    // @return XSAnnotationImpl object
+    XSAnnotationImpl traverseAnnotationDecl(Element annotationDecl, Object[] parentAttrs,
+            boolean isGlobal, XSDocumentInfo schemaDoc) {
+        // General Attribute Checking
+        Object[] attrValues = fAttrChecker.checkAttributes(annotationDecl, isGlobal, schemaDoc);
+        fAttrChecker.returnAttrArray(attrValues, schemaDoc);
+
+        String contents = DOMUtil.getAnnotation(annotationDecl);
+        Element child = DOMUtil.getFirstChildElement(annotationDecl);
+        if (child != null) {
+            do {
+                String name = DOMUtil.getLocalName(child);
+
+                // the only valid children of "annotation" are
+                // "appinfo" and "documentation"
+                if (!((name.equals(SchemaSymbols.ELT_APPINFO)) ||
+                        (name.equals(SchemaSymbols.ELT_DOCUMENTATION)))) {
+                    reportSchemaError("src-annotation", new Object[]{name}, child);
+                }
+                else {
+                    // General Attribute Checking
+                    // There is no difference between global or local appinfo/documentation,
+                    // so we assume it's always global.
+                    attrValues = fAttrChecker.checkAttributes(child, true, schemaDoc);
+                    fAttrChecker.returnAttrArray(attrValues, schemaDoc);
+                }
+
+                child = DOMUtil.getNextSiblingElement(child);
+            }
+            while (child != null);
+        }
+        // if contents was null, must have been some kind of error;
+        // nothing to contribute to PSVI
+        if (contents == null) return null;
+
+        // find the grammar; fSchemaHandler must be known!
+        SchemaGrammar grammar = fSchemaHandler.getGrammar(schemaDoc.fTargetNamespace);
+        // fish out local attributes passed from parent
+        Vector annotationLocalAttrs = (Vector)parentAttrs[XSAttributeChecker.ATTIDX_NONSCHEMA];
+        // optimize for case where there are no local attributes
+        if(annotationLocalAttrs != null && !annotationLocalAttrs.isEmpty()) {
+            StringBuffer localStrBuffer = new StringBuffer(64);
+            localStrBuffer.append(" ");
+            // Vector should contain rawname value pairs
+            int i = 0;
+            while (i < annotationLocalAttrs.size()) {
+                String rawname = (String)annotationLocalAttrs.elementAt(i++);
+                int colonIndex = rawname.indexOf(':');
+                String prefix, localpart;
+                if (colonIndex == -1) {
+                    prefix = "";
+                    localpart = rawname;
+                }
+                else {
+                    prefix = rawname.substring(0,colonIndex);
+                    localpart = rawname.substring(colonIndex+1);
+                }
+                String uri = schemaDoc.fNamespaceSupport.getURI(fSymbolTable.addSymbol(prefix));
+                if (annotationDecl.getAttributeNS(uri, localpart).length() != 0) {
+                    i++; // skip the next value, too
+                    continue;
+                }
+                localStrBuffer.append(rawname)
+                .append("=\"");
+                String value = (String)annotationLocalAttrs.elementAt(i++);
+                // search for pesky "s and <s within attr value:
+                value = processAttValue(value);
+                localStrBuffer.append(value)
+                .append("\" ");
+            }
+            // and now splice it into place; immediately after the annotation token, for simplicity's sake
+            StringBuffer contentBuffer = new StringBuffer(contents.length() + localStrBuffer.length());
+            int annotationTokenEnd = contents.indexOf(SchemaSymbols.ELT_ANNOTATION);
+            // annotation must occur somewhere or we're in big trouble...
+            if(annotationTokenEnd == -1) return null;
+            annotationTokenEnd += SchemaSymbols.ELT_ANNOTATION.length();
+            contentBuffer.append(contents.substring(0,annotationTokenEnd));
+            contentBuffer.append(localStrBuffer.toString());
+            contentBuffer.append(contents.substring(annotationTokenEnd, contents.length()));
+            final String annotation = contentBuffer.toString();
+            if (fValidateAnnotations) {
+                schemaDoc.addAnnotation(new XSAnnotationInfo(annotation, annotationDecl));
+            }
+            return new XSAnnotationImpl(annotation, grammar);
+        } else {
+            if (fValidateAnnotations) {
+                schemaDoc.addAnnotation(new XSAnnotationInfo(contents, annotationDecl));
+            }
+            return new XSAnnotationImpl(contents, grammar);
+        }
+
+    }
+
+    XSAnnotationImpl traverseSyntheticAnnotation(Element annotationParent, String initialContent,
+            Object[] parentAttrs, boolean isGlobal, XSDocumentInfo schemaDoc) {
+
+        String contents = initialContent;
+
+        // find the grammar; fSchemaHandler must be known!
+        SchemaGrammar grammar = fSchemaHandler.getGrammar(schemaDoc.fTargetNamespace);
+        // fish out local attributes passed from parent
+        Vector annotationLocalAttrs = (Vector)parentAttrs[XSAttributeChecker.ATTIDX_NONSCHEMA];
+        // optimize for case where there are no local attributes
+        if (annotationLocalAttrs != null && !annotationLocalAttrs.isEmpty()) {
+            StringBuffer localStrBuffer = new StringBuffer(64);
+            localStrBuffer.append(" ");
+            // Vector should contain rawname value pairs
+            int i = 0;
+            while (i < annotationLocalAttrs.size()) {
+                String rawname = (String)annotationLocalAttrs.elementAt(i++);
+                int colonIndex = rawname.indexOf(':');
+                String prefix, localpart;
+                if (colonIndex == -1) {
+                    prefix = "";
+                    localpart = rawname;
+                }
+                else {
+                    prefix = rawname.substring(0,colonIndex);
+                    localpart = rawname.substring(colonIndex+1);
+                }
+                String uri = schemaDoc.fNamespaceSupport.getURI(fSymbolTable.addSymbol(prefix));
+                localStrBuffer.append(rawname)
+                .append("=\"");
+                String value = (String)annotationLocalAttrs.elementAt(i++);
+                // search for pesky "s and <s within attr value:
+                value = processAttValue(value);
+                localStrBuffer.append(value)
+                .append("\" ");
+            }
+            // and now splice it into place; immediately after the annotation token, for simplicity's sake
+            StringBuffer contentBuffer = new StringBuffer(contents.length() + localStrBuffer.length());
+            int annotationTokenEnd = contents.indexOf(SchemaSymbols.ELT_ANNOTATION);
+            // annotation must occur somewhere or we're in big trouble...
+            if(annotationTokenEnd == -1) return null;
+            annotationTokenEnd += SchemaSymbols.ELT_ANNOTATION.length();
+            contentBuffer.append(contents.substring(0,annotationTokenEnd));
+            contentBuffer.append(localStrBuffer.toString());
+            contentBuffer.append(contents.substring(annotationTokenEnd, contents.length()));
+            final String annotation = contentBuffer.toString();
+            if (fValidateAnnotations) {
+                schemaDoc.addAnnotation(new XSAnnotationInfo(annotation, annotationParent));
+            }
+            return new XSAnnotationImpl(annotation, grammar);
+        } else {
+            if (fValidateAnnotations) {
+                schemaDoc.addAnnotation(new XSAnnotationInfo(contents, annotationParent));
+            }
+            return new XSAnnotationImpl(contents, grammar);
+        }
+    }
+
+    // the QName simple type used to resolve qnames
+    private static final XSSimpleType fQNameDV = (XSSimpleType)SchemaGrammar.SG_SchemaNS.getGlobalTypeDecl(SchemaSymbols.ATTVAL_QNAME);
+    // Temp data structures to be re-used in traversing facets
+    private StringBuffer fPattern = new StringBuffer();
+    private final XSFacets xsFacets = new XSFacets();
+
+    static final class FacetInfo {
+
+        final XSFacets facetdata;
+        final Element nodeAfterFacets;
+        final short fPresentFacets;
+        final short fFixedFacets;
+
+        FacetInfo(XSFacets facets, Element nodeAfterFacets, short presentFacets, short fixedFacets) {
+            facetdata = facets;
+            this.nodeAfterFacets = nodeAfterFacets;
+            fPresentFacets = presentFacets;
+            fFixedFacets = fixedFacets;
+        }
+    }
+
+    FacetInfo traverseFacets(Element content,
+            XSSimpleType baseValidator,
+            XSDocumentInfo schemaDoc) {
+
+        short facetsPresent = 0 ;
+        short facetsFixed = 0; // facets that have fixed="true"
+        String facet;
+        boolean hasQName = containsQName(baseValidator);
+        Vector enumData = null;
+        XSObjectListImpl enumAnnotations = null;
+        XSObjectListImpl patternAnnotations = null;
+        Vector enumNSDecls = hasQName ? new Vector() : null;
+        int currentFacet = 0;
+        xsFacets.reset();
+        while (content != null) {
+            // General Attribute Checking
+            Object[] attrs = null;
+            facet = DOMUtil.getLocalName(content);
+            if (facet.equals(SchemaSymbols.ELT_ENUMERATION)) {
+                attrs = fAttrChecker.checkAttributes(content, false, schemaDoc, hasQName);
+                String enumVal = (String)attrs[XSAttributeChecker.ATTIDX_VALUE];
+                // The facet can't be used if the value is missing. Ignore
+                // this facet element.
+                if (enumVal == null) {
+                    reportSchemaError("s4s-att-must-appear", new Object[]{SchemaSymbols.ELT_ENUMERATION, SchemaSymbols.ATT_VALUE}, content);
+                    fAttrChecker.returnAttrArray (attrs, schemaDoc);
+                    content = DOMUtil.getNextSiblingElement(content);
+                    continue;
+                }
+
+                NamespaceSupport nsDecls = (NamespaceSupport)attrs[XSAttributeChecker.ATTIDX_ENUMNSDECLS];
+
+                // for NOTATION types, need to check whether there is a notation
+                // declared with the same name as the enumeration value.
+                if (baseValidator.getVariety() == XSSimpleType.VARIETY_ATOMIC &&
+                        baseValidator.getPrimitiveKind() == XSSimpleType.PRIMITIVE_NOTATION) {
+                    // need to use the namespace context returned from checkAttributes
+                    schemaDoc.fValidationContext.setNamespaceSupport(nsDecls);
+                    Object notation = null;
+                    try{
+                        QName temp = (QName)fQNameDV.validate(enumVal, schemaDoc.fValidationContext, null);
+                        // try to get the notation decl. if failed, getGlobalDecl
+                        // reports an error, so we don't need to report one again.
+                        notation = fSchemaHandler.getGlobalDecl(schemaDoc, XSDHandler.NOTATION_TYPE, temp, content);
+                    }catch(InvalidDatatypeValueException ex){
+                        reportSchemaError(ex.getKey(), ex.getArgs(), content);
+                    }
+                    if (notation == null) {
+                        // Either the QName value is invalid, or it doens't
+                        // resolve to a notation declaration.
+                        // Ignore this facet, to avoid instance validation problems
+                        fAttrChecker.returnAttrArray (attrs, schemaDoc);
+                        content = DOMUtil.getNextSiblingElement(content);
+                        continue;
+                    }
+                    // restore to the normal namespace context
+                    schemaDoc.fValidationContext.setNamespaceSupport(schemaDoc.fNamespaceSupport);
+                }
+                if (enumData == null){
+                    enumData = new Vector();
+                    enumAnnotations = new XSObjectListImpl();
+                }
+                enumData.addElement(enumVal);
+                enumAnnotations.addXSObject(null);
+                if (hasQName)
+                    enumNSDecls.addElement(nsDecls);
+                Element child = DOMUtil.getFirstChildElement( content );
+
+                if (child != null &&
+                    DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION)) {
+                    // traverse annotation if any
+                    enumAnnotations.addXSObject(enumAnnotations.getLength()-1,traverseAnnotationDecl(child, attrs, false, schemaDoc));
+                    child = DOMUtil.getNextSiblingElement(child);
+                }
+                else {
+                    String text = DOMUtil.getSyntheticAnnotation(content);
+                    if (text != null) {
+                        enumAnnotations.addXSObject(enumAnnotations.getLength()-1, traverseSyntheticAnnotation(content, text, attrs, false, schemaDoc));
+                    }
+                }
+                if (child !=null) {
+                    reportSchemaError("s4s-elt-must-match.1", new Object[]{"enumeration", "(annotation?)", DOMUtil.getLocalName(child)}, child);
+                }
+            }
+            else if (facet.equals(SchemaSymbols.ELT_PATTERN)) {
+                facetsPresent |= XSSimpleType.FACET_PATTERN;
+                attrs = fAttrChecker.checkAttributes(content, false, schemaDoc);
+                String patternVal = (String)attrs[XSAttributeChecker.ATTIDX_VALUE];
+                // The facet can't be used if the value is missing. Ignore
+                // this facet element.
+                if (patternVal == null) {
+                    reportSchemaError("s4s-att-must-appear", new Object[]{SchemaSymbols.ELT_PATTERN, SchemaSymbols.ATT_VALUE}, content);
+                    fAttrChecker.returnAttrArray (attrs, schemaDoc);
+                    content = DOMUtil.getNextSiblingElement(content);
+                    continue;
+                }
+
+                if (fPattern.length() == 0) {
+                    fPattern.append(patternVal);
+                } else {
+                    // ---------------------------------------------
+                    //datatypes: 5.2.4 pattern: src-multiple-pattern
+                    // ---------------------------------------------
+                    fPattern.append("|");
+                    fPattern.append(patternVal);
+                }
+                Element child = DOMUtil.getFirstChildElement( content );
+                if (child != null &&
+                        DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION)) {
+                    // traverse annotation if any
+                    if (patternAnnotations == null){
+                        patternAnnotations = new XSObjectListImpl();
+                    }
+                    patternAnnotations.addXSObject(traverseAnnotationDecl(child, attrs, false, schemaDoc));
+                    child = DOMUtil.getNextSiblingElement(child);
+                }
+                else {
+                    String text = DOMUtil.getSyntheticAnnotation(content);
+                    if (text != null) {
+                        if (patternAnnotations == null){
+                            patternAnnotations = new XSObjectListImpl();
+                        }
+                        patternAnnotations.addXSObject(traverseSyntheticAnnotation(content, text, attrs, false, schemaDoc));
+                    }
+                }
+                if (child !=null) {
+                    reportSchemaError("s4s-elt-must-match.1", new Object[]{"pattern", "(annotation?)", DOMUtil.getLocalName(child)}, child);
+                }
+            }
+            else {
+                if (facet.equals(SchemaSymbols.ELT_MINLENGTH)) {
+                    currentFacet = XSSimpleType.FACET_MINLENGTH;
+                }
+                else if (facet.equals(SchemaSymbols.ELT_MAXLENGTH)) {
+                    currentFacet = XSSimpleType.FACET_MAXLENGTH;
+                }
+                else if (facet.equals(SchemaSymbols.ELT_MAXEXCLUSIVE)) {
+                    currentFacet = XSSimpleType.FACET_MAXEXCLUSIVE;
+                }
+                else if (facet.equals(SchemaSymbols.ELT_MAXINCLUSIVE)) {
+                    currentFacet = XSSimpleType.FACET_MAXINCLUSIVE;
+                }
+                else if (facet.equals(SchemaSymbols.ELT_MINEXCLUSIVE)) {
+                    currentFacet = XSSimpleType.FACET_MINEXCLUSIVE;
+                }
+                else if (facet.equals(SchemaSymbols.ELT_MININCLUSIVE)) {
+                    currentFacet = XSSimpleType.FACET_MININCLUSIVE;
+                }
+                else if (facet.equals(SchemaSymbols.ELT_TOTALDIGITS)) {
+                    currentFacet = XSSimpleType.FACET_TOTALDIGITS;
+                }
+                else if (facet.equals(SchemaSymbols.ELT_FRACTIONDIGITS)) {
+                    currentFacet = XSSimpleType.FACET_FRACTIONDIGITS;
+                }
+                else if (facet.equals(SchemaSymbols.ELT_WHITESPACE)) {
+                    currentFacet = XSSimpleType.FACET_WHITESPACE;
+                }
+                else if (facet.equals(SchemaSymbols.ELT_LENGTH)) {
+                    currentFacet = XSSimpleType.FACET_LENGTH;
+                }
+                else {
+                    break;   // a non-facet
+                }
+
+                attrs = fAttrChecker.checkAttributes(content, false, schemaDoc);
+
+                // check for duplicate facets
+                if ((facetsPresent & currentFacet) != 0) {
+                    // Ignore this facet, to avoid corrupting the previous facet
+                    reportSchemaError("src-single-facet-value", new Object[]{facet}, content);
+                    fAttrChecker.returnAttrArray (attrs, schemaDoc);
+                    content = DOMUtil.getNextSiblingElement(content);
+                    continue;
+                }
+
+                // The facet can't be used if the value is missing. Ignore
+                // this facet element.
+                if (attrs[XSAttributeChecker.ATTIDX_VALUE] == null) {
+                    // Report an error if the "value" attribute is missing.
+                    // If it's not missing, then its value is invalid, and an
+                    // error should have already been reported by the
+                    // attribute checker.
+                    if (content.getAttributeNodeNS(null, "value") == null) {
+                        reportSchemaError("s4s-att-must-appear", new Object[]{content.getLocalName(), SchemaSymbols.ATT_VALUE}, content);
+                    }
+                    fAttrChecker.returnAttrArray (attrs, schemaDoc);
+                    content = DOMUtil.getNextSiblingElement(content);
+                    continue;
+                }
+
+                facetsPresent |= currentFacet;
+                // check for fixed facet
+                if (((Boolean)attrs[XSAttributeChecker.ATTIDX_FIXED]).booleanValue()) {
+                    facetsFixed |= currentFacet;
+                }
+                switch (currentFacet) {
+                case XSSimpleType.FACET_MINLENGTH:
+                    xsFacets.minLength = ((XInt)attrs[XSAttributeChecker.ATTIDX_VALUE]).intValue();
+                    break;
+                case XSSimpleType.FACET_MAXLENGTH:
+                    xsFacets.maxLength = ((XInt)attrs[XSAttributeChecker.ATTIDX_VALUE]).intValue();
+                    break;
+                case XSSimpleType.FACET_MAXEXCLUSIVE:
+                    xsFacets.maxExclusive = (String)attrs[XSAttributeChecker.ATTIDX_VALUE];
+                    break;
+                case XSSimpleType.FACET_MAXINCLUSIVE:
+                    xsFacets.maxInclusive = (String)attrs[XSAttributeChecker.ATTIDX_VALUE];
+                    break;
+                case XSSimpleType.FACET_MINEXCLUSIVE:
+                    xsFacets.minExclusive = (String)attrs[XSAttributeChecker.ATTIDX_VALUE];
+                    break;
+                case XSSimpleType.FACET_MININCLUSIVE:
+                    xsFacets.minInclusive = (String)attrs[XSAttributeChecker.ATTIDX_VALUE];
+                    break;
+                case XSSimpleType.FACET_TOTALDIGITS:
+                    xsFacets.totalDigits = ((XInt)attrs[XSAttributeChecker.ATTIDX_VALUE]).intValue();
+                    break;
+                case XSSimpleType.FACET_FRACTIONDIGITS:
+                    xsFacets.fractionDigits = ((XInt)attrs[XSAttributeChecker.ATTIDX_VALUE]).intValue();
+                    break;
+                case XSSimpleType.FACET_WHITESPACE:
+                    xsFacets.whiteSpace = ((XInt)attrs[XSAttributeChecker.ATTIDX_VALUE]).shortValue();
+                    break;
+                case XSSimpleType.FACET_LENGTH:
+                    xsFacets.length = ((XInt)attrs[XSAttributeChecker.ATTIDX_VALUE]).intValue();
+                    break;
+                }
+
+                Element child = DOMUtil.getFirstChildElement( content );
+                XSAnnotationImpl annotation = null;
+                if (child != null &&
+                    DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION)) {
+                    // traverse annotation if any
+                    annotation = traverseAnnotationDecl(child, attrs, false, schemaDoc);
+                    child = DOMUtil.getNextSiblingElement(child);
+                }
+                else {
+                    String text = DOMUtil.getSyntheticAnnotation(content);
+                    if (text != null) {
+                        annotation = traverseSyntheticAnnotation(content, text, attrs, false, schemaDoc);
+                    }
+               }
+                switch (currentFacet) {
+                case XSSimpleType.FACET_MINLENGTH:
+                    xsFacets.minLengthAnnotation = annotation;
+                break;
+                case XSSimpleType.FACET_MAXLENGTH:
+                    xsFacets.maxLengthAnnotation = annotation;
+                break;
+                case XSSimpleType.FACET_MAXEXCLUSIVE:
+                    xsFacets.maxExclusiveAnnotation = annotation;
+                break;
+                case XSSimpleType.FACET_MAXINCLUSIVE:
+                    xsFacets.maxInclusiveAnnotation = annotation;
+                break;
+                case XSSimpleType.FACET_MINEXCLUSIVE:
+                    xsFacets.minExclusiveAnnotation = annotation;
+                break;
+                case XSSimpleType.FACET_MININCLUSIVE:
+                    xsFacets.minInclusiveAnnotation = annotation;
+                break;
+                case XSSimpleType.FACET_TOTALDIGITS:
+                    xsFacets.totalDigitsAnnotation = annotation;
+                break;
+                case XSSimpleType.FACET_FRACTIONDIGITS:
+                    xsFacets.fractionDigitsAnnotation = annotation;
+                break;
+                case XSSimpleType.FACET_WHITESPACE:
+                    xsFacets.whiteSpaceAnnotation = annotation;
+                break;
+                case XSSimpleType.FACET_LENGTH:
+                    xsFacets.lengthAnnotation = annotation;
+                break;
+                }
+                if (child != null) {
+                    reportSchemaError("s4s-elt-must-match.1", new Object[]{facet, "(annotation?)", DOMUtil.getLocalName(child)}, child);
+                }
+            }
+            fAttrChecker.returnAttrArray (attrs, schemaDoc);
+            content = DOMUtil.getNextSiblingElement(content);
+        }
+        if (enumData !=null) {
+            facetsPresent |= XSSimpleType.FACET_ENUMERATION;
+            xsFacets.enumeration = enumData;
+            xsFacets.enumNSDecls = enumNSDecls;
+            xsFacets.enumAnnotations = enumAnnotations;
+        }
+        if ((facetsPresent & XSSimpleType.FACET_PATTERN) != 0) {
+            xsFacets.pattern = fPattern.toString();
+            xsFacets.patternAnnotations = patternAnnotations;
+        }
+
+        fPattern.setLength(0);
+
+        return new FacetInfo(xsFacets, content, facetsPresent, facetsFixed);
+    }
+
+
+    // return whether QName/NOTATION is part of the given type
+    private boolean containsQName(XSSimpleType type) {
+        if (type.getVariety() == XSSimpleType.VARIETY_ATOMIC) {
+            short primitive = type.getPrimitiveKind();
+            return (primitive == XSSimpleType.PRIMITIVE_QNAME ||
+                    primitive == XSSimpleType.PRIMITIVE_NOTATION);
+        }
+        else if (type.getVariety() == XSSimpleType.VARIETY_LIST) {
+            return containsQName((XSSimpleType)type.getItemType());
+        }
+        else if (type.getVariety() == XSSimpleType.VARIETY_UNION) {
+            XSObjectList members = type.getMemberTypes();
+            for (int i = 0; i < members.getLength(); i++) {
+                if (containsQName((XSSimpleType)members.item(i)))
+                    return true;
+            }
+        }
+        return false;
+    }
+
+    //
+    // Traverse a set of attribute and attribute group elements
+    // Needed by complexType and attributeGroup traversal
+    // This method will return the first non-attribute/attrgrp found
+    //
+    Element traverseAttrsAndAttrGrps(Element firstAttr, XSAttributeGroupDecl attrGrp,
+            XSDocumentInfo schemaDoc, SchemaGrammar grammar,
+            XSComplexTypeDecl enclosingCT) {
+
+        Element child=null;
+        XSAttributeGroupDecl tempAttrGrp = null;
+        XSAttributeUseImpl tempAttrUse = null;
+        XSAttributeUse otherUse = null;
+        String childName;
+
+        for (child=firstAttr; child!=null; child=DOMUtil.getNextSiblingElement(child)) {
+            childName = DOMUtil.getLocalName(child);
+            if (childName.equals(SchemaSymbols.ELT_ATTRIBUTE)) {
+                tempAttrUse = fSchemaHandler.fAttributeTraverser.traverseLocal(child,
+                        schemaDoc,
+                        grammar,
+                        enclosingCT);
+                if (tempAttrUse == null) continue;
+                if (tempAttrUse.fUse == SchemaSymbols.USE_PROHIBITED) {
+                    attrGrp.addAttributeUse(tempAttrUse);
+                    continue;
+                }
+                otherUse = attrGrp.getAttributeUseNoProhibited(
+                        tempAttrUse.fAttrDecl.getNamespace(),
+                        tempAttrUse.fAttrDecl.getName());
+                if (otherUse==null) {
+                    String idName = attrGrp.addAttributeUse(tempAttrUse);
+                    if (idName != null) {
+                        String code = (enclosingCT == null) ? "ag-props-correct.3" : "ct-props-correct.5";
+                        String name = (enclosingCT == null) ? attrGrp.fName : enclosingCT.getName();
+                        reportSchemaError(code, new Object[]{name, tempAttrUse.fAttrDecl.getName(), idName}, child);
+                    }
+                }
+                else if (otherUse != tempAttrUse) {
+                    String code = (enclosingCT == null) ? "ag-props-correct.2" : "ct-props-correct.4";
+                    String name = (enclosingCT == null) ? attrGrp.fName : enclosingCT.getName();
+                    reportSchemaError(code, new Object[]{name, tempAttrUse.fAttrDecl.getName()}, child);
+                }
+            }
+            else if (childName.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) {
+                //REVISIT: do we need to save some state at this point??
+                tempAttrGrp = fSchemaHandler.fAttributeGroupTraverser.traverseLocal(
+                        child, schemaDoc, grammar);
+                if(tempAttrGrp == null ) continue;
+                XSObjectList attrUseS = tempAttrGrp.getAttributeUses();
+                XSAttributeUseImpl oneAttrUse;
+                int attrCount = attrUseS.getLength();
+                for (int i=0; i<attrCount; i++) {
+                    oneAttrUse = (XSAttributeUseImpl)attrUseS.item(i);
+                    if (oneAttrUse.fUse == SchemaSymbols.USE_PROHIBITED) {
+                        attrGrp.addAttributeUse(oneAttrUse);
+                        continue;
+                    }
+                    otherUse = attrGrp.getAttributeUseNoProhibited(
+                            oneAttrUse.fAttrDecl.getNamespace(),
+                            oneAttrUse.fAttrDecl.getName());
+                    if (otherUse==null) {
+                        String idName = attrGrp.addAttributeUse(oneAttrUse);
+                        if (idName != null) {
+                            String code = (enclosingCT == null) ? "ag-props-correct.3" : "ct-props-correct.5";
+                            String name = (enclosingCT == null) ? attrGrp.fName : enclosingCT.getName();
+                            reportSchemaError(code, new Object[]{name, oneAttrUse.fAttrDecl.getName(), idName}, child);
+                        }
+                    }
+                    else if (oneAttrUse != otherUse) {
+                        String code = (enclosingCT == null) ? "ag-props-correct.2" : "ct-props-correct.4";
+                        String name = (enclosingCT == null) ? attrGrp.fName : enclosingCT.getName();
+                        reportSchemaError(code, new Object[]{name, oneAttrUse.fAttrDecl.getName()}, child);
+                    }
+                }
+
+                if (tempAttrGrp.fAttributeWC != null) {
+                    if (attrGrp.fAttributeWC == null) {
+                        attrGrp.fAttributeWC = tempAttrGrp.fAttributeWC;
+                    }
+                    // perform intersection of attribute wildcard
+                    else {
+                        attrGrp.fAttributeWC = attrGrp.fAttributeWC.
+                        performIntersectionWith(tempAttrGrp.fAttributeWC, attrGrp.fAttributeWC.fProcessContents);
+                        if (attrGrp.fAttributeWC == null) {
+                            String code = (enclosingCT == null) ? "src-attribute_group.2" : "src-ct.4";
+                            String name = (enclosingCT == null) ? attrGrp.fName : enclosingCT.getName();
+                            reportSchemaError(code, new Object[]{name}, child);
+                        }
+                    }
+                }
+            }
+            else
+                break;
+        } // for
+
+        if (child != null) {
+            childName = DOMUtil.getLocalName(child);
+            if (childName.equals(SchemaSymbols.ELT_ANYATTRIBUTE)) {
+                XSWildcardDecl tempAttrWC = fSchemaHandler.fWildCardTraverser.
+                traverseAnyAttribute(child, schemaDoc, grammar);
+                if (attrGrp.fAttributeWC == null) {
+                    attrGrp.fAttributeWC = tempAttrWC;
+                }
+                // perform intersection of attribute wildcard
+                else {
+                    attrGrp.fAttributeWC = tempAttrWC.
+                    performIntersectionWith(attrGrp.fAttributeWC, tempAttrWC.fProcessContents);
+                    if (attrGrp.fAttributeWC == null) {
+                        String code = (enclosingCT == null) ? "src-attribute_group.2" : "src-ct.4";
+                        String name = (enclosingCT == null) ? attrGrp.fName : enclosingCT.getName();
+                        reportSchemaError(code, new Object[]{name}, child);
+                    }
+                }
+                child = DOMUtil.getNextSiblingElement(child);
+            }
+        }
+
+        // Success
+        return child;
+
+    }
+
+    void reportSchemaError (String key, Object[] args, Element ele) {
+        fSchemaHandler.reportSchemaError(key, args, ele);
+    }
+
+    /**
+     * Element/Attribute traversers call this method to check whether
+     * the type is NOTATION without enumeration facet
+     */
+    void checkNotationType(String refName, XSTypeDefinition typeDecl, Element elem) {
+        if (typeDecl.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE &&
+                ((XSSimpleType)typeDecl).getVariety() == XSSimpleType.VARIETY_ATOMIC &&
+                ((XSSimpleType)typeDecl).getPrimitiveKind() == XSSimpleType.PRIMITIVE_NOTATION) {
+            if ((((XSSimpleType)typeDecl).getDefinedFacets() & XSSimpleType.FACET_ENUMERATION) == 0) {
+                reportSchemaError("enumeration-required-notation", new Object[]{typeDecl.getName(), refName, DOMUtil.getLocalName(elem)}, elem);
+            }
+        }
+    }
+
+    // Checks constraints for minOccurs, maxOccurs
+    protected XSParticleDecl checkOccurrences(XSParticleDecl particle,
+            String particleName, Element parent,
+            int allContextFlags,
+            long defaultVals) {
+
+        int min = particle.fMinOccurs;
+        int max = particle.fMaxOccurs;
+        boolean defaultMin = (defaultVals & (1 << XSAttributeChecker.ATTIDX_MINOCCURS)) != 0;
+        boolean defaultMax = (defaultVals & (1 << XSAttributeChecker.ATTIDX_MAXOCCURS)) != 0;
+
+        boolean processingAllEl = ((allContextFlags & PROCESSING_ALL_EL) != 0);
+        boolean processingAllGP = ((allContextFlags & PROCESSING_ALL_GP) != 0);
+        boolean groupRefWithAll = ((allContextFlags & GROUP_REF_WITH_ALL) != 0);
+        boolean isGroupChild    = ((allContextFlags & CHILD_OF_GROUP) != 0);
+
+        // Neither minOccurs nor maxOccurs may be specified
+        // for the child of a model group definition.
+        if (isGroupChild) {
+            if (!defaultMin) {
+                Object[] args = new Object[]{particleName, "minOccurs"};
+                reportSchemaError("s4s-att-not-allowed", args, parent);
+                min = 1;
+            }
+            if (!defaultMax) {
+                Object[] args = new Object[]{particleName, "maxOccurs"};
+                reportSchemaError("s4s-att-not-allowed", args, parent);
+                max = 1;
+            }
+        }
+
+        // If minOccurs=maxOccurs=0, no component is specified
+        if (min == 0 && max== 0) {
+            particle.fType = XSParticleDecl.PARTICLE_EMPTY;
+            return null;
+        }
+
+        // For the elements referenced in an <all>, minOccurs attribute
+        // must be zero or one, and maxOccurs attribute must be one.
+        // For a complex type definition that contains an <all> or a
+        // reference a <group> whose model group is an all model group,
+        // minOccurs and maxOccurs must be one.
+        if (processingAllEl) {
+            if (max != 1) {
+                reportSchemaError("cos-all-limited.2", new Object[]{
+                        (max == SchemaSymbols.OCCURRENCE_UNBOUNDED) ? SchemaSymbols.ATTVAL_UNBOUNDED : Integer.toString(max),
+                        ((XSElementDecl)particle.fValue).getName()}, parent);
+                max = 1;
+                if (min > 1)
+                    min = 1;
+            }
+        }
+        else if (processingAllGP || groupRefWithAll) {
+            if (max != 1) {
+                reportSchemaError("cos-all-limited.1.2", null, parent);
+                if (min > 1)
+                    min = 1;
+                max = 1;
+            }
+        }
+
+        particle.fMinOccurs = min;
+        particle.fMaxOccurs = max;
+
+        return particle;
+    }
+
+    private static String processAttValue(String original) {
+        final int length = original.length();
+        // normally, nothing will happen
+        for (int i = 0; i < length; ++i) {
+            char currChar = original.charAt(i);
+            if (currChar == '"' || currChar == '<' || currChar == '&' ||
+                    currChar == 0x09 || currChar == 0x0A || currChar == 0x0D) {
+                return escapeAttValue(original, i);
+            }
+        }
+        return original;
+    }
+
+    // this is not terribly performant!
+    private static String escapeAttValue(String original, int from) {
+        int i;
+        final int length = original.length();
+        StringBuffer newVal = new StringBuffer(length);
+        newVal.append(original.substring(0, from));
+        for (i = from; i < length; ++i) {
+            char currChar = original.charAt(i);
+            if (currChar == '"') {
+                newVal.append("&quot;");
+            }
+            else if (currChar == '<') {
+                newVal.append("&lt;");
+            }
+            else if (currChar == '&') {
+                newVal.append("&amp;");
+            }
+            // Must escape 0x09, 0x0A and 0x0D if they appear in attribute
+            // value so that they may be round-tripped. They would otherwise
+            // be transformed to a 0x20 during attribute value normalization.
+            else if (currChar == 0x09) {
+                newVal.append("&#x9;");
+            }
+            else if (currChar == 0x0A) {
+                newVal.append("&#xA;");
+            }
+            else if (currChar == 0x0D) {
+                newVal.append("&#xD;");
+            }
+            else {
+                newVal.append(currChar);
+            }
+        }
+        return newVal.toString();
+    }
+}