You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xerces.apache.org by sa...@apache.org on 2010/11/05 20:09:17 UTC

svn commit: r1031723 [2/3] - /xerces/java/branches/xml-schema-1.1-dev/src/org/apache/xerces/impl/xs/models/XS11CMRestriction.java

Modified: xerces/java/branches/xml-schema-1.1-dev/src/org/apache/xerces/impl/xs/models/XS11CMRestriction.java
URL: http://svn.apache.org/viewvc/xerces/java/branches/xml-schema-1.1-dev/src/org/apache/xerces/impl/xs/models/XS11CMRestriction.java?rev=1031723&r1=1031722&r2=1031723&view=diff
==============================================================================
--- xerces/java/branches/xml-schema-1.1-dev/src/org/apache/xerces/impl/xs/models/XS11CMRestriction.java (original)
+++ xerces/java/branches/xml-schema-1.1-dev/src/org/apache/xerces/impl/xs/models/XS11CMRestriction.java Fri Nov  5 19:09:17 2010
@@ -1,1371 +1,1371 @@
-/*
- * 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 org.apache.xerces.impl.xs.models;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import org.apache.xerces.impl.Constants;
-import org.apache.xerces.impl.xs.SchemaGrammar;
-import org.apache.xerces.impl.xs.SubstitutionGroupHandler;
-import org.apache.xerces.impl.xs.XSConstraints;
-import org.apache.xerces.impl.xs.XSElementDecl;
-import org.apache.xerces.impl.xs.XSElementDeclHelper;
-import org.apache.xerces.impl.xs.XSGrammarBucket;
-import org.apache.xerces.impl.xs.XSOpenContentDecl;
-import org.apache.xerces.impl.xs.XSWildcardDecl;
-import org.apache.xerces.impl.xs.identity.IdentityConstraint;
-import org.apache.xerces.xni.QName;
-import org.apache.xerces.xs.XSComplexTypeDefinition;
-import org.apache.xerces.xs.XSConstants;
-import org.apache.xerces.xs.XSNamedMap;
-import org.apache.xerces.xs.XSSimpleTypeDefinition;
-import org.apache.xerces.xs.XSTypeDefinition;
-
-/**
-    // TODO: tests:
-    // * base all: (e, w?)?; derived all: (e)? w. Should be invalid <e1/>
-    // * base all: (e/f, w); derived all: (e, w)
-    // * base: e|w(lax) + w(skip), derived: w(lax) + w(skip)
-            // Example test:
-            // Bad: base: ((a|b)&) derived: (a & b).
-            // derive allow a,b, base doesn't.
-            // Bad: base: ((ns1:a|ns2:b) & ns1:*) derived: (ns1:a & ns2:b).
-            // derive allow a,b, base doesn't.
-            // Good: base: ((ns1:a|ns2:b) & ns1:*? & ns2:*?) derived: (ns1:a & ns2:b).
-            // base: (a{2} & *), derived: (a & *)
-    
- * @version $Id$
- */
-public final class XS11CMRestriction implements XSElementDeclHelper {
-    private final SubstitutionGroupHandler sgh;
-    private final XSGrammarBucket gb;
-    private final CMBuilder cmb;
-    private final XSConstraints xsc;
-    
-    // Content models to be checked
-    private XS11CM base, derived;
-    // Used when both base and derived are "all" groups
-    private XS11AllCM allb, alld;
-    // Used when base is "dfa" and derived is "all"
-    private XSDFACM dfab;
-
-    // Temporary QName object
-    private QName qname = new QName();
-
-    // Pairs of matching states from base and derived.
-    private List states = new ArrayList();
-    // A pair of matching states.
-    private StatePair pair = null;
-
-    // The following field represents a wildcard. It's typically a wildcad
-    // from the derived type. We keep subtract matching components in the base
-    // from this wildcard.
-    private short wType;
-    private List wNSList = new ArrayList();
-    private List wNSListTemp = new ArrayList();
-    // Disallowed name list
-    private List wDNList = new ArrayList();
-    // ##sibling and ##defined
-    private boolean wDD, wDS;
-    // Allowed name list, used after subtracting a disallowed list.
-    private List wANList = new ArrayList();
-
-    // List of QNames used for ##sibling and ##defined checking
-    private List globals;
-    private List siblingsB;
-    private List siblingsD;
-
-    // Element/wildcard decls in base and derived
-    private XSElementDecl eb, ed;
-    private XSWildcardDecl wb, wd;
-    // Current/next states in base and derived.
-    private int[] b, bn, d, dn;
-    // Index of the previously matched decl in base and derived, so that we
-    // know where to continue.
-    private int[] indexb = new int[1], indexd = new int[1];
-    // Optimization. If an element declaration in derived is the same as an
-    // element declaration in base without using any substitution group, then
-    // we don't need to dig into the sub-groups. They will be the same.
-    private boolean matchedHead;
-
-    // Interface implemented by the content model classes
-    interface XS11CM extends XSCMValidator {
-        // Find the next possible element transition.
-        // "s" is the current state, "sn" is the next state after the transition,
-        // "index" has info about where to start looking, and stores the index
-        // of the new declaration if one is found, or -1.
-        // Returns the matching decl, or null.
-        public XSElementDecl nextElementTransition(int[] s, int[] sn, int[] index);
-        // Find the next possible wildcard transition, including open content.
-        public XSWildcardDecl nextWildcardTransition(int[] s, int[] sn, int[] index);
-        // Check whether a matched wildcard is an open content.
-        public boolean isOpenContent(XSWildcardDecl w);
-        // Check whether a QName is allowed by a wildcard in the content model.
-        // Need to check namespace, local name, ##sibling, and ##defined.
-        public boolean allowExpandedName(XSWildcardDecl wildcard,
-                QName name, SubstitutionGroupHandler sgh,
-                XSElementDeclHelper edh);
-        // Get the list of names known to the content model, for ##sibling.
-        public List getDefinedNames(SubstitutionGroupHandler sgh);
-        // Before putting a pair of states into the list, give the content
-        // model a chance to optimize. If a set of states can be folded into
-        // a single one, the content model can change the state int arrays
-        // to represent the one state. e.g. if both base and derived have
-        // the same element declaration with the same min/maxOccurs information,
-        // then we don't have to have many different states.
-        // Currently this is only implemented by DFA.
-        public void optimizeStates(XS11CM base, int[] b, int[] d, int indexb);
-    }
-    
-    public XS11CMRestriction(XSCMValidator base, XSCMValidator derived,
-            SubstitutionGroupHandler sgh, XSGrammarBucket gb,
-            CMBuilder cmb, XSConstraints xsc) {
-        this.base = (XS11CM)base;
-        this.derived = (XS11CM)derived;
-        this.sgh = sgh;
-        this.gb = gb;
-        this.cmb = cmb;
-        this.xsc = xsc;
-    }
-
-    // Helper: add a pair of states to the list, if such pair is not already
-    // in the list.
-    private void addState() {
-        // Optimize the states when possible.
-        derived.optimizeStates(base, bn, dn, indexb[0]);
-        // Reuse the "pair" object
-        if (pair == null) {
-            pair = new StatePair(bn, dn);
-        }
-        else {
-            pair.set(bn, dn);
-        }
-        // Only add if the pair isn't already in the list
-        if (!states.contains(pair)) {
-            states.add(pair);
-            pair = null;
-        }
-    }
-
-    // Helper: copy a derived wildcard to fields of this class.
-    private void copyDerivedWildcard() {
-        wType = wd.fType;
-        wDD = wd.fDisallowedDefined;
-        wDS = wd.fDisallowedSibling;
-        wNSList.clear();
-        if (wType == XSWildcardDecl.NSCONSTRAINT_ANY) {
-            // "any" is the same as "not" + empty namespace list.
-            wType = XSWildcardDecl.NSCONSTRAINT_NOT;
-        }
-        else {
-            int size = wd.fNamespaceList == null ? 0 : wd.fNamespaceList.length;
-            for (int i = 0; i < size; i++) {
-                wNSList.add(wd.fNamespaceList[i]);
-            }
-        }
-        // Copy disallowed name list
-        // Don't clear, because the list is pre-populated with element names
-        int size = wd.fDisallowedNamesList == null ? 0 : wd.fDisallowedNamesList.length;
-        for (int i = 0; i < size; i++) {
-            wDNList.add(wd.fDisallowedNamesList[i].uri);
-            wDNList.add(wd.fDisallowedNamesList[i].localpart);
-        }
-        // Allowed name list starts as empty
-        wANList.clear();
-    }
-
-    // Helper: add a name to the "allowed" list
-    private void addAN(String ns, String name) {
-        // Only add if it's allowed by the current wildcard
-        if (!allowNS(ns)) {
-            return;
-        }
-        // Only add if the name is not in the disallowed name list.
-        for (int i = 0; i < wDNList.size();) {
-            if (wDNList.get(i++) == ns && wDNList.get(i++) == name) {
-                return;
-            }
-        }
-        // Only add if the name is allowed by the wildcard in terms of
-        // ##sibling and ##defined.
-        qname.uri = ns;
-        qname.localpart = name;
-        if (!derived.allowExpandedName(wd, qname, sgh, this)) {
-            return;
-        }
-        // The name is allowed, add it.
-        wANList.add(ns);
-        wANList.add(name);
-    }
-
-    // Helper: check whether a namespace name is allowed by the wildcard
-    private boolean allowNS(String ns) {
-        return wType == XSWildcardDecl.NSCONSTRAINT_ANY ||
-               wType == XSWildcardDecl.NSCONSTRAINT_NOT && !wNSList.contains(ns) ||
-               wType == XSWildcardDecl.NSCONSTRAINT_LIST && wNSList.contains(ns);
-    }
-
-    // Helper: check whether a name is allowed by the current wildcard
-    private boolean allowName(String ns, String name) {
-        // Check namespace first
-        if (!allowNS(ns)) {
-            return false;
-        }
-        // Whether the name is in the disallowed list
-        for (int i = 0; i < wDNList.size(); i+=2) {
-            if (ns == wDNList.get(i) && name == wDNList.get(i+1)) {
-                return false;
-            }
-        }
-        // Whether the name is in the allowed list
-        for (int i = 0; i < wANList.size(); i+=2) {
-            if (ns == wANList.get(i) && name == wANList.get(i+1)) {
-                return true;
-            }
-        }
-        // Additional ##sibling and ##defined checks
-        qname.uri = ns;
-        qname.localpart = name;
-        return derived.allowExpandedName(wd, qname, sgh, this);
-    }
-
-    // Helper: whether the current wildcard is empty: allows nothing
-    private boolean emptyWildcard() {
-        // Only when the list of namespace and the list of allowed names are
-        // both empty.
-        return wType == XSWildcardDecl.NSCONSTRAINT_LIST &&
-        wNSList.size() == 0 && wANList.size() == 0;
-    }
-
-    // Helper: get all defined elements. For ##defined.
-    private void getGlobalElements() {
-        globals = new ArrayList();
-        SchemaGrammar[] sgs = gb.getGrammars();
-        for (int i = 0; i < sgs.length; i++) {
-            addGlobals(sgs[i]);
-        }
-    }
-
-    // Helper: get all defined elements in a given namespace. For ##defined.
-    private void addGlobals(SchemaGrammar g) {
-        XSNamedMap map = g.getComponents(XSConstants.ELEMENT_DECLARATION);
-        for (int i = 0; i < map.getLength(); i++) {
-            XSElementDecl e = (XSElementDecl)map.item(i);
-            globals.add(e.fTargetNamespace);
-            globals.add(e.fName);
-        }
-    }
-
-    // Helper: get all known names in the base content model. For ##sibling.
-    private void getBaseSiblings() {
-        siblingsB = base.getDefinedNames(sgh);
-    }
-
-    // Helper: get all known names in the derived content model. For ##sibling.
-    private void getDerivedSiblings() {
-        siblingsD = derived.getDefinedNames(sgh);
-    }
-    
-    // Helper: get a global element declaration with the specified name.
-    public XSElementDecl getGlobalElementDecl(QName name) {
-        SchemaGrammar sg = gb.getGrammar(name.uri);
-        return sg != null ? sg.getGlobalElementDecl(name.localpart) : null;
-    }
-
-    // Entry point: check the content models passed in to the constructor.
-    public boolean check() {
-        // Initialize the states. Needs this before the "derived is all" check,
-        // because these state arrays are always needed.
-        b = base.startContentModel();
-        bn = base.startContentModel();
-        d = derived.startContentModel();
-        dn = derived.startContentModel();
-
-        // If derived is all, then we may be able to do better than treating
-        // it as a DFA.
-        if (derived instanceof XS11AllCM) {
-            alld = (XS11AllCM)derived;
-            // True: valid; False: invalid; null: need further checking
-            Boolean res = checkAllDerived();
-            if (res != null) {
-                return res.booleanValue();
-            }
-        }
-
-        // Helper list to gather all names that can't match the wildcard
-        // in derived, because the wildcard is weaker than the elements.
-        List excludedElementsCopy = new ArrayList();
-
-        // For every state in derived, find the corresponding states in base.
-        // For each pair of corresponding states, make sure all transitions
-        // allowed by derived are also allowed by base. The target states
-        // are also treated as "corresponding states". Continue for all such
-        // pairs. When derived is at a final state, the corresponding state
-        // for base must also be a final state.
-
-        // Handling the list of state pairs as a list, not a stack.
-        // Otherwise we may pop a pair off the stack, but latter find the same
-        // pair, but there is no way to know we've already seen that pair.
-        
-        // the number of processed state pairs.
-        int pos = 0;
-        // initialize the unprocessed set: put initial states in it
-        StatePair p = new StatePair(b, d);
-        states.add(p);
-        // while there is unprocessed pair
-        while (pos < states.size()) {
-            StatePair sp = (StatePair)states.get(pos++);
-            sp.getStates(b, d);
-
-            // for all possible element edges
-            excludedElementsCopy.clear();
-            indexd[0] = -1;
-            while ((ed = derived.nextElementTransition(d, dn, indexd)) != null) {
-                // Add them to the "can't match wildcard name" list
-                excludedElementsCopy.add(ed.fTargetNamespace);
-                excludedElementsCopy.add(ed.fName);
-                if (ed.getScope() == XSConstants.SCOPE_GLOBAL) {
-                    XSElementDecl[] eds = sgh.getSubstitutionGroup(ed, Constants.SCHEMA_VERSION_1_1);
-                    for (int j = 0; j < eds.length; j++) {
-                        excludedElementsCopy.add(eds[j].fTargetNamespace);
-                        excludedElementsCopy.add(eds[j].fName);
-                    }
-                }
-                // Make sure this element is allowed by the base
-                if (!matchElementInBase()) {
-                    return false;
-                }
-            }
-
-            // for all possible wildcard edges
-            indexd[0] = -1;
-            while ((wd = derived.nextWildcardTransition(d, dn, indexd)) != null) {
-                // Put all the stronger element names in the disallowed list
-                wDNList.clear();
-                wDNList.addAll(excludedElementsCopy);
-                // And make sure the wildcard is allowed by the base
-                if (!matchWildcardInBase()) {
-                    return false;
-                }
-            }
-        }
-        
-        // We processed all state pairs. Now check final states.
-        return checkFinalStates();
-    }
-
-    // for an element and all elements in its sub group, check whether
-    // there are matching edges in the base.
-    private boolean matchElementInBase() {
-        matchedHead = false;
-        // Look for an element decl in the base
-        if (!findElementInBase()) {
-            // There is a route in the derived, but no matching
-            // route in the base. not a valid restriction.
-            return false;
-        }
-        // put this pair in the unprocessed states, if it's not there
-        addState();
-
-        // Same element decl as derived, no need to look at sub-group.
-        if (matchedHead) {
-            return true;
-        }
-
-        // get all sub group elements
-        XSElementDecl[] eds = sgh.getSubstitutionGroup(ed, Constants.SCHEMA_VERSION_1_1);
-        for (int i = 0; i < eds.length; i++) {
-            ed = eds[i];
-            // check whether there is a matching edge
-            if (!findElementInBase()) {
-                // if not, there is a route in the derived, but no matching
-                // route in the base. not a valid restriction.
-                return false;
-            }
-            // put this pair in the unprocessed states, if it's not there
-            addState();
-        }
-
-        return true;
-    }
-
-    // find the matching next state in the base
-    private boolean findElementInBase() {
-        // for all edges in the base that leaves the base state
-        // check whether it's an edge matching the base edge.
-        // if it is, return the next state.
-        indexb[0] = -1;
-        while ((eb = base.nextElementTransition(b, bn, indexb)) != null) {
-            // Base element edge, check whether it matches the derived element
-            if (matchElementWithBaseElement()) {
-                // If name matches, check type, nil, fixed etc.
-                return checkEERestriction();
-            }
-        }
-        // No matching element edge, try wildcards.
-        indexb[0] = -1;
-        while ((wb = base.nextWildcardTransition(b, bn, indexb)) != null) {
-            // Base wildcard edge, check whether it matches the derived element
-            qname.uri = ed.fTargetNamespace;
-            qname.localpart = ed.fName;
-            if (base.allowExpandedName(wb, qname, sgh, this)) {
-                // If name matches, check whether there is a matching global.
-                return checkEWRestriction();
-            }
-        }
-        return false;
-    }
-
-    // whether 2 element edges match
-    private boolean matchElementWithBaseElement() {
-        if (eb.getName() == ed.getName() && eb.getNamespace() == ed.getNamespace()) {
-            // The elements match without using sub-groups. Remember this fact
-            // so that we know we don't need to check sub-groups.
-            matchedHead = eb == ed;
-            return true;
-        }
-
-        // if the name doesn't match, try its sub group elements
-        XSElementDecl[] ebs = sgh.getSubstitutionGroup(eb, Constants.SCHEMA_VERSION_1_1);
-        for (int i = 0; i < ebs.length; i++) {
-            if (ebs[i].getName() == ed.getName() &&
-                ebs[i].getNamespace() == ed.getNamespace()) {
-                eb = ebs[i];
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private boolean checkEERestriction() {
-        if (eb == ed) {
-            return true;
-        }
-        
-        // 4.1 Either G.{nillable} = true  or S.{nillable} = false.
-        if (!eb.getNillable() && ed.getNillable()) {
-            return false;
-        }
-
-        // 4.2 Either G has no {value constraint}, or it is not fixed,
-        // or S has a fixed {value constraint} with an equal value.
-        if (eb.getConstraintType() == XSConstants.VC_FIXED) {
-            // derived one has to have a fixed value
-            if (ed.getConstraintType() != XSConstants.VC_FIXED) {
-                return false;
-            }
-
-            // Get primitive kind for the fixed values. Use "string" for
-            // complex type with mixed content.
-            short btype, dtype;
-            if (eb.fType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
-                btype = ((XSSimpleTypeDefinition)eb.fType).getPrimitiveType().getBuiltInKind();
-            }
-            else {
-                XSComplexTypeDefinition complex = (XSComplexTypeDefinition)eb.fType;
-                if (complex.getContentType() == XSComplexTypeDefinition.CONTENTTYPE_SIMPLE) {
-                    btype = complex.getSimpleType().getPrimitiveType().getBuiltInKind();
-                }
-                else {
-                    btype = XSConstants.STRING_DT;
-                }
-            }
-            if (ed.fType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
-                dtype = ((XSSimpleTypeDefinition)ed.fType).getPrimitiveType().getBuiltInKind();
-            }
-            else {
-                XSComplexTypeDefinition complex = (XSComplexTypeDefinition)ed.fType;
-                if (complex.getContentType() == XSComplexTypeDefinition.CONTENTTYPE_SIMPLE) {
-                    dtype = complex.getSimpleType().getPrimitiveType().getBuiltInKind();
-                }
-                else {
-                    dtype = XSConstants.STRING_DT;
-                }
-            }
-            // The 2 values must have the same primitive kind and actual value.
-            // equals() checks both equality and identity.
-            if (btype != dtype || !eb.fDefault.actualValue.equals(ed.fDefault.actualValue)) {
-                return false;
-            }
-        }
-
-        // 4.3 S.{identity-constraint definitions} is a superset of G.{identity-constraint definitions}.
-        if (!checkIDConstraintRestriction(ed, eb)) {
-            return false;
-        }
-
-        // 4.4 S disallows a superset of the substitutions that G does.
-        if ((ed.fBlock & eb.fBlock) != eb.fBlock) {
-            return false;
-        }
-
-        // 4.5 S's declared {type definition} is ·validly substitutable as
-        // a restriction· for G's declared {type definition}.
-        if (!xsc.checkTypeDerivationOk(ed.fType, eb.fType,
-                (short)(XSConstants.DERIVATION_EXTENSION|XSConstants.DERIVATION_LIST|XSConstants.DERIVATION_UNION))) {
-            return false;
-        }
-        
-        return true;
-    }
-
-    private boolean checkIDConstraintRestriction(XSElementDecl derivedElemDecl,
-            XSElementDecl baseElemDecl) {
-        IdentityConstraint[] idcd = derivedElemDecl.getIDConstraints();
-        IdentityConstraint[] idcb = baseElemDecl.getIDConstraints();
-        int sizeb = idcb == null ? 0 : idcb.length;
-        int sized = idcd == null ? 0 : idcd.length;
-        // For each IDC in the base, look for the same IDC in derived
-        for (int b = 0; b < sizeb; b++) {
-            int d = 0;
-            for (; d < sized; d++) {
-                if (idcb[b] == idcd[d]) {
-                    break;
-                }
-            }
-            // Didn't find a match, error.
-            if (d == idcd.length) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    // whether 2 edges match
-    private boolean checkEWRestriction() {
-        // 1 G is skip.
-        if (wb.getProcessContents() == XSWildcardDecl.PC_SKIP) {
-            return true;
-        }
-        qname.uri = ed.fTargetNamespace;
-        qname.localpart = ed.fName;
-        eb = getGlobalElementDecl(qname);
-        if (eb == null) {
-            // 2 G is lax and S is not skip.
-            return wb.getProcessContents() == XSWildcardDecl.PC_LAX;
-        }
-        else {
-            // 4 G and S are both Element Declarations and all of the following are true:
-            return checkEERestriction();
-        }
-    }
-
-    private boolean matchWildcardInBase() {
-        // For each wildcard in derived, subtract stronger elements first,
-        // then look for matches in base, in the order of element, wildcard,
-        // then open content.
-        
-        // Copy the derived wildcard into fields of this class, so that we can
-        // start subtract parts that have matches in the base.
-        // The strong elements are already stored in the "disallowed list"
-        // before this method is called.
-        copyDerivedWildcard();
-
-        // If this wildcard is the open content, also need to subtract all
-        // wildcard edges, because open content is weaker than the wildcards.
-        if (derived.isOpenContent(wd)) {
-            int[] idx = new int[1];
-            idx[0] = -1;
-            XSWildcardDecl wd1;
-            // Subtract all wildcard edges. Stop if the wildcard becomes empty
-            while (!emptyWildcard() && (wd1 = derived.nextWildcardTransition(d, dn, idx)) != null) {
-                if (wd1 != wd) {
-                    subtractWildcard(wd1, true);
-                }
-            }
-        }
-        
-        // Go through all base element transitions
-        indexb[0] = -1;
-        while ((eb = base.nextElementTransition(b, bn, indexb)) != null) {
-            // True: good match; False: bad match; null: no match
-            Boolean res = checkWERestriction();
-            if (res != null) {
-                if (!res.booleanValue()) {
-                    return false;
-                }
-                else {
-                    // The base element name is added to the disallow list
-                    // in checkWERestriction();
-                    // Add good match to the state pair list
-                    addState();
-                }
-            }
-            // Also attempt to match sub-group members in base. Same process.
-            if (eb.getScope() == XSConstants.SCOPE_GLOBAL) {
-                XSElementDecl[] ebs = sgh.getSubstitutionGroup(eb, Constants.SCHEMA_VERSION_1_1);
-                for (int j = 0; j < ebs.length; j++) {
-                    this.eb = ebs[j];
-                    res = checkWERestriction();
-                    if (res != null) {
-                        if (!res.booleanValue()) {
-                            return false;
-                        }
-                        else {
-                            addState();
-                        }
-                    }
-                }
-            }
-        }
-
-        // Now go through all base wildcard transitions
-        indexb[0] = -1;
-        while (!emptyWildcard() && (wb = base.nextWildcardTransition(b, bn, indexb)) != null) {
-            // Returns whether there was any overlap that got subtracted
-            if (subtractWildcard(wb, false)) {
-                // If there was overlap (match), check "process contents"
-                if (wd.weakerProcessContents(wb)) {
-                    return false;
-                }
-                // Add good match to the state pair list
-                addState();
-            }
-        }
-        
-        // The emtire wildcard must have been matched. If there's anything left,
-        // it's allowed by derived but not base. Error.
-        if (!emptyWildcard()) {
-            return false;
-        }
-        
-        return true;
-    }
-    
-    // Base element and derived wildcard.
-    // True: good match; False: bad match; null: no match
-    private Boolean checkWERestriction() {
-        // Whether element name is allowed by the wildcard
-        if (!allowName(eb.fTargetNamespace, eb.fName)) {
-            return null;
-        }
-        // Skip wildcard in derived can't restrict element in base.
-        if (wd.fProcessContents == XSWildcardDecl.PC_SKIP) {
-            return Boolean.FALSE;
-        }
-        // Must be able to find a global decl. Otherwise wildcard in derived
-        // can't restrict element in base.
-        ed = getGlobalElementDecl(qname);
-        if (ed == null) {
-            return Boolean.FALSE;
-        }
-        // The global element decl must match the base element
-        if (ed != eb && !checkEERestriction()) {
-            return Boolean.FALSE;
-        }
-        // Good match. Subtract the name from the wildcard.
-        wDNList.add(eb.fTargetNamespace);
-        wDNList.add(eb.fName);
-        return Boolean.TRUE;
-    }
-
-    // Subtract the specified wildcard from the wildcard in this class.
-    // Returns whether the 2 wildcards had any overlap.
-    private boolean subtractWildcard(XSWildcardDecl wc, boolean isDerived) {
-        boolean changed = false;
-        
-        // Because of UPA, it's not possible to add a name to the allowed list
-        // when subtracting a wildcard, then remove that same name when
-        // subtracting another wildcard, except for when the second wildcard
-        // is the open content. So only need to clear the allowed list
-        // when subtracting the open content.
-        // Also because open content is the last wildcard to subtract, all
-        // allowed names must be allowed by the base open content. If there is
-        // a name that's not allowed, we can return quickly, leaving this
-        // wildcard as non-empty, which will cause an error later.
-        if (!isDerived && base.isOpenContent(wc) && wANList.size() > 0) {
-            for (int i = 0; i < wANList.size();) {
-                qname.uri = (String)wANList.get(i++);
-                qname.localpart = (String)wANList.get(i++);
-                // A name allowed by derived wildcard but not by base open
-                // content. Quick return and detect the error later.
-                if (!base.allowExpandedName(wc, qname, sgh, this)) {
-                    return false;
-                }
-            }
-            // All allowed names have base matches. Clear them.
-            wANList.clear();
-            changed = true;
-        }
-
-        // First add "disallowedNames" in "sub" to the allowed list.
-        
-        // All disallowed names in the "sub" wildcard are added as allowed names
-        // if they are allowed by this wildcard.
-        int count = wc.fDisallowedNamesList == null ? 0 : wc.fDisallowedNamesList.length;
-        for (int i = 0; i < count; i++) {
-            addAN(wc.fDisallowedNamesList[i].uri, wc.fDisallowedNamesList[i].localpart);
-        }
-        // If "sub" wildcard has ##defined, and this doesn't, add all global
-        // element names to the allowed list, if this wildcard allows them.
-        if (wc.fDisallowedDefined && !wDD) {
-            if (globals == null) {
-                getGlobalElements();
-            }
-            for (int i = 0; i < globals.size();) {
-                String ns = (String)globals.get(i++);
-                String name = (String)globals.get(i++);
-                if (wc.allowNamespace(ns)) {
-                    addAN(ns, name);
-                }
-            }
-        }
-        // If "sub" wildcard has ##sibling
-        if (wc.fDisallowedSibling) {
-            if (!isDerived) {
-                // Add all names known to the base to the allowed list
-                if (siblingsB == null) {
-                    getBaseSiblings();
-                }
-                for (int i = 0; i < siblingsB.size();) {
-                    String ns = (String)siblingsB.get(i++);
-                    String name = (String)siblingsB.get(i++);
-                    if (wc.allowNamespace(ns)) {
-                        addAN(ns, name);
-                    }
-                }
-            }
-            else if (!wDS){
-                // If "sub" is also from derived, don't need to subtract
-                // if this wildcard also has ##sibling. Otherwise add all
-                // known names in derived to the allowed list
-                if (siblingsD == null) {
-                    getDerivedSiblings();
-                }
-                for (int i = 0; i < siblingsD.size();) {
-                    String ns = (String)siblingsD.get(i++);
-                    String name = (String)siblingsD.get(i++);
-                    if (wc.allowNamespace(ns)) {
-                        addAN(ns, name);
-                    }
-                }
-            }
-        }
-        
-        // Now deal with namespace. "sub" is any, remove all namespaces.
-        if (wc.getConstraintType() == XSWildcardDecl.NSCONSTRAINT_ANY) {
-            wType = XSWildcardDecl.NSCONSTRAINT_LIST;
-            wNSList.clear();
-            return true;
-        }
-
-        if (wc.getConstraintType() == XSWildcardDecl.NSCONSTRAINT_NOT) {
-            // both "sub" and this are "not". Only keep namespaces in "sub"'s
-            // "not" list but not in my "not" list.
-            if (wType == XSWildcardDecl.NSCONSTRAINT_NOT) {
-                wType = XSWildcardDecl.NSCONSTRAINT_LIST;
-                wNSListTemp.clear();
-                for (int i = 0; i < wc.fNamespaceList.length; i++) {
-                    if (!wNSList.contains(wc.fNamespaceList[i])) {
-                        wNSListTemp.add(wc.fNamespaceList[i]);
-                    }
-                }
-                wNSList.clear();
-                wNSList.addAll(wNSListTemp);
-                return true;
-            }
-
-            // This is "list" and "sub" is "not". Only namespaces in "sub"'s
-            // "not" list and also in my "yes" list.
-            wNSListTemp.clear();
-            for (int i = 0; i < wc.fNamespaceList.length; i++) {
-                if (wNSList.contains(wc.fNamespaceList[i])) {
-                    wNSListTemp.add(wc.fNamespaceList[i]);
-                }
-            }
-
-            // No namespace was removed.
-            if (wNSList.size() == wNSListTemp.size()) {
-                return changed;
-            }
-            
-            // Some namespaces were removed.
-            wNSList.clear();
-            wNSList.addAll(wNSListTemp);
-            
-            return true;
-        }
-        
-        if (wType == XSWildcardDecl.NSCONSTRAINT_NOT) {
-            // "sub" is list, this is "not". Add "sub"'s list to my "not" list.
-            for (int i = 0; i < wc.fNamespaceList.length; i++) {
-                if (!wNSList.contains(wc.fNamespaceList[i])) {
-                    wNSList.add(wc.fNamespaceList[i]);
-                    changed = true;
-                }
-            }
-        }
-        else {
-            // Both are lists. Remove "sub"'s list from my list.
-            for (int i = 0; i < wc.fNamespaceList.length; i++) {
-                if (wNSList.remove(wc.fNamespaceList[i])) {
-                    changed = true;
-                }
-            }
-        }
-
-        return changed;
-    }
-
-    // For each pair of matching states, if derived is final, base must be final.
-    private boolean checkFinalStates() {
-        for (int i = 0 ; i < states.size(); i++) {
-            StatePair sp = (StatePair)states.get(i);
-            sp.getStates(b, d);
-            if (derived.endContentModel(d) && !base.endContentModel(b)) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    // A pair of base/derived states.
-    private static class StatePair {
-        private int[] states;
-        public StatePair(int[] b, int[] d) {
-            this.states = new int[b.length + d.length];
-            System.arraycopy(b, 0, states, 0, b.length);
-            System.arraycopy(d, 0, states, states.length - d.length, d.length);
-        }
-        private void set(int[] b, int[] d) {
-            System.arraycopy(b, 0, states, 0, b.length);
-            System.arraycopy(d, 0, states, states.length - d.length, d.length);
-        }
-        private void getStates(int[] b, int[] d) {
-            System.arraycopy(states, 0, b, 0, b.length);
-            System.arraycopy(states, states.length - d.length, d, 0, d.length);
-        }
-        // Equal objects must have same hash code
-        public int hashCode() {
-            return Arrays.hashCode(states);
-        }
-        // it equals to another object if and only if they both have the same
-        // base and derived states
-        public boolean equals(Object o) {
-            if (!(o instanceof StatePair))
-                return false;
-            StatePair sp = (StatePair)o;
-            return Arrays.equals(states, sp.states);
-        }
-    }
-
-    // Optimization for when derived is "all", to avoid turning it into DFA
-    private Boolean checkAllDerived() {
-        // Derived is "all"; base is empty
-        if (base instanceof XSEmptyCM) {
-            Boolean ret = checkAllEmpty();
-            if (ret != null) {
-                return ret;
-            }
-            // Base must be an empty with open content. It's turned into an
-            // all with open content. Fall through.
-        }
-
-        if (base instanceof XS11AllCM) {
-            // Both are "all"
-            allb = (XS11AllCM)base;
-            // True: valid; False; invalid: null: check further
-            Boolean ret = checkAllAll();
-            // Even thought checkAllAll() didn't give a definitive answer, it
-            // may have simplified the content models. Use the new ones.
-            if (ret == null) {
-                base = allb;
-                derived = alld;
-                // Treating the all derived as DFA. Check whether that'll
-                // consume too much memory.
-                cmb.testOccurrences(alld.calOccurs());
-            }
-            return ret;
-        }
-        else { // if (base instanceof XSDFACM)
-            // Derived is "all"; base is DFA
-            dfab = (XSDFACM)base;
-            // True: valid; False; invalid: null: check further
-            Boolean ret = checkAllDFA();
-            // Even thought checkAllDFA() didn't give a definitive answer, it
-            // may have simplified the content models. Use the new ones.
-            if (ret == null) {
-                base = dfab;
-                derived = alld;
-                // Treating the all derived as DFA. Check whether that'll
-                // consume too much memory.
-                cmb.testOccurrences(alld.calOccurs());
-            }
-            return ret;
-        }
-    }
-
-    private Boolean checkAllEmpty() {
-        // If base (empty) has an open content, turn it into an "all".
-        int[] idx = new int[]{-1};
-        if (base.nextWildcardTransition(b, bn, idx) != null) {
-            base = new XS11AllCM(false, 0, null, ((XSEmptyCM)base).getOpenContent());
-            return null;
-        }
-        // Base allows nothing. Derived must be empty too.
-        return Boolean.valueOf(derived.nextElementTransition(d, dn, idx) == null &&
-                derived.nextWildcardTransition(d, dn, idx) == null);
-    }    
-
-    // Optimize for the common case where base has elements and derived has
-    // same-named elements. Try to reduce occurrence from derive, or remove
-    // the elements entirely. Don't try too hard for wildcards.
-    private Boolean checkAllAll() {
-        if (allb.getOpenContent() != null &&
-                allb.getOpenContent().fMode == XSOpenContentDecl.MODE_SUFFIX &&
-                alld.getOpenContent() != null &&
-                alld.getOpenContent().fMode == XSOpenContentDecl.MODE_INTERLEAVE) {
-            // Base (e)+suffix, derived (e)+interleave. If we remove "e", we
-            // may think the derivation is OK. Don't optimize. Fall back.
-            return null;
-        }
-
-        if (siblingsD == null) {
-            getDerivedSiblings();
-        }
-
-        // TODO
-//        List excludedUnboundedElementsCopy = new ArrayList();
-//        indexd[0] = -1;
-//        while ((ed = derived.nextElementTransition(d, dn, indexd)) != null) {
-//            if (alld.isUnbounded(indexd[0])) {
-//                excludedUnboundedElementsCopy.add(ed.fTargetNamespace);
-//                excludedUnboundedElementsCopy.add(ed.fName);
-//            }
-//            if (ed.getScope() == XSConstants.SCOPE_GLOBAL) {
-//                XSElementDecl[] eds = sgh.getSubstitutionGroup(ed, Constants.SCHEMA_VERSION_1_1);
-//                for (int i = 0; i < eds.length; i++) {
-//                    if (alld.isUnbounded(indexd[0])) {
-//                        excludedUnboundedElementsCopy.add(ed.fTargetNamespace);
-//                        excludedUnboundedElementsCopy.add(ed.fName);
-//                    }
-//                }
-//            }
-//        }
-        
-        if (alld.hasOptionalContent()) {
-            if (!checkOptionalContent()) {
-                return Boolean.FALSE;
-            }
-        }
-        else if (allb.hasOptionalContent()) {
-            // base: (a&)? derived: (a?&) should be OK.
-            // Not easy to detect; fall back
-            return null;
-        }
-
-        // We've dealt with open content and optional content mismatches.
-        // Now we can start reducing element occurrences. Ideally to 0.
-        
-        // The following scenario is safe to be reduced. Not sure about others.
-        // 1. A base element B matches one or more derived elements
-        // 2. B doesn't match any of the derived wildcards
-        // 3. B matches the entirety of the derived elements. As a consequence,
-        //    the derived elements don't match any other base element.
-        // 4.1 B matches exactly one derived element, or
-        // 4.2 B has big enough maxOccurs for all derived elements.
-        // Then we can remove the base element and all the derived ones.
-        // #2 is so that we don't need to worry about
-        //    base: ((ns1:a|ns2:b) & ns2:*) derived (ns1:a & ns2:*)
-        // #3 is so that we don't need to worry about
-        //    base: ((a|b) & c) derived (a & (b|c))
-        // #4 is so that we don't need to worry about
-        //    base: ((a|b) & *) derived (a & b & *)
-        //    but this is OK: (a & *) derived (a{2} & *)
-        // We don't need to worry about if derived elements also match base
-        // wildcard, because the wildcard is weaker and the derived element
-        // always matches the base element (which has sufficient maxOccurs).
-        
-        // TODO: we may be able to do more, but element-element should be the
-        // common case. May want to consider wildcard-element and
-        // wildcard-wildcard, but need to take into account elements that may
-        // have made the wildcards weaker.
-        // e.g. reduce wildcards? open content?
-        // e.g. base (wc*&) derived (e1&e2...) optimize
-        
-        // For each derived element, -1: initial; -2: no matching base element;
-        // >= 0 index of matching base element
-        int[] matchD = derived.startContentModel();
-        // For each base element: 0: not used; < 0: can't be used;
-        // > 0: number of derived elements that match this base element
-        int[] usedB = base.startContentModel();
-        indexd[0] = -1;
-        while ((ed = derived.nextElementTransition(d, dn, indexd)) != null) {
-            // For each derived element, try to find matching base elements.
-            // Checking #1 and #3 above.
-            matchD[indexd[0]] = -1;
-            matchedHead = false;
-            if (!matchEE(matchD, usedB)) {
-                // Bad match, return the error immediately
-                return Boolean.FALSE;
-            }
-            if (!matchedHead) {
-                if (ed.getScope() == XSConstants.SCOPE_GLOBAL) {
-                    XSElementDecl[] eds = sgh.getSubstitutionGroup(ed, Constants.SCHEMA_VERSION_1_1);
-                    for (int i = 0; i < eds.length; i++) {
-                        ed = eds[i];
-                        if (!matchEE(matchD, usedB)) {
-                            // Bad match, return the error immediately
-                            return Boolean.FALSE;
-                        }
-                    }
-                }
-            }
-        }
-        
-        // Match derived wildcards with base elements, to make sure #2 above
-        // is satisfied.
-        // The wildcards are weaker than elements. Remove element names.
-        wDNList.clear();
-        wDNList.addAll(siblingsD);
-        indexd[0] = -1;
-        while ((wd = derived.nextWildcardTransition(d, dn, indexd)) != null) {
-            if (!matchWE(usedB)) {
-                // Bad match, return the error immediately
-                return Boolean.FALSE;
-            }
-        }
-        
-        // Now gather maxOccurs from derived to check for #4
-        // For each base element, take the sum of all matching derived elements.
-        int[] min = base.startContentModel(), max = base.startContentModel();
-        indexd[0] = -1;
-        while ((ed = derived.nextElementTransition(d, dn, indexd)) != null) {
-            indexb[0] = matchD[indexd[0]];
-            if (indexb[0] >= 0) {
-                alld.collectOccurs(min, max, indexb[0], indexd[0]);
-            }
-        }
-        
-        // About to reduce min/maxOccurs. Make a copy of the content models.
-        allb = allb.copy();
-        alld = alld.copy();
-        // Check whether the base can accommodate the total of the derived.
-        if (!allb.removeAsBase(min, max, usedB)) {
-            // If the base has more minOccurs than sum of derived, then
-            // bad derivation. The minOccurs can't be satisfied by other
-            // components (i.e wildcards), because the wildcards can take
-            // names other than that of the base element.
-            return Boolean.FALSE;
-        }
-        // For those that pass #4, remove corresponding derived elements.
-        alld.removeAsDerived(max, usedB, matchD);
-
-        // Whatever is left will be handled by the default DFA path.
-        return null;
-    }
-    private boolean checkOptionalContent() {
-        // Called when derived has optional content (a & b)?, so allows empty.
-        // Need to make sure that
-        // 1. Base also allowed the empty sequence
-        // 2. If derived allows the first element to match the open content,
-        //    leaving the "all" content as empty, then base doesn't match that
-        //    element using an entry in the "all" content and require other
-        //    things in the "all" content to also be present.
-        
-        // Check #1: Make sure base also allows empty.
-        int totalMin = allb.totalMin();
-        if (!allb.hasOptionalContent() && totalMin != 0) {
-            return false;
-        }
-
-        // If derived doesn't have an open content, don't need to check #2.
-        XSOpenContentDecl oc = alld.getOpenContent();
-        wd = oc == null ? null : oc.fWildcard;
-        if (wd == null) {
-            return true;
-        }
-        
-        // Calculate the effective open content for first element, by
-        // subtracting all elements/wildcards from the "all" content.
-        wDNList.clear();
-        wDNList.addAll(siblingsD);
-        copyDerivedWildcard();
-        int[] idx = new int[1];
-        idx[0] = -1;
-        XSWildcardDecl wd1;
-        while (!emptyWildcard() && (wd1 = derived.nextWildcardTransition(d, dn, idx)) != null) {
-            if (wd1 != wd) {
-                subtractWildcard(wd1, true);
-            }
-        }
-        // If the "first element" open content is empty, don't need #2.
-        if (emptyWildcard()) {
-            return true;
-        }
-
-        // Now "first element" open content is not empty, need to check whether
-        // it matches any element/wildcard in base "all" content. If it does,
-        // then the matching component must not have min>1 and all the other
-        // components must have min=0, to not impose more "required" elements.
-        indexb[0] = -1;
-        while ((eb = base.nextElementTransition(b, bn, indexb)) != null) {
-            int min = allb.min(indexb[0]);
-            if (allowName(eb.fTargetNamespace, eb.fName)) {
-                // This element matches the derived open content. Make sure
-                // no additional elements are required.
-                if (min > 1 || min < totalMin) {
-                    return false;
-                }
-                // No need to check sub-group, as they have same "min".
-                continue;
-            }
-            if (eb.getScope() == XSConstants.SCOPE_GLOBAL) {
-                XSElementDecl[] ebs = sgh.getSubstitutionGroup(eb, Constants.SCHEMA_VERSION_1_1);
-                for (int j = 0; j < ebs.length; j++) {
-                    this.eb = ebs[j];
-                    if (allowName(eb.fTargetNamespace, eb.fName)) {
-                        // This element matches the derived open content. Make
-                        // sure no additional elements are required.
-                        if (min > 1 || min < totalMin) {
-                            return false;
-                        }
-                        break;
-                    }
-                }
-            }
-        }
-
-        // Now match "first element" open content with base wildcards.
-        indexb[0] = -1;
-        while ((wb = base.nextWildcardTransition(b, bn, indexb)) != null) {
-            if (!base.isOpenContent(wb) && overlap()) {
-                int min = allb.min(indexb[0]);
-                // This wildcards matches the derived open content. Make
-                // sure no additional elements are required.
-                if (min > 1 || min < totalMin) {
-                    return false;
-                }
-            }
-        }
-        
-        // Now we are certain that when the derived optional "all" content
-        // is not used, the base do not have any required element.
-        return true;
-    }
-    private boolean overlap() {
-        // Check whether the derived open content wildcard overlaps with the
-        // base wildcard "wb".
-        
-        // Overlap if names in the allowed list are allowed by "wb".
-        for (int i = 0; i < wANList.size();) {
-            qname.uri = (String)wANList.get(i++);
-            qname.localpart = (String)wANList.get(i++);
-            if (base.allowExpandedName(wb, qname, sgh, this)) {
-                return true;
-            }
-        }
-        // Overlap if namespaces overlap.
-        // Both are any/not. Always overlap.
-        if (wType == XSWildcardDecl.NSCONSTRAINT_ANY ||
-                wb.fType == XSWildcardDecl.NSCONSTRAINT_ANY ||
-                wType == XSWildcardDecl.NSCONSTRAINT_NOT &&
-                wb.fType == XSWildcardDecl.NSCONSTRAINT_NOT) {
-            return true;
-        }
-        // Both are lists. Overlap if the namespace lists overlap.
-        if (wType == XSWildcardDecl.NSCONSTRAINT_LIST &&
-                wb.fType == XSWildcardDecl.NSCONSTRAINT_LIST) {
-            for (int i = 0; i < wb.fNamespaceList.length; i++) {
-                if (wNSList.contains(wb.fNamespaceList[i])) {
-                    return true;
-                }
-            }
-            return false;
-        }
-        // Derived is "not" and "wb" is list. Overlap if a namespace in "wb"
-        // list is not excluded from derived.
-        if (wType == XSWildcardDecl.NSCONSTRAINT_NOT) {
-            for (int i = 0; i < wb.fNamespaceList.length; i++) {
-                if (!wNSList.contains(wb.fNamespaceList[i])) {
-                    return true;
-                }
-            }
-            return false;
-        }
-        // Derived is list and "wb" is "not". Overlap if a namespace in derived
-        // list is not excluded from "wb".
-        for (int i = 0; i < wNSList.size(); i++) {
-            String ns = (String)wNSList.get(i);
-            int j = 0;
-            for (; j < wb.fNamespaceList.length; j++) {
-                if (ns == null && wb.fNamespaceList[j] == null ||
-                    ns != null && ns.equals(wb.fNamespaceList[j])) {
-                    break;
-                }
-            }
-            // A namespace in "derived" is not excluded from "wb". Overlap.
-            if (j == wb.fNamespaceList.length) {
-                return true;
-            }
-        }
-        return false;
-    }
-    // Similar to findElementInBase, but need to handle the match/used arrays.
-    private boolean matchEE(int[] matchD, int[] usedB) {
-        // Look for a base element to match "ed"
-        int id = indexd[0];
-        indexb[0] = -1;
-        while ((eb = base.nextElementTransition(b, bn, indexb)) != null) {
-            int ib = indexb[0];
-            if (eb.getName() == ed.getName() && eb.getNamespace() == ed.getNamespace()) {
-                // If derived had a match before, e.g. its sub-group member
-                // matched an element before, and the head now also matches
-                // an element. Then make sure the 2 base element are the same,
-                // otherwise we break #3: same derived different base.
-                if (matchD[id] != -1 && matchD[id] != ib) {
-                    // Mark both base elements as "not usable".
-                    usedB[matchD[id]] = -1;
-                    usedB[ib] = -1;
-                    // This derived element isn't usable either. Return.
-                    // But this is not an error, so return true.
-                    return true;
-                }
-                // Need to make sure the base is usable.
-                if (usedB[ib] < 0) {
-                    // Remember that the derived element had a match.
-                    // In case this element matches a different base,
-                    // then we know we need to mark that other base
-                    // as not usable.
-                    matchD[id] = ib;
-                    return true;
-                }
-                // Record the match.
-                if (matchD[id] == -1) {
-                    matchD[id] = ib;
-                    // Remember how many matches the base element has.
-                    // Only do so if this is the first match, so that we only
-                    // count each base element once.
-                    usedB[ib]++;
-                }
-                // Head match. No need to check sub-group members.
-                matchedHead = eb == ed;
-                // Must satisfy other element-element restriction requirements.
-                return checkEERestriction();
-            }
-            else {
-                // if the name doesn't match, try its sub group elements
-                XSElementDecl[] ebs = sgh.getSubstitutionGroup(eb, Constants.SCHEMA_VERSION_1_1);
-                for (int i = 0; i < ebs.length; i++) {
-                    // found a name match, check properties of the decls
-                    if (ebs[i].getName() == ed.getName() &&
-                            ebs[i].getNamespace() == ed.getNamespace()) {
-                        if (matchD[id] != -1 && matchD[id] != ib) {
-                            // #3: Same derived matches multiple base.
-                            // Mark both base elements as "not usable".
-                            if (matchD[id] >= 0) {
-                                usedB[matchD[id]] = -1;
-                            }
-                            usedB[ib] = -1;
-                            // This derived element isn't usable either. Return.
-                            // But this is not an error, so return true.
-                            return true;
-                        }
-                        // Need to make sure the base is usable.
-                        if (usedB[ib] < 0) {
-                            // Remember that the derived element had a match.
-                            // In case this element matches a different base,
-                            // then we know we need to mark that other base
-                            // as not usable.
-                            matchD[id] = ib;
-                            return true;
-                        }
-                        // Record the match. Also need to make sure the base is usable.
-                        if (matchD[id] == -1) {
-                            matchD[id] = ib;
-                            // Remember how many matches the base element has.
-                            // Only do so if this is the first match, so that we only
-                            // count each base element once.
-                            usedB[ib]++;
-                        }
-                        eb = ebs[i];
-                        return checkEERestriction();
-                    }
-                }
-            }
-        }
-        // Derived element has no match in base.
-        if (matchD[id] >= 0) {
-            // If this element had a match, then #3 is not satisfied.
-            // Mark the base as not usable.
-            usedB[matchD[id]] = -1;
-        }
-        // Remember the fact that this element had a no-match. If we find a
-        // match for it (its sub-group member) later, need to mark the matching
-        // base as not usable.
-        matchD[id] = -2;
-        
-        return true;
-    }
-    // Similar to matchWildcardInBase, but only deal with base element,
-    // and need to handle the used array.
-    private boolean matchWE(int[] usedB) {
-        indexb[0] = -1;
-        while ((eb = base.nextElementTransition(b, bn, indexb)) != null) {
-            int ib = indexb[0];
-            // Only interested in base elements that had derived matches.
-            // Other elements will be handled when we fall back to DFA.
-            if (usedB[ib] <= 0) {
-                continue;
-            }
-            // True: good match; False: bad match; null: no match
-            Boolean res = checkWERestriction();
-            if (res != null) {
-                if (!res.booleanValue()) {
-                    return false;
-                }
-                else {
-                    // Same base element matches both element and wildcard
-                    // in derived. Fallback to DFA.
-                    usedB[ib] = -1;
-                    return true;
-                }
-            }
-
-            // No match. Look at sub-group
-            if (eb.getScope() == XSConstants.SCOPE_GLOBAL) {
-                XSElementDecl[] ebs = sgh.getSubstitutionGroup(eb, Constants.SCHEMA_VERSION_1_1);
-                for (int i = 0; i < ebs.length; i++) {
-                    this.eb = ebs[i];
-                    res = checkWERestriction();
-                    if (res != null) {
-                        if (!res.booleanValue()) {
-                            return false;
-                        }
-                        else {
-                            // Same base element matches both element and wildcard
-                            // in derived. Fallback to DFA.
-                            usedB[ib] = -1;
-                            return true;
-                        }
-                    }
-                }
-            }
-        }
-        return true;
-    }
-    
-    private Boolean checkAllDFA() {
-        // Don't optimize for this case yet. It's a strange derivation to
-        // restrict a sequence/choice content model to an "all".
-        return null;
-    }    
-
-}
+/*
+ * 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 org.apache.xerces.impl.xs.models;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.xerces.impl.Constants;
+import org.apache.xerces.impl.xs.SchemaGrammar;
+import org.apache.xerces.impl.xs.SubstitutionGroupHandler;
+import org.apache.xerces.impl.xs.XSConstraints;
+import org.apache.xerces.impl.xs.XSElementDecl;
+import org.apache.xerces.impl.xs.XSElementDeclHelper;
+import org.apache.xerces.impl.xs.XSGrammarBucket;
+import org.apache.xerces.impl.xs.XSOpenContentDecl;
+import org.apache.xerces.impl.xs.XSWildcardDecl;
+import org.apache.xerces.impl.xs.identity.IdentityConstraint;
+import org.apache.xerces.xni.QName;
+import org.apache.xerces.xs.XSComplexTypeDefinition;
+import org.apache.xerces.xs.XSConstants;
+import org.apache.xerces.xs.XSNamedMap;
+import org.apache.xerces.xs.XSSimpleTypeDefinition;
+import org.apache.xerces.xs.XSTypeDefinition;
+
+/**
+    // TODO: tests:
+    // * base all: (e, w?)?; derived all: (e)? w. Should be invalid <e1/>
+    // * base all: (e/f, w); derived all: (e, w)
+    // * base: e|w(lax) + w(skip), derived: w(lax) + w(skip)
+            // Example test:
+            // Bad: base: ((a|b)&) derived: (a & b).
+            // derive allow a,b, base doesn't.
+            // Bad: base: ((ns1:a|ns2:b) & ns1:*) derived: (ns1:a & ns2:b).
+            // derive allow a,b, base doesn't.
+            // Good: base: ((ns1:a|ns2:b) & ns1:*? & ns2:*?) derived: (ns1:a & ns2:b).
+            // base: (a{2} & *), derived: (a & *)
+    
+ * @version $Id$
+ */
+public final class XS11CMRestriction implements XSElementDeclHelper {
+    private final SubstitutionGroupHandler sgh;
+    private final XSGrammarBucket gb;
+    private final CMBuilder cmb;
+    private final XSConstraints xsc;
+    
+    // Content models to be checked
+    private XS11CM base, derived;
+    // Used when both base and derived are "all" groups
+    private XS11AllCM allb, alld;
+    // Used when base is "dfa" and derived is "all"
+    private XSDFACM dfab;
+
+    // Temporary QName object
+    private QName qname = new QName();
+
+    // Pairs of matching states from base and derived.
+    private List states = new ArrayList();
+    // A pair of matching states.
+    private StatePair pair = null;
+
+    // The following field represents a wildcard. It's typically a wildcad
+    // from the derived type. We keep subtract matching components in the base
+    // from this wildcard.
+    private short wType;
+    private List wNSList = new ArrayList();
+    private List wNSListTemp = new ArrayList();
+    // Disallowed name list
+    private List wDNList = new ArrayList();
+    // ##sibling and ##defined
+    private boolean wDD, wDS;
+    // Allowed name list, used after subtracting a disallowed list.
+    private List wANList = new ArrayList();
+
+    // List of QNames used for ##sibling and ##defined checking
+    private List globals;
+    private List siblingsB;
+    private List siblingsD;
+
+    // Element/wildcard decls in base and derived
+    private XSElementDecl eb, ed;
+    private XSWildcardDecl wb, wd;
+    // Current/next states in base and derived.
+    private int[] b, bn, d, dn;
+    // Index of the previously matched decl in base and derived, so that we
+    // know where to continue.
+    private int[] indexb = new int[1], indexd = new int[1];
+    // Optimization. If an element declaration in derived is the same as an
+    // element declaration in base without using any substitution group, then
+    // we don't need to dig into the sub-groups. They will be the same.
+    private boolean matchedHead;
+
+    // Interface implemented by the content model classes
+    interface XS11CM extends XSCMValidator {
+        // Find the next possible element transition.
+        // "s" is the current state, "sn" is the next state after the transition,
+        // "index" has info about where to start looking, and stores the index
+        // of the new declaration if one is found, or -1.
+        // Returns the matching decl, or null.
+        public XSElementDecl nextElementTransition(int[] s, int[] sn, int[] index);
+        // Find the next possible wildcard transition, including open content.
+        public XSWildcardDecl nextWildcardTransition(int[] s, int[] sn, int[] index);
+        // Check whether a matched wildcard is an open content.
+        public boolean isOpenContent(XSWildcardDecl w);
+        // Check whether a QName is allowed by a wildcard in the content model.
+        // Need to check namespace, local name, ##sibling, and ##defined.
+        public boolean allowExpandedName(XSWildcardDecl wildcard,
+                QName name, SubstitutionGroupHandler sgh,
+                XSElementDeclHelper edh);
+        // Get the list of names known to the content model, for ##sibling.
+        public List getDefinedNames(SubstitutionGroupHandler sgh);
+        // Before putting a pair of states into the list, give the content
+        // model a chance to optimize. If a set of states can be folded into
+        // a single one, the content model can change the state int arrays
+        // to represent the one state. e.g. if both base and derived have
+        // the same element declaration with the same min/maxOccurs information,
+        // then we don't have to have many different states.
+        // Currently this is only implemented by DFA.
+        public void optimizeStates(XS11CM base, int[] b, int[] d, int indexb);
+    }
+    
+    public XS11CMRestriction(XSCMValidator base, XSCMValidator derived,
+            SubstitutionGroupHandler sgh, XSGrammarBucket gb,
+            CMBuilder cmb, XSConstraints xsc) {
+        this.base = (XS11CM)base;
+        this.derived = (XS11CM)derived;
+        this.sgh = sgh;
+        this.gb = gb;
+        this.cmb = cmb;
+        this.xsc = xsc;
+    }
+
+    // Helper: add a pair of states to the list, if such pair is not already
+    // in the list.
+    private void addState() {
+        // Optimize the states when possible.
+        derived.optimizeStates(base, bn, dn, indexb[0]);
+        // Reuse the "pair" object
+        if (pair == null) {
+            pair = new StatePair(bn, dn);
+        }
+        else {
+            pair.set(bn, dn);
+        }
+        // Only add if the pair isn't already in the list
+        if (!states.contains(pair)) {
+            states.add(pair);
+            pair = null;
+        }
+    }
+
+    // Helper: copy a derived wildcard to fields of this class.
+    private void copyDerivedWildcard() {
+        wType = wd.fType;
+        wDD = wd.fDisallowedDefined;
+        wDS = wd.fDisallowedSibling;
+        wNSList.clear();
+        if (wType == XSWildcardDecl.NSCONSTRAINT_ANY) {
+            // "any" is the same as "not" + empty namespace list.
+            wType = XSWildcardDecl.NSCONSTRAINT_NOT;
+        }
+        else {
+            int size = wd.fNamespaceList == null ? 0 : wd.fNamespaceList.length;
+            for (int i = 0; i < size; i++) {
+                wNSList.add(wd.fNamespaceList[i]);
+            }
+        }
+        // Copy disallowed name list
+        // Don't clear, because the list is pre-populated with element names
+        int size = wd.fDisallowedNamesList == null ? 0 : wd.fDisallowedNamesList.length;
+        for (int i = 0; i < size; i++) {
+            wDNList.add(wd.fDisallowedNamesList[i].uri);
+            wDNList.add(wd.fDisallowedNamesList[i].localpart);
+        }
+        // Allowed name list starts as empty
+        wANList.clear();
+    }
+
+    // Helper: add a name to the "allowed" list
+    private void addAN(String ns, String name) {
+        // Only add if it's allowed by the current wildcard
+        if (!allowNS(ns)) {
+            return;
+        }
+        // Only add if the name is not in the disallowed name list.
+        for (int i = 0; i < wDNList.size();) {
+            if (wDNList.get(i++) == ns && wDNList.get(i++) == name) {
+                return;
+            }
+        }
+        // Only add if the name is allowed by the wildcard in terms of
+        // ##sibling and ##defined.
+        qname.uri = ns;
+        qname.localpart = name;
+        if (!derived.allowExpandedName(wd, qname, sgh, this)) {
+            return;
+        }
+        // The name is allowed, add it.
+        wANList.add(ns);
+        wANList.add(name);
+    }
+
+    // Helper: check whether a namespace name is allowed by the wildcard
+    private boolean allowNS(String ns) {
+        return wType == XSWildcardDecl.NSCONSTRAINT_ANY ||
+               wType == XSWildcardDecl.NSCONSTRAINT_NOT && !wNSList.contains(ns) ||
+               wType == XSWildcardDecl.NSCONSTRAINT_LIST && wNSList.contains(ns);
+    }
+
+    // Helper: check whether a name is allowed by the current wildcard
+    private boolean allowName(String ns, String name) {
+        // Check namespace first
+        if (!allowNS(ns)) {
+            return false;
+        }
+        // Whether the name is in the disallowed list
+        for (int i = 0; i < wDNList.size(); i+=2) {
+            if (ns == wDNList.get(i) && name == wDNList.get(i+1)) {
+                return false;
+            }
+        }
+        // Whether the name is in the allowed list
+        for (int i = 0; i < wANList.size(); i+=2) {
+            if (ns == wANList.get(i) && name == wANList.get(i+1)) {
+                return true;
+            }
+        }
+        // Additional ##sibling and ##defined checks
+        qname.uri = ns;
+        qname.localpart = name;
+        return derived.allowExpandedName(wd, qname, sgh, this);
+    }
+
+    // Helper: whether the current wildcard is empty: allows nothing
+    private boolean emptyWildcard() {
+        // Only when the list of namespace and the list of allowed names are
+        // both empty.
+        return wType == XSWildcardDecl.NSCONSTRAINT_LIST &&
+        wNSList.size() == 0 && wANList.size() == 0;
+    }
+
+    // Helper: get all defined elements. For ##defined.
+    private void getGlobalElements() {
+        globals = new ArrayList();
+        SchemaGrammar[] sgs = gb.getGrammars();
+        for (int i = 0; i < sgs.length; i++) {
+            addGlobals(sgs[i]);
+        }
+    }
+
+    // Helper: get all defined elements in a given namespace. For ##defined.
+    private void addGlobals(SchemaGrammar g) {
+        XSNamedMap map = g.getComponents(XSConstants.ELEMENT_DECLARATION);
+        for (int i = 0; i < map.getLength(); i++) {
+            XSElementDecl e = (XSElementDecl)map.item(i);
+            globals.add(e.fTargetNamespace);
+            globals.add(e.fName);
+        }
+    }
+
+    // Helper: get all known names in the base content model. For ##sibling.
+    private void getBaseSiblings() {
+        siblingsB = base.getDefinedNames(sgh);
+    }
+
+    // Helper: get all known names in the derived content model. For ##sibling.
+    private void getDerivedSiblings() {
+        siblingsD = derived.getDefinedNames(sgh);
+    }
+    
+    // Helper: get a global element declaration with the specified name.
+    public XSElementDecl getGlobalElementDecl(QName name) {
+        SchemaGrammar sg = gb.getGrammar(name.uri);
+        return sg != null ? sg.getGlobalElementDecl(name.localpart) : null;
+    }
+
+    // Entry point: check the content models passed in to the constructor.
+    public boolean check() {
+        // Initialize the states. Needs this before the "derived is all" check,
+        // because these state arrays are always needed.
+        b = base.startContentModel();
+        bn = base.startContentModel();
+        d = derived.startContentModel();
+        dn = derived.startContentModel();
+
+        // If derived is all, then we may be able to do better than treating
+        // it as a DFA.
+        if (derived instanceof XS11AllCM) {
+            alld = (XS11AllCM)derived;
+            // True: valid; False: invalid; null: need further checking
+            Boolean res = checkAllDerived();
+            if (res != null) {
+                return res.booleanValue();
+            }
+        }
+
+        // Helper list to gather all names that can't match the wildcard
+        // in derived, because the wildcard is weaker than the elements.
+        List excludedElementsCopy = new ArrayList();
+
+        // For every state in derived, find the corresponding states in base.
+        // For each pair of corresponding states, make sure all transitions
+        // allowed by derived are also allowed by base. The target states
+        // are also treated as "corresponding states". Continue for all such
+        // pairs. When derived is at a final state, the corresponding state
+        // for base must also be a final state.
+
+        // Handling the list of state pairs as a list, not a stack.
+        // Otherwise we may pop a pair off the stack, but latter find the same
+        // pair, but there is no way to know we've already seen that pair.
+        
+        // the number of processed state pairs.
+        int pos = 0;
+        // initialize the unprocessed set: put initial states in it
+        StatePair p = new StatePair(b, d);
+        states.add(p);
+        // while there is unprocessed pair
+        while (pos < states.size()) {
+            StatePair sp = (StatePair)states.get(pos++);
+            sp.getStates(b, d);
+
+            // for all possible element edges
+            excludedElementsCopy.clear();
+            indexd[0] = -1;
+            while ((ed = derived.nextElementTransition(d, dn, indexd)) != null) {
+                // Add them to the "can't match wildcard name" list
+                excludedElementsCopy.add(ed.fTargetNamespace);
+                excludedElementsCopy.add(ed.fName);
+                if (ed.getScope() == XSConstants.SCOPE_GLOBAL) {
+                    XSElementDecl[] eds = sgh.getSubstitutionGroup(ed, Constants.SCHEMA_VERSION_1_1);
+                    for (int j = 0; j < eds.length; j++) {
+                        excludedElementsCopy.add(eds[j].fTargetNamespace);
+                        excludedElementsCopy.add(eds[j].fName);
+                    }
+                }
+                // Make sure this element is allowed by the base
+                if (!matchElementInBase()) {
+                    return false;
+                }
+            }
+
+            // for all possible wildcard edges
+            indexd[0] = -1;
+            while ((wd = derived.nextWildcardTransition(d, dn, indexd)) != null) {
+                // Put all the stronger element names in the disallowed list
+                wDNList.clear();
+                wDNList.addAll(excludedElementsCopy);
+                // And make sure the wildcard is allowed by the base
+                if (!matchWildcardInBase()) {
+                    return false;
+                }
+            }
+        }
+        
+        // We processed all state pairs. Now check final states.
+        return checkFinalStates();
+    }
+
+    // for an element and all elements in its sub group, check whether
+    // there are matching edges in the base.
+    private boolean matchElementInBase() {
+        matchedHead = false;
+        // Look for an element decl in the base
+        if (!findElementInBase()) {
+            // There is a route in the derived, but no matching
+            // route in the base. not a valid restriction.
+            return false;
+        }
+        // put this pair in the unprocessed states, if it's not there
+        addState();
+
+        // Same element decl as derived, no need to look at sub-group.
+        if (matchedHead) {
+            return true;
+        }
+
+        // get all sub group elements
+        XSElementDecl[] eds = sgh.getSubstitutionGroup(ed, Constants.SCHEMA_VERSION_1_1);
+        for (int i = 0; i < eds.length; i++) {
+            ed = eds[i];
+            // check whether there is a matching edge
+            if (!findElementInBase()) {
+                // if not, there is a route in the derived, but no matching
+                // route in the base. not a valid restriction.
+                return false;
+            }
+            // put this pair in the unprocessed states, if it's not there
+            addState();
+        }
+
+        return true;
+    }
+
+    // find the matching next state in the base
+    private boolean findElementInBase() {
+        // for all edges in the base that leaves the base state
+        // check whether it's an edge matching the base edge.
+        // if it is, return the next state.
+        indexb[0] = -1;
+        while ((eb = base.nextElementTransition(b, bn, indexb)) != null) {
+            // Base element edge, check whether it matches the derived element
+            if (matchElementWithBaseElement()) {
+                // If name matches, check type, nil, fixed etc.
+                return checkEERestriction();
+            }
+        }
+        // No matching element edge, try wildcards.
+        indexb[0] = -1;
+        while ((wb = base.nextWildcardTransition(b, bn, indexb)) != null) {
+            // Base wildcard edge, check whether it matches the derived element
+            qname.uri = ed.fTargetNamespace;
+            qname.localpart = ed.fName;
+            if (base.allowExpandedName(wb, qname, sgh, this)) {
+                // If name matches, check whether there is a matching global.
+                return checkEWRestriction();
+            }
+        }
+        return false;
+    }
+
+    // whether 2 element edges match
+    private boolean matchElementWithBaseElement() {
+        if (eb.getName() == ed.getName() && eb.getNamespace() == ed.getNamespace()) {
+            // The elements match without using sub-groups. Remember this fact
+            // so that we know we don't need to check sub-groups.
+            matchedHead = eb == ed;
+            return true;
+        }
+
+        // if the name doesn't match, try its sub group elements
+        XSElementDecl[] ebs = sgh.getSubstitutionGroup(eb, Constants.SCHEMA_VERSION_1_1);
+        for (int i = 0; i < ebs.length; i++) {
+            if (ebs[i].getName() == ed.getName() &&
+                ebs[i].getNamespace() == ed.getNamespace()) {
+                eb = ebs[i];
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean checkEERestriction() {
+        if (eb == ed) {
+            return true;
+        }
+        
+        // 4.1 Either G.{nillable} = true  or S.{nillable} = false.
+        if (!eb.getNillable() && ed.getNillable()) {
+            return false;
+        }
+
+        // 4.2 Either G has no {value constraint}, or it is not fixed,
+        // or S has a fixed {value constraint} with an equal value.
+        if (eb.getConstraintType() == XSConstants.VC_FIXED) {
+            // derived one has to have a fixed value
+            if (ed.getConstraintType() != XSConstants.VC_FIXED) {
+                return false;
+            }
+
+            // Get primitive kind for the fixed values. Use "string" for
+            // complex type with mixed content.
+            short btype, dtype;
+            if (eb.fType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
+                btype = ((XSSimpleTypeDefinition)eb.fType).getPrimitiveType().getBuiltInKind();
+            }
+            else {
+                XSComplexTypeDefinition complex = (XSComplexTypeDefinition)eb.fType;
+                if (complex.getContentType() == XSComplexTypeDefinition.CONTENTTYPE_SIMPLE) {
+                    btype = complex.getSimpleType().getPrimitiveType().getBuiltInKind();
+                }
+                else {
+                    btype = XSConstants.STRING_DT;
+                }
+            }
+            if (ed.fType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
+                dtype = ((XSSimpleTypeDefinition)ed.fType).getPrimitiveType().getBuiltInKind();
+            }
+            else {
+                XSComplexTypeDefinition complex = (XSComplexTypeDefinition)ed.fType;
+                if (complex.getContentType() == XSComplexTypeDefinition.CONTENTTYPE_SIMPLE) {
+                    dtype = complex.getSimpleType().getPrimitiveType().getBuiltInKind();
+                }
+                else {
+                    dtype = XSConstants.STRING_DT;
+                }
+            }
+            // The 2 values must have the same primitive kind and actual value.
+            // equals() checks both equality and identity.
+            if (btype != dtype || !eb.fDefault.actualValue.equals(ed.fDefault.actualValue)) {
+                return false;
+            }
+        }
+
+        // 4.3 S.{identity-constraint definitions} is a superset of G.{identity-constraint definitions}.
+        if (!checkIDConstraintRestriction(ed, eb)) {
+            return false;
+        }
+
+        // 4.4 S disallows a superset of the substitutions that G does.
+        if ((ed.fBlock & eb.fBlock) != eb.fBlock) {
+            return false;
+        }
+
+        // 4.5 S's declared {type definition} is ·validly substitutable as
+        // a restriction· for G's declared {type definition}.
+        if (!xsc.checkTypeDerivationOk(ed.fType, eb.fType,
+                (short)(XSConstants.DERIVATION_EXTENSION|XSConstants.DERIVATION_LIST|XSConstants.DERIVATION_UNION))) {
+            return false;
+        }
+        
+        return true;
+    }
+
+    private boolean checkIDConstraintRestriction(XSElementDecl derivedElemDecl,
+            XSElementDecl baseElemDecl) {
+        IdentityConstraint[] idcd = derivedElemDecl.getIDConstraints();
+        IdentityConstraint[] idcb = baseElemDecl.getIDConstraints();
+        int sizeb = idcb == null ? 0 : idcb.length;
+        int sized = idcd == null ? 0 : idcd.length;
+        // For each IDC in the base, look for the same IDC in derived
+        for (int b = 0; b < sizeb; b++) {
+            int d = 0;
+            for (; d < sized; d++) {
+                if (idcb[b] == idcd[d]) {
+                    break;
+                }
+            }
+            // Didn't find a match, error.
+            if (d == idcd.length) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    // whether 2 edges match
+    private boolean checkEWRestriction() {
+        // 1 G is skip.
+        if (wb.getProcessContents() == XSWildcardDecl.PC_SKIP) {
+            return true;
+        }
+        qname.uri = ed.fTargetNamespace;
+        qname.localpart = ed.fName;
+        eb = getGlobalElementDecl(qname);
+        if (eb == null) {
+            // 2 G is lax and S is not skip.
+            return wb.getProcessContents() == XSWildcardDecl.PC_LAX;
+        }
+        else {
+            // 4 G and S are both Element Declarations and all of the following are true:
+            return checkEERestriction();
+        }
+    }
+
+    private boolean matchWildcardInBase() {
+        // For each wildcard in derived, subtract stronger elements first,
+        // then look for matches in base, in the order of element, wildcard,
+        // then open content.
+        
+        // Copy the derived wildcard into fields of this class, so that we can
+        // start subtract parts that have matches in the base.
+        // The strong elements are already stored in the "disallowed list"
+        // before this method is called.
+        copyDerivedWildcard();
+
+        // If this wildcard is the open content, also need to subtract all
+        // wildcard edges, because open content is weaker than the wildcards.
+        if (derived.isOpenContent(wd)) {
+            int[] idx = new int[1];
+            idx[0] = -1;
+            XSWildcardDecl wd1;
+            // Subtract all wildcard edges. Stop if the wildcard becomes empty
+            while (!emptyWildcard() && (wd1 = derived.nextWildcardTransition(d, dn, idx)) != null) {
+                if (wd1 != wd) {
+                    subtractWildcard(wd1, true);
+                }
+            }
+        }
+        
+        // Go through all base element transitions
+        indexb[0] = -1;
+        while ((eb = base.nextElementTransition(b, bn, indexb)) != null) {
+            // True: good match; False: bad match; null: no match
+            Boolean res = checkWERestriction();
+            if (res != null) {
+                if (!res.booleanValue()) {
+                    return false;
+                }
+                else {
+                    // The base element name is added to the disallow list
+                    // in checkWERestriction();
+                    // Add good match to the state pair list
+                    addState();
+                }
+            }
+            // Also attempt to match sub-group members in base. Same process.
+            if (eb.getScope() == XSConstants.SCOPE_GLOBAL) {
+                XSElementDecl[] ebs = sgh.getSubstitutionGroup(eb, Constants.SCHEMA_VERSION_1_1);
+                for (int j = 0; j < ebs.length; j++) {
+                    this.eb = ebs[j];
+                    res = checkWERestriction();
+                    if (res != null) {
+                        if (!res.booleanValue()) {
+                            return false;
+                        }
+                        else {
+                            addState();
+                        }
+                    }
+                }
+            }
+        }
+
+        // Now go through all base wildcard transitions
+        indexb[0] = -1;
+        while (!emptyWildcard() && (wb = base.nextWildcardTransition(b, bn, indexb)) != null) {
+            // Returns whether there was any overlap that got subtracted
+            if (subtractWildcard(wb, false)) {
+                // If there was overlap (match), check "process contents"
+                if (wd.weakerProcessContents(wb)) {
+                    return false;
+                }
+                // Add good match to the state pair list
+                addState();
+            }
+        }
+        
+        // The emtire wildcard must have been matched. If there's anything left,
+        // it's allowed by derived but not base. Error.
+        if (!emptyWildcard()) {
+            return false;
+        }
+        
+        return true;
+    }
+    
+    // Base element and derived wildcard.
+    // True: good match; False: bad match; null: no match
+    private Boolean checkWERestriction() {
+        // Whether element name is allowed by the wildcard
+        if (!allowName(eb.fTargetNamespace, eb.fName)) {
+            return null;
+        }
+        // Skip wildcard in derived can't restrict element in base.
+        if (wd.fProcessContents == XSWildcardDecl.PC_SKIP) {
+            return Boolean.FALSE;
+        }
+        // Must be able to find a global decl. Otherwise wildcard in derived
+        // can't restrict element in base.
+        ed = getGlobalElementDecl(qname);
+        if (ed == null) {
+            return Boolean.FALSE;
+        }
+        // The global element decl must match the base element
+        if (ed != eb && !checkEERestriction()) {
+            return Boolean.FALSE;
+        }
+        // Good match. Subtract the name from the wildcard.
+        wDNList.add(eb.fTargetNamespace);
+        wDNList.add(eb.fName);
+        return Boolean.TRUE;
+    }
+
+    // Subtract the specified wildcard from the wildcard in this class.
+    // Returns whether the 2 wildcards had any overlap.
+    private boolean subtractWildcard(XSWildcardDecl wc, boolean isDerived) {
+        boolean changed = false;
+        
+        // Because of UPA, it's not possible to add a name to the allowed list
+        // when subtracting a wildcard, then remove that same name when
+        // subtracting another wildcard, except for when the second wildcard
+        // is the open content. So only need to clear the allowed list

[... 685 lines stripped ...]


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@xerces.apache.org
For additional commands, e-mail: commits-help@xerces.apache.org