/*   Copyright 2004 The Apache Software Foundation
 *
 *   Licensed 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.xmlbeans.impl.schema;

import org.apache.xmlbeans.*;
import org.apache.xmlbeans.impl.common.QNameHelper;
import org.apache.xmlbeans.impl.xb.xsdschema.*;
import org.apache.xmlbeans.impl.xb.xsdschema.AnyDocument.Any;
import org.apache.xmlbeans.impl.xb.xsdschema.SchemaDocument.Schema;

import javax.xml.namespace.QName;
import java.math.BigInteger;
import java.util.*;
import java.util.function.BinaryOperator;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StscComplexTypeResolver {
    public static Group getContentModel(ComplexType parseCt) {
        return getContentModel(parseCt::getAll, parseCt::getSequence, parseCt::getChoice, parseCt::getGroup);
    }

    public static Group getContentModel(ComplexRestrictionType parseRest) {
        return getContentModel(parseRest::getAll, parseRest::getSequence, parseRest::getChoice, parseRest::getGroup);
    }

    public static Group getContentModel(ExtensionType parseExt) {
        return getContentModel(parseExt::getAll, parseExt::getSequence, parseExt::getChoice, parseExt::getGroup);
    }

    @SafeVarargs
    private static Group getContentModel(Supplier<? extends Group>... grps) {
        return Stream.of(grps).map(Supplier::get).filter(Objects::nonNull).findFirst().orElse(null);
    }

    static Schema getSchema(XmlObject o) {
        XmlCursor c = o.newCursor();

        try {
            while (c.toParent()) {
                o = c.getObject();

                if (o.schemaType().equals(Schema.type)) {
                    return (Schema) o;
                }
            }
        } finally {
            c.dispose();
        }

        return null;
    }

    public static void resolveComplexType(SchemaTypeImpl sImpl) {
        ComplexType parseCt = (ComplexType) sImpl.getParseObject();
        StscState state = StscState.get();
        Schema schema = getSchema(parseCt);

        // Set abstract & final flags
        boolean abs = parseCt.isSetAbstract() && parseCt.getAbstract();
        boolean finalExt = false;
        boolean finalRest = false;
        boolean finalList = false;
        boolean finalUnion = false;

        Object ds = null;
        if (parseCt.isSetFinal()) {
            ds = parseCt.getFinal();
        }
        // Inspect the final default attribute on the schema
        else if (schema != null && schema.isSetFinalDefault()) {
            ds = schema.getFinalDefault();
        }

        if (ds != null) {
            if (ds instanceof String && ds.equals("#all")) {
                // #ALL value
                finalExt = finalRest = finalList = finalUnion = true;
            } else if (ds instanceof List) {
                List<?> dsl = (List<?>) ds;
                finalExt = dsl.contains("extension");
                finalRest = dsl.contains("restriction");

// Since complex types don't participate in list and unions, these can remain
// false.  Perhaps we should throw an error.

//                if (((List)ds).contains("list"))
//                    finalList = true;
//
//                if (((List)ds).contains("union"))
//                    finalUnion = true;
            }
        }

        sImpl.setAbstractFinal(abs, finalExt, finalRest, finalList, finalUnion);

        // Set block flags
        boolean blockExt = false;
        boolean blockRest = false;
        Object block = null;

        if (parseCt.isSetBlock()) {
            block = parseCt.getBlock();
        } else if (schema != null && schema.isSetBlockDefault()) {
            block = schema.getBlockDefault();
        }

        if (block != null) {
            if (block instanceof String && block.equals("#all")) {
                // #ALL value
                blockExt = blockRest = true;
            } else if (block instanceof List) {
                List<?> blist = (List<?>) block;
                if (blist.contains("extension")) {
                    blockExt = true;
                }
                if (blist.contains("restriction")) {
                    blockRest = true;
                }
            }
        }

        sImpl.setBlock(blockExt, blockRest);

        // Verify: have simpleContent, complexContent, or direct stuff
        ComplexContentDocument.ComplexContent parseCc = parseCt.getComplexContent();
        SimpleContentDocument.SimpleContent parseSc = parseCt.getSimpleContent();
        final Group parseGroup = getContentModel(parseCt);
        int count =
            (parseCc != null ? 1 : 0) +
            (parseSc != null ? 1 : 0) +
            (parseGroup != null ? 1 : 0);
        if (count > 1) {
            // KHK: s4s should catch this?
            state.error("A complex type must define either a content model, " +
                        "or a simpleContent or complexContent derivation: " +
                        "more than one found.",
                XmlErrorCodes.REDUNDANT_CONTENT_MODEL, parseCt);
            // recovery: treat it as the first of complexContent, simpleContent, model
            if (parseCc != null && parseSc != null) {
                parseSc = null;
            }
        }

        if (parseCc != null) {
            // KHK: s4s should catch this?
            if (parseCc.getExtension() != null && parseCc.getRestriction() != null) {
                state.error("Restriction conflicts with extension", XmlErrorCodes.REDUNDANT_CONTENT_MODEL, parseCc.getRestriction());
            }

            // Mixed can be specified in two places: the rules are that Cc wins over Ct if present
            // http://www.w3.org/TR/xmlschema-1/#c-mve
            boolean mixed = parseCc.isSetMixed() ? parseCc.getMixed() : parseCt.getMixed();

            if (parseCc.getExtension() != null) {
                resolveCcExtension(sImpl, parseCc.getExtension(), mixed);
            } else if (parseCc.getRestriction() != null) {
                resolveCcRestriction(sImpl, parseCc.getRestriction(), mixed);
            } else {
                // KHK: s4s should catch this?
                state.error("Missing restriction or extension", XmlErrorCodes.MISSING_RESTRICTION_OR_EXTENSION, parseCc);
                resolveErrorType(sImpl);
            }
        } else if (parseSc != null) {
            // KHK: s4s should catch this?
            if (parseSc.getExtension() != null && parseSc.getRestriction() != null) {
                state.error("Restriction conflicts with extension", XmlErrorCodes.REDUNDANT_CONTENT_MODEL, parseSc.getRestriction());
            }

            if (parseSc.getExtension() != null) {
                resolveScExtension(sImpl, parseSc.getExtension());
            } else if (parseSc.getRestriction() != null) {
                resolveScRestriction(sImpl, parseSc.getRestriction());
            } else {
                // KHK: s4s should catch this?
                state.error("Missing restriction or extension", XmlErrorCodes.MISSING_RESTRICTION_OR_EXTENSION, parseSc);
                resolveErrorType(sImpl);
            }
        } else {
            resolveBasicComplexType(sImpl);
        }
    }

    @SuppressWarnings("unused")
    static void resolveErrorType(SchemaTypeImpl sImpl) {
        throw new RuntimeException("This type of error recovery not yet implemented.");
    }

    private static SchemaType.Ref[] makeRefArray(Collection<SchemaType> typeList) {
        return typeList.stream().map(SchemaType::getRef).toArray(SchemaType.Ref[]::new);
    }


    static void resolveBasicComplexType(SchemaTypeImpl sImpl) {
        List<SchemaType> anonymousTypes = new ArrayList<>();
        ComplexType parseTree = (ComplexType) sImpl.getParseObject();
        String targetNamespace = sImpl.getTargetNamespace();
        boolean chameleon = (sImpl.getChameleonNamespace() != null);
        Group parseGroup = getContentModel(parseTree);

        if (sImpl.isRedefinition()) {
            StscState.get().error(XmlErrorCodes.SCHEMA_REDEFINE$EXTEND_OR_RESTRICT,
                new Object[]{"<complexType>"}, parseTree);
            // recovery: oh well.
        }

        int particleCode = translateParticleCode(parseGroup);

        // build content model and anonymous types
        SchemaParticle contentModel = translateContentModel(sImpl,
            parseGroup, targetNamespace, chameleon,
            sImpl.getElemFormDefault(), sImpl.getAttFormDefault(),
            particleCode, anonymousTypes, new LinkedHashMap<>(), false, null);

        // detect the nonempty "all" case (empty <all> doesn't count - it needs to be eliminated to match XSD test cases)
        boolean isAll = contentModel != null && contentModel.getParticleType() == SchemaParticle.ALL;

        // build attr model and anonymous types
        SchemaAttributeModelImpl attrModel = new SchemaAttributeModelImpl();
        translateAttributeModel(parseTree, targetNamespace, chameleon, sImpl.getAttFormDefault(),
            anonymousTypes, sImpl, null, attrModel, null, true, null);

        // summarize wildcard information
        WildcardResult wcElt = summarizeEltWildcards(contentModel);
        WildcardResult wcAttr = summarizeAttrWildcards(attrModel);

        // build state machine and verify that content model is deterministic
        if (contentModel != null) {
            buildStateMachine(contentModel);
            if (!StscState.get().noUpa() && !((SchemaParticleImpl) contentModel).isDeterministic()) {
                StscState.get().error(XmlErrorCodes.UNIQUE_PARTICLE_ATTRIBUTION, null, parseGroup);
            }
        }

        // build property model
        // emitDBG("Building content Model for " + sImpl);
        Map<QName, SchemaProperty> elementPropertyModel = buildContentPropertyModelByQName(contentModel, sImpl);

        // add attribute property model
        Map<QName, SchemaProperty> attributePropertyModel = buildAttributePropertyModelByQName(attrModel, sImpl);

        // figure out content type
        int complexVariety =
            parseTree.getMixed()
                ? SchemaType.MIXED_CONTENT
                : contentModel == null
                ? SchemaType.EMPTY_CONTENT
                : SchemaType.ELEMENT_CONTENT;

        // now fill in the actual schema type implementation
        sImpl.setBaseTypeRef(BuiltinSchemaTypeSystem.ST_ANY_TYPE.getRef());
        sImpl.setBaseDepth(BuiltinSchemaTypeSystem.ST_ANY_TYPE.getBaseDepth() + 1);
        sImpl.setDerivationType(SchemaType.DT_EXTENSION);
        sImpl.setComplexTypeVariety(complexVariety);
        sImpl.setContentModel(contentModel, attrModel, elementPropertyModel, attributePropertyModel, isAll);
        sImpl.setAnonymousTypeRefs(makeRefArray(anonymousTypes));
        sImpl.setWildcardSummary(wcElt.typedWildcards, wcElt.hasWildcards, wcAttr.typedWildcards, wcAttr.hasWildcards);
    }

    static void resolveCcRestriction(SchemaTypeImpl sImpl, ComplexRestrictionType parseTree, boolean mixed) {
        StscState state = StscState.get();
        String targetNamespace = sImpl.getTargetNamespace();
        boolean chameleon = (sImpl.getChameleonNamespace() != null);

        // BUGBUG: NOT YET REALLY IMPLEMENTED
        // throw new RuntimeException("Not yet implemented.");

        SchemaTypeImpl baseType;
        if (parseTree.getBase() == null) {
            // KHK: s4s
            state.error("A complexContent must define a base type", XmlErrorCodes.MISSING_BASE, parseTree);
            baseType = null; // recovery: no inheritance.
        } else {
            if (sImpl.isRedefinition()) {
                baseType = state.findRedefinedGlobalType(parseTree.getBase(), sImpl.getChameleonNamespace(), sImpl);
                if (baseType != null && !baseType.getName().equals(sImpl.getName())) {
                    state.error(XmlErrorCodes.SCHEMA_REDEFINE$SAME_TYPE,
                        new Object[]{"<complexType>",
                            QNameHelper.pretty(baseType.getName()),
                            QNameHelper.pretty(sImpl.getName())
                        },
                        parseTree);
                }
            } else {
                baseType = state.findGlobalType(parseTree.getBase(), sImpl.getChameleonNamespace(), targetNamespace);
            }

            if (baseType == null) {
                state.notFoundError(parseTree.getBase(), SchemaType.TYPE, parseTree.xgetBase(), true);
            }
        }

        if (baseType == null) {
            baseType = BuiltinSchemaTypeSystem.ST_ANY_TYPE;
        }

        if (baseType != null && baseType.finalRestriction()) {
            state.error(XmlErrorCodes.COMPLEX_TYPE_RESTRICTION$FINAL,
                new Object[]{QNameHelper.pretty(baseType.getName()), QNameHelper.pretty(sImpl.getName())},
                parseTree.xgetBase());
            // recovery: just keep going
        }

        // Recursion
        if (baseType != null) {
            if (!StscResolver.resolveType(baseType)) {
                baseType = null; // circular dependency: no inheritance
            }
        }

        List<SchemaType> anonymousTypes = new ArrayList<>();
        Group parseEg = getContentModel(parseTree);

        // detect the "all" case
        int particleCode = translateParticleCode(parseEg);

        // build content model and anonymous types
        SchemaParticle contentModel = translateContentModel(sImpl,
            parseEg, targetNamespace, chameleon,
            sImpl.getElemFormDefault(), sImpl.getAttFormDefault(),
            particleCode, anonymousTypes, new LinkedHashMap<>(), false, null);

        // detect the nonempty "all" case (empty <all> doesn't count - it needs to be eliminated to match XSD test cases)
        boolean isAll = contentModel != null && contentModel.getParticleType() == SchemaParticle.ALL;

        // build attr model and anonymous types
        SchemaAttributeModelImpl attrModel;
        if (baseType == null) {
            attrModel = new SchemaAttributeModelImpl();
        } else {
            attrModel = new SchemaAttributeModelImpl(baseType.getAttributeModel());
        }
        translateAttributeModel(parseTree, targetNamespace, chameleon, sImpl.getAttFormDefault(),
            anonymousTypes, sImpl, null, attrModel, baseType, false, null);

        // summarize wildcard information
        WildcardResult wcElt = summarizeEltWildcards(contentModel);
        WildcardResult wcAttr = summarizeAttrWildcards(attrModel);

        // build state machine and verify that content model is deterministic
        if (contentModel != null) {
            buildStateMachine(contentModel);
            if (!StscState.get().noUpa() && !((SchemaParticleImpl) contentModel).isDeterministic()) {
                StscState.get().error(XmlErrorCodes.UNIQUE_PARTICLE_ATTRIBUTION, null, parseEg);
            }
        }

        // build property model
        // emitDBG("Building content Model for " + sImpl);
        Map<QName, SchemaProperty> elementPropertyModel = buildContentPropertyModelByQName(contentModel, sImpl);

        // add attribute property model
        Map<QName, SchemaProperty> attributePropertyModel = buildAttributePropertyModelByQName(attrModel, sImpl);

        // compute empty/element/mixed
        // fix for XMLBEANS-414
        int complexVariety = (mixed ? SchemaType.MIXED_CONTENT :
            (contentModel == null ? SchemaType.EMPTY_CONTENT : SchemaType.ELEMENT_CONTENT));

        // now fill in the actual schema type implementation
        if (baseType != null) {
            sImpl.setBaseTypeRef(baseType.getRef());
            sImpl.setBaseDepth(baseType.getBaseDepth() + 1);
        }
        sImpl.setDerivationType(SchemaType.DT_RESTRICTION);
        sImpl.setComplexTypeVariety(complexVariety);
        sImpl.setContentModel(contentModel, attrModel, elementPropertyModel, attributePropertyModel, isAll);
        sImpl.setAnonymousTypeRefs(makeRefArray(anonymousTypes));
        sImpl.setWildcardSummary(wcElt.typedWildcards, wcElt.hasWildcards, wcAttr.typedWildcards, wcAttr.hasWildcards);
    }

    static Map<QName, SchemaType> extractElementModel(SchemaType sType) {
        if (sType == null) {
            return new HashMap<>();
        }
        return Stream.of(sType.getProperties())
            .filter(p -> !p.isAttribute())
            .collect(Collectors.toMap(SchemaProperty::getName, SchemaProperty::getType));
    }

    static void resolveCcExtension(SchemaTypeImpl sImpl, ExtensionType parseTree, boolean mixed) {
        SchemaType baseType;
        StscState state = StscState.get();
        String targetNamespace = sImpl.getTargetNamespace();
        boolean chameleon = (sImpl.getChameleonNamespace() != null);

        if (parseTree.getBase() == null) {
            // KHK: s4s
            state.error("A complexContent must define a base type", XmlErrorCodes.MISSING_BASE, parseTree);
            baseType = null; // recovery: no inheritance.
        } else {
            if (sImpl.isRedefinition()) {
                baseType = state.findRedefinedGlobalType(parseTree.getBase(), sImpl.getChameleonNamespace(), sImpl);
                if (baseType != null && !baseType.getName().equals(sImpl.getName())) {
                    state.error(XmlErrorCodes.SCHEMA_REDEFINE$SAME_TYPE,
                        new Object[]{"<complexType>",
                            QNameHelper.pretty(baseType.getName()),
                            QNameHelper.pretty(sImpl.getName())
                        },
                        parseTree);
                }
            } else {
                baseType = state.findGlobalType(parseTree.getBase(), sImpl.getChameleonNamespace(), targetNamespace);
            }
            if (baseType == null) {
                state.notFoundError(parseTree.getBase(), SchemaType.TYPE, parseTree.xgetBase(), true);
            }
        }

        // Recursion
        if (baseType != null) {
            if (!StscResolver.resolveType((SchemaTypeImpl) baseType)) {
                baseType = null; // circular dependency: no inheritance
            }
        }

        if (baseType != null && baseType.isSimpleType()) {
            state.recover(XmlErrorCodes.SCHEMA_COMPLEX_TYPE$COMPLEX_CONTENT,
                new Object[]{QNameHelper.pretty(baseType.getName())},
                parseTree.xgetBase());
            baseType = null; // recovery: no inheritance.
        }

        if (baseType != null && baseType.finalExtension()) {
            state.error(XmlErrorCodes.COMPLEX_TYPE_EXTENSION$FINAL,
                new Object[]{QNameHelper.pretty(baseType.getName()), QNameHelper.pretty(sImpl.getName())},
                parseTree.xgetBase());
            // recovery: just keep going
        }

        // get base content model
        SchemaParticle baseContentModel = (baseType == null ? null : baseType.getContentModel());
        // TODO: attribute model also

        List<SchemaType> anonymousTypes = new ArrayList<>();
        Map<QName, SchemaType> baseElementModel = extractElementModel(baseType);
        Group parseEg = getContentModel(parseTree);

        if (baseType != null &&
            (baseType.getContentType() == SchemaType.SIMPLE_CONTENT)) {
            if (parseEg != null) {
                // if this type has complexContent, baseType is complexType
                // but with non-empty simpleContent then this type cannot
                // add extra elements
                state.recover(XmlErrorCodes.COMPLEX_TYPE_EXTENSION$EXTENDING_SIMPLE_CONTENT,
                    new Object[]{QNameHelper.pretty(baseType.getName())},
                    parseTree.xgetBase());
                baseType = null; // recovery: no inheritance.
            } else {
                // No extra elements, the type is a complex type with simple content
                resolveScExtensionPart2(sImpl, baseType, parseTree, targetNamespace, chameleon);
                return;
            }
        }

        // build extension model
        SchemaParticle extensionModel = translateContentModel(sImpl,
            parseEg, targetNamespace, chameleon,
            sImpl.getElemFormDefault(), sImpl.getAttFormDefault(),
            translateParticleCode(parseEg), anonymousTypes, baseElementModel, false, null);

        // apply rule #2 near http://www.w3.org/TR/xmlschema-1/#c-mve: empty ext model -> mixed taken from base
        if (extensionModel == null && !mixed) {
            mixed = (baseType != null && baseType.getContentType() == SchemaType.MIXED_CONTENT);
        }

        // apply Derivation Valid (Extension) rule 1.4.2.2
        if (baseType != null && (baseType.getContentType() != SchemaType.EMPTY_CONTENT) &&
            ((baseType.getContentType() == SchemaType.MIXED_CONTENT) != mixed)) {
            state.error(XmlErrorCodes.COMPLEX_TYPE_EXTENSION$BOTH_ELEMEMENT_OR_MIXED, null, parseTree.xgetBase());
            // recovery: just keep going
        }

        // detect the "all" base case
        if (baseType != null && baseType.hasAllContent() && extensionModel != null) {
            // KHK: which rule? cos-particle-extend.2 or cos-all-limited.1.2.  I think the limited one.
            state.error("Cannot extend a type with 'all' content model", XmlErrorCodes.CANNOT_EXTEND_ALL, parseTree.xgetBase());
            extensionModel = null; // recovery: drop extension
        }

        // build content model and anonymous types
        SchemaParticle contentModel = extendContentModel(baseContentModel, extensionModel, parseTree);

        // detect the nonempty "all" case (empty <all> doesn't count - it needs to be eliminated to match XSD test cases)
        boolean isAll = contentModel != null && contentModel.getParticleType() == SchemaParticle.ALL;

        // build attr model and anonymous types
        SchemaAttributeModelImpl attrModel;
        if (baseType == null) {
            attrModel = new SchemaAttributeModelImpl();
        } else {
            attrModel = new SchemaAttributeModelImpl(baseType.getAttributeModel());
        }
        translateAttributeModel(parseTree, targetNamespace, chameleon, sImpl.getAttFormDefault(),
            anonymousTypes, sImpl, null, attrModel, baseType, true, null);

        // summarize wildcard information
        WildcardResult wcElt = summarizeEltWildcards(contentModel);
        WildcardResult wcAttr = summarizeAttrWildcards(attrModel);

        // build state machine and verify that content model is deterministic
        if (contentModel != null) {
            buildStateMachine(contentModel);
            if (!StscState.get().noUpa() && !((SchemaParticleImpl) contentModel).isDeterministic()) {
                StscState.get().error(XmlErrorCodes.UNIQUE_PARTICLE_ATTRIBUTION, null, parseEg);
            }
        }

        // build property model
        // emitDBG("Building content Model for " + sImpl);
        Map<QName, SchemaProperty> elementPropertyModel = buildContentPropertyModelByQName(contentModel, sImpl);

        // add attribute property model
        Map<QName, SchemaProperty> attributePropertyModel = buildAttributePropertyModelByQName(attrModel, sImpl);

        // compute empty/element/mixed
        int complexVariety;
        if (contentModel == null && baseType != null &&
            baseType.getContentType() == SchemaType.SIMPLE_CONTENT) {
            complexVariety = SchemaType.SIMPLE_CONTENT;
            sImpl.setContentBasedOnTypeRef(baseType.getContentBasedOnType().getRef());
        } else {
            complexVariety = (mixed ? SchemaType.MIXED_CONTENT :
                (contentModel == null ? SchemaType.EMPTY_CONTENT : SchemaType.ELEMENT_CONTENT));
        }

        // now fill in the actual schema type implementation
        if (baseType == null) {
            baseType = XmlObject.type;
        }
        sImpl.setBaseTypeRef(baseType.getRef());
        sImpl.setBaseDepth(((SchemaTypeImpl) baseType).getBaseDepth() + 1);
        sImpl.setDerivationType(SchemaType.DT_EXTENSION);
        sImpl.setComplexTypeVariety(complexVariety);
        sImpl.setContentModel(contentModel, attrModel, elementPropertyModel, attributePropertyModel, isAll);
        sImpl.setAnonymousTypeRefs(makeRefArray(anonymousTypes));
        sImpl.setWildcardSummary(wcElt.typedWildcards, wcElt.hasWildcards, wcAttr.typedWildcards, wcAttr.hasWildcards);
    }

    static void resolveScRestriction(SchemaTypeImpl sImpl, SimpleRestrictionType parseTree) {
        SchemaTypeImpl baseType;
        SchemaTypeImpl contentType = null;
        StscState state = StscState.get();
        String targetNamespace = sImpl.getTargetNamespace();
        boolean chameleon = (sImpl.getChameleonNamespace() != null);
        List<SchemaType> anonymousTypes = new ArrayList<>();
        if (parseTree.getSimpleType() != null) {
            LocalSimpleType typedef = parseTree.getSimpleType();
            contentType = StscTranslator.
                translateAnonymousSimpleType(typedef, targetNamespace, chameleon,
                    sImpl.getElemFormDefault(), sImpl.getAttFormDefault(),
                    anonymousTypes, sImpl);
        }
        if (parseTree.getBase() == null) {
            state.error("A simpleContent restriction must define a base type", XmlErrorCodes.MISSING_BASE, parseTree);
            // recovery: extends ANY_SIMPLE type
            baseType = BuiltinSchemaTypeSystem.ST_ANY_SIMPLE;
        } else {
            if (sImpl.isRedefinition()) {
                baseType = state.findRedefinedGlobalType(parseTree.getBase(), sImpl.getChameleonNamespace(), sImpl);
                if (baseType != null && !baseType.getName().equals(sImpl.getName())) {
                    state.error(XmlErrorCodes.SCHEMA_REDEFINE$SAME_TYPE,
                        new Object[]{"<simpleType>",
                            QNameHelper.pretty(baseType.getName()),
                            QNameHelper.pretty(sImpl.getName())
                        },
                        parseTree);
                }
            } else {
                baseType = state.findGlobalType(parseTree.getBase(), sImpl.getChameleonNamespace(), targetNamespace);
            }
        }
        if (baseType == null) {
            state.notFoundError(parseTree.getBase(), SchemaType.TYPE, parseTree.xgetBase(), true);
            // recovery: extends ANY_SIMPLE type
            baseType = BuiltinSchemaTypeSystem.ST_ANY_SIMPLE;
        }

        // Recursion
        StscResolver.resolveType(baseType);
        if (contentType != null) {
            StscResolver.resolveType(contentType);
        } else {
            contentType = baseType;
        }

        if (baseType.isSimpleType()) {
            // src-ct.2: complex types with simple content cannot restrict simple types
            state.recover(XmlErrorCodes.COMPLEX_TYPE_PROPERTIES$SIMPLE_TYPE_EXTENSION,
                new Object[]{QNameHelper.pretty(baseType.getName())},
                parseTree);
            // recovery: extends ANY_SIMPLE type
            baseType = BuiltinSchemaTypeSystem.ST_ANY_SIMPLE;
        }

        if (baseType != null && baseType.finalRestriction()) {
            state.error(XmlErrorCodes.COMPLEX_TYPE_RESTRICTION$FINAL,
                new Object[]{QNameHelper.pretty(baseType.getName()), QNameHelper.pretty(sImpl.getName())},
                parseTree.xgetBase());
            // recovery: just keep going
        }

        // build attr model and anonymous types
        SchemaAttributeModelImpl attrModel;
        if (baseType == null) {
            attrModel = new SchemaAttributeModelImpl();
        } else {
            attrModel = new SchemaAttributeModelImpl(baseType.getAttributeModel());
        }
        translateAttributeModel(parseTree, targetNamespace, chameleon, sImpl.getAttFormDefault(),
            anonymousTypes, sImpl, null, attrModel, baseType, false, null);

        // summarize wildcard information
        WildcardResult wcAttr = summarizeAttrWildcards(attrModel);

        // add attribute property model
        Map<QName, SchemaProperty> attributePropertyModel = buildAttributePropertyModelByQName(attrModel, sImpl);

        // now fill in the actual schema type implementation
        if (baseType != null) {
            sImpl.setBaseTypeRef(baseType.getRef());
            sImpl.setBaseDepth(baseType.getBaseDepth() + 1);
        }
        sImpl.setContentBasedOnTypeRef(contentType.getRef());
        sImpl.setDerivationType(SchemaType.DT_RESTRICTION);
        sImpl.setAnonymousTypeRefs(makeRefArray(anonymousTypes));
        sImpl.setWildcardSummary(QNameSet.EMPTY, false, wcAttr.typedWildcards, wcAttr.hasWildcards);
        sImpl.setComplexTypeVariety(SchemaType.SIMPLE_CONTENT);
        sImpl.setContentModel(null, attrModel, null, attributePropertyModel, false);
        sImpl.setSimpleTypeVariety(contentType.getSimpleVariety());
        sImpl.setPrimitiveTypeRef(contentType.getPrimitiveType() == null ? null : contentType.getPrimitiveType().getRef());
        switch (sImpl.getSimpleVariety()) {
            case SchemaType.LIST: {
                SchemaType lit = contentType.getListItemType();
                if (lit != null) {
                    sImpl.setListItemTypeRef(lit.getRef());
                }
                break;
            }

            case SchemaType.UNION:
                sImpl.setUnionMemberTypeRefs(makeRefArray(Arrays.asList(contentType.getUnionMemberTypes())));
                break;
        }

        // deal with facets
        StscSimpleTypeResolver.resolveFacets(sImpl, parseTree, contentType);

        // now compute our intrinsic properties
        StscSimpleTypeResolver.resolveFundamentalFacets(sImpl);
    }

    static void resolveScExtension(SchemaTypeImpl sImpl, SimpleExtensionType parseTree) {
        SchemaTypeImpl baseType;
        StscState state = StscState.get();
        String targetNamespace = sImpl.getTargetNamespace();
        boolean chameleon = (sImpl.getChameleonNamespace() != null);
        if (parseTree.getBase() == null) {
            state.error("A simpleContent extension must define a base type", XmlErrorCodes.MISSING_BASE, parseTree);
            // recovery: extends ANY_SIMPLE type
            baseType = BuiltinSchemaTypeSystem.ST_ANY_SIMPLE;
        } else {
            if (sImpl.isRedefinition()) {
                baseType = state.findRedefinedGlobalType(parseTree.getBase(), sImpl.getChameleonNamespace(), sImpl);
                if (baseType != null && !baseType.getName().equals(sImpl.getName())) {
                    state.error(XmlErrorCodes.SCHEMA_REDEFINE$SAME_TYPE,
                        new Object[]{"<simpleType>",
                            QNameHelper.pretty(baseType.getName()),
                            QNameHelper.pretty(sImpl.getName())
                        },
                        parseTree);
                }
            } else {
                baseType = state.findGlobalType(parseTree.getBase(), sImpl.getChameleonNamespace(), targetNamespace);
            }
            if (baseType == null) {
                state.notFoundError(parseTree.getBase(), SchemaType.TYPE, parseTree.xgetBase(), true);
                // recovery: extends ANY_SIMPLE type
                baseType = BuiltinSchemaTypeSystem.ST_ANY_SIMPLE;
            }
        }

        // Recursion
        StscResolver.resolveType(baseType);

        if (!baseType.isSimpleType() && baseType.getContentType() != SchemaType.SIMPLE_CONTENT) {
            // src-ct.2: complex types with simple content can only extend simple types
            state.error(XmlErrorCodes.SCHEMA_COMPLEX_TYPE$SIMPLE_CONTENT,
                new Object[]{QNameHelper.pretty(baseType.getName())},
                parseTree);
            // recovery: extends ANY_SIMPLE type
            baseType = BuiltinSchemaTypeSystem.ST_ANY_SIMPLE;
        }

        if (baseType != null && baseType.finalExtension()) {
            state.error(XmlErrorCodes.COMPLEX_TYPE_EXTENSION$FINAL,
                new Object[]{QNameHelper.pretty(baseType.getName()), QNameHelper.pretty(sImpl.getName())},
                parseTree.xgetBase());
            // recovery: just keep going
        }

        resolveScExtensionPart2(sImpl, baseType, parseTree, targetNamespace, chameleon);
    }

    static void resolveScExtensionPart2(SchemaTypeImpl sImpl, SchemaType baseType, ExtensionType parseTree,
                                        String targetNamespace, boolean chameleon) {
        // build attr model and anonymous types
        List<SchemaType> anonymousTypes = new ArrayList<>();
        SchemaAttributeModelImpl attrModel;
        attrModel = new SchemaAttributeModelImpl(baseType.getAttributeModel());
        translateAttributeModel(parseTree, targetNamespace, chameleon, sImpl.getAttFormDefault(), anonymousTypes, sImpl, null, attrModel, baseType, true, null);

        // summarize wildcard information
        WildcardResult wcAttr = summarizeAttrWildcards(attrModel);

        // add attribute property model
        Map<QName, SchemaProperty> attributePropertyModel = buildAttributePropertyModelByQName(attrModel, sImpl);

        // now fill in the actual schema type implementation
        sImpl.setBaseTypeRef(baseType.getRef());
        sImpl.setBaseDepth(((SchemaTypeImpl) baseType).getBaseDepth() + 1);
        sImpl.setContentBasedOnTypeRef(baseType.getRef());
        sImpl.setDerivationType(SchemaType.DT_EXTENSION);
        sImpl.setAnonymousTypeRefs(makeRefArray(anonymousTypes));
        sImpl.setWildcardSummary(QNameSet.EMPTY, false, wcAttr.typedWildcards, wcAttr.hasWildcards);
        sImpl.setComplexTypeVariety(SchemaType.SIMPLE_CONTENT);
        sImpl.setContentModel(null, attrModel, null, attributePropertyModel, false);
        sImpl.setSimpleTypeVariety(baseType.getSimpleVariety());
        sImpl.setPrimitiveTypeRef(baseType.getPrimitiveType() == null ? null : baseType.getPrimitiveType().getRef());
        switch (sImpl.getSimpleVariety()) {
            case SchemaType.LIST:
                sImpl.setListItemTypeRef(baseType.getListItemType().getRef());
                break;

            case SchemaType.UNION:
                sImpl.setUnionMemberTypeRefs(makeRefArray(Arrays.asList(baseType.getUnionMemberTypes())));
                break;
        }

        // deal with facets
        StscSimpleTypeResolver.resolveFacets(sImpl, null, (SchemaTypeImpl) baseType);

        // now compute our intrinsic properties
        StscSimpleTypeResolver.resolveFundamentalFacets(sImpl);
    }

    static class WildcardResult {
        WildcardResult(QNameSet typedWildcards, boolean hasWildcards) {
            this.typedWildcards = typedWildcards;
            this.hasWildcards = hasWildcards;
        }

        QNameSet typedWildcards;
        boolean hasWildcards;
    }

    static WildcardResult summarizeAttrWildcards(SchemaAttributeModel attrModel) {
        if (attrModel.getWildcardProcess() == SchemaAttributeModel.NONE) {
            return new WildcardResult(QNameSet.EMPTY, false);
        }
        if (attrModel.getWildcardProcess() == SchemaAttributeModel.SKIP) {
            return new WildcardResult(QNameSet.EMPTY, true);
        }
        return new WildcardResult(attrModel.getWildcardSet(), true);
    }

    static WildcardResult summarizeEltWildcards(SchemaParticle contentModel) {
        if (contentModel == null) {
            return new WildcardResult(QNameSet.EMPTY, false);
        }

        switch (contentModel.getParticleType()) {
            case SchemaParticle.ALL:
            case SchemaParticle.SEQUENCE:
            case SchemaParticle.CHOICE:
                QNameSetBuilder set = new QNameSetBuilder();
                boolean hasWildcards = false;
                for (int i = 0; i < contentModel.countOfParticleChild(); i++) {
                    WildcardResult inner = summarizeEltWildcards(contentModel.getParticleChild(i));
                    set.addAll(inner.typedWildcards);
                    hasWildcards |= inner.hasWildcards;
                }
                return new WildcardResult(set.toQNameSet(), hasWildcards);
            case SchemaParticle.WILDCARD:
                return new WildcardResult(
                    (contentModel.getWildcardProcess() == SchemaParticle.SKIP) ?
                        QNameSet.EMPTY : contentModel.getWildcardSet(), true);
            // otherwise fallthrough

            default:
                return new WildcardResult(QNameSet.EMPTY, false);
        }
    }

    static void translateAttributeModel(XmlObject parseTree,
                                        String targetNamespace, boolean chameleon, String formDefault,
                                        List<SchemaType> anonymousTypes, SchemaType outerType,
                                        Set<QName> seenAttributes, SchemaAttributeModelImpl result,
                                        SchemaType baseType, boolean extension,
                                        SchemaAttributeGroupImpl redefinitionFor) {
        StscState state = StscState.get();
        if (seenAttributes == null) {
            seenAttributes = new HashSet<>();
        }
        boolean seenWildcard = false;
        boolean seenRedefinition = false;
        SchemaAttributeModel baseModel = null;
        if (baseType != null) {
            baseModel = baseType.getAttributeModel();
        }

        XmlCursor cur = parseTree.newCursor();

        for (boolean more = cur.toFirstChild(); more; more = cur.toNextSibling()) {
            switch (translateAttributeCode(cur.getName())) {
                case ATTRIBUTE_CODE: {
                    Attribute xsdattr = (Attribute) cur.getObject();

                    SchemaLocalAttribute sAttr = StscTranslator.translateAttribute(xsdattr, targetNamespace, formDefault, chameleon, anonymousTypes, outerType, baseModel, true);
                    if (sAttr == null) {
                        continue;
                    }

                    if (seenAttributes.contains(sAttr.getName())) {
                        state.error(XmlErrorCodes.COMPLEX_TYPE_PROPERTIES$DUPLICATE_ATTRIBUTE,
                            new Object[]{QNameHelper.pretty(sAttr.getName()), QNameHelper.pretty(outerType.getName())},
                            xsdattr.xgetName());
                        continue; // ignore the duplicate attr
                    }

                    seenAttributes.add(sAttr.getName());

                    if (baseModel != null) {
                        SchemaLocalAttribute baseAttr = baseModel.getAttribute(sAttr.getName());
                        if (baseAttr == null) {
                            if (!extension) {
                                if (!baseModel.getWildcardSet().contains(sAttr.getName())) {
                                    state.error(XmlErrorCodes.COMPLEX_TYPE_RESTRICTION$ATTR_IN_BASE_WILDCARD_SET,
                                        new Object[]{QNameHelper.pretty(sAttr.getName()), QNameHelper.pretty(outerType.getName())}, xsdattr);
                                }
                            }
                        } else {
                            if (extension) {
                                // KHK: cos-ct-extends.1.2?
                                if (sAttr.getUse() == SchemaLocalAttribute.PROHIBITED) {
                                    state.error("An extension cannot prohibit an attribute from the base type; use restriction instead.", XmlErrorCodes.DUPLICATE_ATTRIBUTE_NAME, xsdattr.xgetUse());
                                }
                            } else {
                                if (sAttr.getUse() != SchemaLocalAttribute.REQUIRED) {
                                    if (baseAttr.getUse() == SchemaLocalAttribute.REQUIRED) {
                                        state.error(XmlErrorCodes.COMPLEX_TYPE_RESTRICTION$ATTR_REQUIRED,
                                            new Object[]{QNameHelper.pretty(sAttr.getName()), QNameHelper.pretty(outerType.getName())}, xsdattr);
                                    }

                                    if (sAttr.getUse() == SchemaLocalAttribute.PROHIBITED) {
                                        result.removeProhibitedAttribute(sAttr.getName());
                                    }
                                }
                            }
                        }
                    }

                    if (sAttr.getUse() != SchemaLocalAttribute.PROHIBITED) {
                        result.addAttribute(sAttr);
                    } else {
                        // attribute is prohibited. If it has an anonymous type remove
                        // it from the list (this will prevent inclusion of any anonymous
                        // types defined within the prohibited attribute which would
                        // otherwise attempt to refer to the prohibited attribute at
                        // save() time)
                        SchemaType attrType = sAttr.getType();
                        if (anonymousTypes != null) {
                            anonymousTypes.remove(attrType);
                        }
                    }

                    if (sAttr.getDefaultText() != null && !sAttr.isFixed()) {
                        if (sAttr.getUse() != SchemaLocalAttribute.OPTIONAL) {
                            state.error(XmlErrorCodes.SCHEMA_ATTR$DEFAULT_AND_USE_OPTIONAL,
                                new Object[]{QNameHelper.pretty(sAttr.getName())}, xsdattr);
                        }
                    }


                    break;
                }
                case ANY_ATTRIBUTE_CODE: {
                    Wildcard xsdwc = (Wildcard) cur.getObject();
                    if (seenWildcard) {
                        // KHK: ?
                        state.error("Only one attribute wildcard allowed", XmlErrorCodes.DUPLICATE_ANY_ATTRIBUTE, xsdwc);
                        continue; // ignore the extra wildcard
                    }
                    seenWildcard = true;
                    NamespaceList nsList = xsdwc.xgetNamespace();
                    String nsText;
                    if (nsList == null) {
                        nsText = "##any";
                    } else {
                        nsText = nsList.getStringValue();
                    }
                    QNameSet wcset = QNameSet.forWildcardNamespaceString(nsText, targetNamespace);

                    if (baseModel != null && !extension) {
                        if (baseModel.getWildcardSet() == null) {
                            state.error(XmlErrorCodes.COMPLEX_TYPE_RESTRICTION$BASE_HAS_ATTR_WILDCARD, null, xsdwc);
                            continue; // ignore the extra wildcard
                        } else if (!baseModel.getWildcardSet().containsAll(wcset)) {
                            state.error(XmlErrorCodes.COMPLEX_TYPE_RESTRICTION$ATTR_WILDCARD_SUBSET,
                                new Object[]{nsText}, xsdwc);
                            continue; // ignore the restriction
                        }
                    }

                    int wcprocess = translateWildcardProcess(xsdwc.xgetProcessContents());
                    if (result.getWildcardProcess() == SchemaAttributeModel.NONE) {
                        result.setWildcardSet(wcset);
                        result.setWildcardProcess(wcprocess);
                    } else {
                        if (extension) {
                            result.setWildcardSet(wcset.union(result.getWildcardSet()));
                            result.setWildcardProcess(wcprocess);
                        } else {
                            result.setWildcardSet(wcset.intersect(result.getWildcardSet()));
                            // keep old process
                        }
                    }
                    break;
                }
                case ATTRIBUTE_GROUP_CODE: {
                    AttributeGroupRef xsdag = (AttributeGroupRef) cur.getObject();
                    QName ref = xsdag.getRef();
                    if (ref == null) {
                        // KHK: s4s
                        state.error("Attribute group reference must have a ref attribute", XmlErrorCodes.ATTRIBUTE_GROUP_MISSING_REF, xsdag);
                        continue;
                    }
                    SchemaAttributeGroupImpl group;
                    if (redefinitionFor != null) {
                        group = state.findRedefinedAttributeGroup(ref, chameleon ? targetNamespace : null, redefinitionFor);
                        if (group != null &&
                            redefinitionFor.getName().equals(group.getName())) {
                            if (seenRedefinition) {
                                state.error(XmlErrorCodes.SCHEMA_REDEFINE$ATTR_GROUP_SELF_REF,
                                    new Object[]{QNameHelper.pretty(redefinitionFor.getName())}, xsdag);
                            }
                            seenRedefinition = true;
                        }
                    } else {
                        group = state.findAttributeGroup(ref, chameleon ? targetNamespace : null, targetNamespace);
                    }
                    if (group == null) {
                        state.notFoundError(ref, SchemaType.ATTRIBUTE_GROUP, xsdag.xgetRef(), true);
                        continue;
                    }
                    if (state.isProcessing(group)) {
                        state.error(XmlErrorCodes.SCHEMA_ATTR_GROUP$SELF_REF,
                            new Object[]{QNameHelper.pretty(group.getName())}, group.getParseObject());
                        continue;
                    }
                    String subTargetNamespace = targetNamespace;
                    if (group.getTargetNamespace() != null) {
                        subTargetNamespace = group.getTargetNamespace();
                        chameleon = group.getChameleonNamespace() != null;
                    }

                    state.startProcessing(group);
                    SchemaAttributeGroupImpl nestedRedefinitionFor = null;
                    if (group.isRedefinition()) {
                        nestedRedefinitionFor = group;
                    }
                    translateAttributeModel(group.getParseObject(), subTargetNamespace, chameleon,
                        group.getFormDefault(),
                        anonymousTypes, outerType, seenAttributes, result, baseType,
                        extension, nestedRedefinitionFor);
                    state.finishProcessing(group);
                    break;
                }
                default:
                    // skip things that are not part of the attribute model.
                    break;
            }
        }
        // If this is restriction and no wildcard was present, then
        // we have to erase the inherited wildcards
        if (!extension && !seenWildcard) {
            result.setWildcardSet(null);
            result.setWildcardProcess(SchemaAttributeModel.NONE);
        }
    }

    static SchemaParticle extendContentModel(SchemaParticle baseContentModel, SchemaParticle extendedContentModel, XmlObject parseTree) {
        // http://www.w3.org/TR/xmlschema-1/#element-complexContent::extension

        // 2.1 If the explicit content is empty, then the {content type} of the type definition resolved to by the �actual value� of the base [attribute]
        if (extendedContentModel == null) {
            return baseContentModel;
        }

        // 2.2 If the type definition resolved to by the actual value of the base [attribute] has a {content type} of empty, then a pair of mixed or elementOnly (determined as per clause 1.2.1 above) and the explicit content itself;
        if (baseContentModel == null) {
            return extendedContentModel;
        }

        // 2.3 otherwise a pair of mixed or elementOnly (determined as per clause 1.2.1 above) and a particle whose properties are as follows:
        SchemaParticleImpl sPart = new SchemaParticleImpl();
        sPart.setParticleType(SchemaParticle.SEQUENCE);

        List<SchemaParticle> accumulate = new ArrayList<>();
        addMinusPointlessParticles(accumulate, baseContentModel, SchemaParticle.SEQUENCE);
        addMinusPointlessParticles(accumulate, extendedContentModel, SchemaParticle.SEQUENCE);
        sPart.setMinOccurs(BigInteger.ONE);
        sPart.setMaxOccurs(BigInteger.ONE);
        sPart.setParticleChildren(accumulate.toArray(new SchemaParticle[0]));

        return filterPointlessParticlesAndVerifyAllParticles(sPart, parseTree);
    }

    static BigInteger extractMinOccurs(XmlNonNegativeInteger nni) {
        if (nni == null) {
            return BigInteger.ONE;
        }
        BigInteger result = nni.getBigIntegerValue();
        if (result == null) {
            return BigInteger.ONE;
        }
        return result;
    }

    static BigInteger extractMaxOccurs(AllNNI allNNI) {
        if (allNNI == null) {
            return BigInteger.ONE;
        }

        if (allNNI.instanceType().getPrimitiveType().getBuiltinTypeCode() == SchemaType.BTC_DECIMAL) {
            return ((XmlInteger) allNNI).getBigIntegerValue();
        } else {
            return null;
        }
    }

    private static class RedefinitionForGroup {
        private final SchemaModelGroupImpl group;
        private boolean seenRedefinition = false;

        public RedefinitionForGroup(SchemaModelGroupImpl group) {
            this.group = group;
        }

        public SchemaModelGroupImpl getGroup() {
            return group;
        }

        public boolean isSeenRedefinition() {
            return seenRedefinition;
        }

        public void setSeenRedefinition(boolean seenRedefinition) {
            this.seenRedefinition = seenRedefinition;
        }
    }

    static SchemaParticle translateContentModel(
        SchemaType outerType,
        XmlObject parseTree, String targetNamespace, boolean chameleon,
        String elemFormDefault, String attFormDefault,
        int particleCode, List<SchemaType> anonymousTypes, Map<QName, SchemaType> elementModel,
        boolean allowElt, RedefinitionForGroup redefinitionFor) {
        if (parseTree == null || particleCode == 0) {
            return null;
        }

        StscState state = StscState.get();

        // emitDBG("Translating content model for " + outerType);
        // indentDBG();

        boolean hasChildren = false;
        BigInteger minOccurs;
        BigInteger maxOccurs;
        SchemaModelGroupImpl group = null;

        SchemaParticleImpl sPart;

        if (particleCode == SchemaParticle.ELEMENT) {
            if (!allowElt) {
                state.error("Must be a sequence, choice or all here", XmlErrorCodes.EXPLICIT_GROUP_NEEDED, parseTree);
            }

            // TODO: detect substitution group for this element and construct a choice

            LocalElement parseElt = (LocalElement) parseTree;
            sPart = StscTranslator.translateElement(parseElt, targetNamespace, chameleon,
                elemFormDefault, attFormDefault, anonymousTypes, outerType);
            if (sPart == null) {
                return null;
            }
            minOccurs = extractMinOccurs(parseElt.xgetMinOccurs());
            maxOccurs = extractMaxOccurs(parseElt.xgetMaxOccurs());

            SchemaType oldType = elementModel.get(sPart.getName());
            if (oldType == null) {
                elementModel.put(sPart.getName(), sPart.getType());
            } else if (!sPart.getType().equals(oldType)) {
                state.error(XmlErrorCodes.ELEM_CONSISTANT, new Object[]{QNameHelper.pretty(sPart.getName())}, parseTree);
                return null;
            }
        } else if (particleCode == SchemaParticle.WILDCARD) {
            if (!allowElt) {
                state.error("Must be a sequence, choice or all here", XmlErrorCodes.EXPLICIT_GROUP_NEEDED, parseTree);
            }
            Any parseAny = (Any) parseTree;
            sPart = new SchemaParticleImpl();
            sPart.setParticleType(SchemaParticle.WILDCARD);
            QNameSet wcset;
            NamespaceList nslist = parseAny.xgetNamespace();
            if (nslist == null) {
                wcset = QNameSet.ALL;
            } else {
                wcset = QNameSet.forWildcardNamespaceString(nslist.getStringValue(), targetNamespace);
            }
            sPart.setWildcardSet(wcset);
            sPart.setWildcardProcess(translateWildcardProcess(parseAny.xgetProcessContents()));
            minOccurs = extractMinOccurs(parseAny.xgetMinOccurs());
            maxOccurs = extractMaxOccurs(parseAny.xgetMaxOccurs());
        } else {
            final Group parseGroup = (Group) parseTree;
            sPart = new SchemaParticleImpl();

            // grab min/maxOccurs before dereferencign group ref
            minOccurs = extractMinOccurs(parseGroup.xgetMinOccurs());
            maxOccurs = extractMaxOccurs(parseGroup.xgetMaxOccurs());

            if (particleCode == MODEL_GROUP_CODE) {
                QName ref = parseGroup.getRef();
                if (ref == null) {
                    // KHK: s4s
                    state.error("Group reference must have a ref attribute", XmlErrorCodes.GROUP_MISSING_REF, parseTree);
                    return null;
                }

                if (redefinitionFor != null) {
                    group = state.findRedefinedModelGroup(ref, chameleon ? targetNamespace : null, redefinitionFor.getGroup());
                    if (group != null && group.getName().equals(redefinitionFor.getGroup().getName())) {
                        if (redefinitionFor.isSeenRedefinition()) {
                            state.error(XmlErrorCodes.SCHEMA_REDEFINE$GROUP_SELF_REF,
                                new Object[]{QNameHelper.pretty(group.getName())}, parseTree);
                        }
                        if (!BigInteger.ONE.equals(maxOccurs) || !BigInteger.ONE.equals(minOccurs)) {
                            state.error(XmlErrorCodes.SCHEMA_REDEFINE$GROUP_SELF_REF_MIN_MAX_1,
                                new Object[]{QNameHelper.pretty(group.getName())}, parseTree);
                        }
                        redefinitionFor.setSeenRedefinition(true);
                    }
                } else {
                    group = state.findModelGroup(ref, chameleon ? targetNamespace : null, targetNamespace);
                }
                if (group == null) {
                    state.notFoundError(ref, SchemaType.MODEL_GROUP, ((Group) parseTree).xgetRef(), true);
                    return null;
                }
                if (state.isProcessing(group)) {
                    state.error(XmlErrorCodes.MODEL_GROUP_PROPERTIES$CIRCULAR,
                        new Object[]{QNameHelper.pretty(group.getName())}, group.getParseObject());
                    return null;
                }

                // no go to the child.
                XmlCursor cur = group.getParseObject().newCursor();
                for (boolean more = cur.toFirstChild(); more; more = cur.toNextSibling()) {
                    particleCode = translateParticleCode(cur.getName());
                    if (particleCode != 0) {
                        parseTree = cur.getObject();
                        break;
                    }
                }
                if (particleCode == 0) {
                    // KHK: s4s
                    state.error("Model group " + QNameHelper.pretty(group.getName()) + " is empty", XmlErrorCodes.EXPLICIT_GROUP_NEEDED, group.getParseObject());
                    return null;
                }
                if (particleCode != SchemaParticle.ALL && particleCode != SchemaParticle.SEQUENCE && particleCode != SchemaParticle.CHOICE) {
                    // KHK: s4s
                    state.error("Model group " + QNameHelper.pretty(group.getName()) + " is not a sequence, all, or choice", XmlErrorCodes.EXPLICIT_GROUP_NEEDED, group.getParseObject());
                }

                String newTargetNamespace = group.getTargetNamespace();
                if (newTargetNamespace != null) {
                    targetNamespace = newTargetNamespace;
                }
                elemFormDefault = group.getElemFormDefault();
                attFormDefault = group.getAttFormDefault();
                chameleon = group.getChameleonNamespace() != null;
            }

            switch (particleCode) {
                case SchemaParticle.ALL:
                case SchemaParticle.SEQUENCE:
                case SchemaParticle.CHOICE:
                    sPart.setParticleType(particleCode);
                    hasChildren = true;
                    break;

                default:
                    assert (false);
                    throw new IllegalStateException();
            }
        }

        if (maxOccurs != null && minOccurs.compareTo(maxOccurs) > 0) {
            state.error(XmlErrorCodes.PARTICLE_PROPERTIES$MIN_LTE_MAX, null, parseTree);
            maxOccurs = minOccurs; // remedy: pin max up to min
        }

        if (maxOccurs != null && maxOccurs.compareTo(BigInteger.ONE) < 0) {
            state.warning(XmlErrorCodes.PARTICLE_PROPERTIES$MAX_GTE_1, null, parseTree);

            // remove from the list of anonymous types if it was added
            anonymousTypes.remove(sPart.getType());
            return null; // maxOccurs == minOccurs == 0, same as no particle at all.
        }

        sPart.setMinOccurs(minOccurs);
        sPart.setMaxOccurs(maxOccurs);

        if (group != null) {
            state.startProcessing(group);
            redefinitionFor = null;
            if (group.isRedefinition()) {
                redefinitionFor = new RedefinitionForGroup(group);
            }
        }

        if (hasChildren) {
            XmlCursor cur = parseTree.newCursor();
            List<SchemaParticle> accumulate = new ArrayList<>();
            for (boolean more = cur.toFirstChild(); more; more = cur.toNextSibling()) {
                int code = translateParticleCode(cur.getName());
                if (code == 0) {
                    continue;
                }
                addMinusPointlessParticles(accumulate,
                    translateContentModel(outerType,
                        cur.getObject(), targetNamespace, chameleon,
                        elemFormDefault, attFormDefault, code,
                        anonymousTypes, elementModel, true, redefinitionFor),
                    sPart.getParticleType());
            }
            sPart.setParticleChildren(accumulate.toArray(new SchemaParticle[0]));
            cur.dispose();
        }


        SchemaParticle result = filterPointlessParticlesAndVerifyAllParticles(sPart, parseTree);

        if (group != null) {
            state.finishProcessing(group);
        }
        // outdentDBG();
        return result;
    }

    static int translateWildcardProcess(Any.ProcessContents process) {
        if (process == null) {
            return SchemaParticle.STRICT;
        }

        String processValue = process.getStringValue();

        if ("lax".equals(processValue)) {
            return SchemaParticle.LAX;
        }

        if ("skip".equals(processValue)) {
            return SchemaParticle.SKIP;
        }

        return SchemaParticle.STRICT;
    }

    static SchemaParticle filterPointlessParticlesAndVerifyAllParticles(SchemaParticle part, XmlObject parseTree) {
        if (part.getMaxOccurs() != null && part.getMaxOccurs().signum() == 0) {
            return null;
        }

        switch (part.getParticleType()) {
            case SchemaParticle.SEQUENCE:
            case SchemaParticle.ALL:
                if (part.getParticleChildren().length == 0) {
                    return null;
                }
                if (part.isSingleton() && part.countOfParticleChild() == 1) {
                    return part.getParticleChild(0);
                }
                break;

            case SchemaParticle.CHOICE:
                if (part.getParticleChildren().length == 0 &&
                    part.getMinOccurs().compareTo(BigInteger.ZERO) == 0) {
                    return null;
                }
                if (part.isSingleton() && part.countOfParticleChild() == 1) {
                    return part.getParticleChild(0);
                }
                break;

            case SchemaParticle.ELEMENT:
            case SchemaParticle.WILDCARD:
                return part;

            default:
                assert (false);
                throw new IllegalStateException();
        }

        boolean isAll = part.getParticleType() == SchemaParticle.ALL;

        if (isAll) {
            // http://www.w3.org/TR/xmlschema-1/#cos-all-limited
            if (part.getMaxOccurs() == null || part.getMaxOccurs().compareTo(BigInteger.ONE) > 0) {
                // An all group must have maxOccurs <= 1
                // KHK: review
                StscState.get().error(XmlErrorCodes.ALL_GROUP_LIMITED$IN_MIN_MAX_1_PARTICLE, null, parseTree);
            }
        }

        for (int i = 0; i < part.countOfParticleChild(); i++) {
            SchemaParticle child = part.getParticleChild(i);
            if (child.getParticleType() == SchemaParticle.ALL) {
                // An all group is only allowed at the top level of the content model
                // KHK: review
                StscState.get().error(XmlErrorCodes.ALL_GROUP_LIMITED$IN_COMPLEX_TYPE_DEF_PARTICLE, null, parseTree);
            } else if (isAll && (child.getParticleType() != SchemaParticle.ELEMENT || child.getMaxOccurs() == null || child.getMaxOccurs().compareTo(BigInteger.ONE) > 0)) {
                // An all group can contain only element particles with maxOccurs <= 1
                // KHK: review
                StscState.get().error(XmlErrorCodes.ALL_GROUP_LIMITED$CHILD_PARTICLES_MAX_LTE_1, null, parseTree);
            }
        }

        return part;
    }

    static void addMinusPointlessParticles(
        List<SchemaParticle> list, SchemaParticle part, int parentParticleType) {
        if (part == null) {
            return;
        }

        switch (part.getParticleType()) {
            case SchemaParticle.SEQUENCE:
                if (parentParticleType == SchemaParticle.SEQUENCE && part.isSingleton()) {
                    // emitDBG("dropping redundant sequence");
                    list.addAll(Arrays.asList(part.getParticleChildren()));
                    return;
                }
                break;

            case SchemaParticle.CHOICE:
                if (parentParticleType == SchemaParticle.CHOICE && part.isSingleton()) {
                    // emitDBG("dropping redundant choice");
                    list.addAll(Arrays.asList(part.getParticleChildren()));
                    return;
                }
                break;

            case SchemaParticle.ALL:
            default:
        }
        list.add(part);
    }

    private static <T> BinaryOperator<T> throwingMerger() {
        return (u,v) -> { throw new IllegalStateException(String.format("Duplicate key %s", u)); };
    }

    static Map<QName, SchemaProperty> buildAttributePropertyModelByQName(SchemaAttributeModel attrModel, SchemaType owner) {
        return Stream.of(attrModel.getAttributes())
            .collect(Collectors.toMap(SchemaLocalAttribute::getName, a -> buildUseProperty(a, owner), throwingMerger(), LinkedHashMap::new));
    }

    static Map<QName, SchemaProperty> buildContentPropertyModelByQName(SchemaParticle part, SchemaType owner) {
        if (part == null) {
            return Collections.emptyMap();
        }

        boolean asSequence = false;
        Map<QName, SchemaProperty> model = null;

        switch (part.getParticleType()) {
            case SchemaParticle.ALL:
            case SchemaParticle.SEQUENCE:
                asSequence = true;
                break;
            case SchemaParticle.CHOICE:
                asSequence = false;
                break;
            case SchemaParticle.ELEMENT:
                model = buildElementPropertyModel((SchemaLocalElement) part, owner);
                break;
            case SchemaParticle.WILDCARD:
                model = Collections.emptyMap();
                break;
            default:
                assert (false);
                throw new IllegalStateException();
        }

        if (model == null) {
            // build model for children
            model = new LinkedHashMap<>();
            SchemaParticle[] children = part.getParticleChildren();

            for (SchemaParticle child : children) {
                // indentDBG();
                Map<QName, SchemaProperty> childModel = buildContentPropertyModelByQName(child, owner);
                // outdentDBG();
                for (SchemaProperty iProp : childModel.values()) {
                    SchemaPropertyImpl oProp = (SchemaPropertyImpl) model.get(iProp.getName());
                    if (oProp == null) {
                        if (!asSequence) {
                            ((SchemaPropertyImpl) iProp).setMinOccurs(BigInteger.ZERO);
                        }
                        model.put(iProp.getName(), iProp);
                        continue;
                    }
                    // consistency verified in an earlier step
                    assert (oProp.getType().equals(iProp.getType()));

                    mergeProperties(oProp, iProp, asSequence);
                }
            }

            // finally deal with minOccurs, maxOccurs over whole group
            BigInteger min = part.getMinOccurs();
            BigInteger max = part.getMaxOccurs();

            for (SchemaProperty oProp : model.values()) {
                BigInteger minOccurs = oProp.getMinOccurs();
                BigInteger maxOccurs = oProp.getMaxOccurs();

                minOccurs = minOccurs.multiply(min);
                if (max != null && max.equals(BigInteger.ZERO)) {
                    maxOccurs = BigInteger.ZERO;
                } else if (maxOccurs != null && !maxOccurs.equals(BigInteger.ZERO)) {
                    maxOccurs = max == null ? null : maxOccurs.multiply(max);
                }

                ((SchemaPropertyImpl) oProp).setMinOccurs(minOccurs);
                ((SchemaPropertyImpl) oProp).setMaxOccurs(maxOccurs);
            }
        }

        return model;
    }

    static Map<QName, SchemaProperty> buildElementPropertyModel(SchemaLocalElement epart, SchemaType owner) {
        SchemaProperty sProp = buildUseProperty(epart, owner);
        return Collections.singletonMap(sProp.getName(), sProp);
    }

    static SchemaProperty buildUseProperty(SchemaField use, SchemaType owner) {
        SchemaPropertyImpl sPropImpl = new SchemaPropertyImpl();
        sPropImpl.setName(use.getName());
        sPropImpl.setContainerTypeRef(owner.getRef());
        sPropImpl.setTypeRef(use.getType().getRef());
        sPropImpl.setAttribute(use.isAttribute());
        sPropImpl.setDefault(use.isDefault() ? SchemaProperty.CONSISTENTLY : SchemaProperty.NEVER);
        sPropImpl.setFixed(use.isFixed() ? SchemaProperty.CONSISTENTLY : SchemaProperty.NEVER);
        sPropImpl.setNillable(use.isNillable() ? SchemaProperty.CONSISTENTLY : SchemaProperty.NEVER);
        sPropImpl.setDefaultText(use.getDefaultText());
        sPropImpl.setMinOccurs(use.getMinOccurs());
        sPropImpl.setMaxOccurs(use.getMaxOccurs());

        if (use instanceof SchemaLocalElementImpl) {
            SchemaLocalElementImpl elt = (SchemaLocalElementImpl) use;
            sPropImpl.setAcceptedNames(elt.acceptedStartNames());
        }

        return sPropImpl;
    }

    static void mergeProperties(SchemaPropertyImpl into, SchemaProperty from, boolean asSequence) {
        // minoccur, maxoccur
        BigInteger minOccurs = into.getMinOccurs();
        BigInteger maxOccurs = into.getMaxOccurs();
        if (asSequence) {
            minOccurs = minOccurs.add(from.getMinOccurs());
            if (maxOccurs != null) {
                maxOccurs = (from.getMaxOccurs() == null ? null :
                    maxOccurs.add(from.getMaxOccurs()));
            }
        } else {
            minOccurs = minOccurs.min(from.getMinOccurs());
            if (maxOccurs != null) {
                maxOccurs = (from.getMaxOccurs() == null ? null :
                    maxOccurs.max(from.getMaxOccurs()));
            }
        }
        into.setMinOccurs(minOccurs);
        into.setMaxOccurs(maxOccurs);

        // nillable, default, fixed
        if (from.hasNillable() != into.hasNillable()) {
            into.setNillable(SchemaProperty.VARIABLE);
        }
        if (from.hasDefault() != into.hasDefault()) {
            into.setDefault(SchemaProperty.VARIABLE);
        }
        if (from.hasFixed() != into.hasFixed()) {
            into.setFixed(SchemaProperty.VARIABLE);
        }

        // default value
        if (into.getDefaultText() != null) {
            if (from.getDefaultText() == null ||
                !into.getDefaultText().equals(from.getDefaultText())) {
                into.setDefaultText(null);
            }
        }
    }

    static SchemaParticle[] ensureStateMachine(SchemaParticle[] children) {
        for (SchemaParticle child : children) {
            buildStateMachine(child);
        }
        return children;
    }

    static void buildStateMachine(SchemaParticle contentModel) {
        if (contentModel == null) {
            return;
        }

        SchemaParticleImpl partImpl = (SchemaParticleImpl) contentModel;
        if (partImpl.hasTransitionNotes()) {
            return;
        }

        QNameSetBuilder start = new QNameSetBuilder();
        QNameSetBuilder excludenext = new QNameSetBuilder();
        boolean deterministic = true;
        SchemaParticle[] children;
        boolean canskip = (partImpl.getMinOccurs().signum() == 0);

        switch (partImpl.getParticleType()) {
            case SchemaParticle.ELEMENT:
                // compute start and excludeNext; canskip is already correct
                if (partImpl.hasTransitionRules()) {
                    start.addAll(partImpl.acceptedStartNames());
                } else {
                    start.add(partImpl.getName());
                }

                break;

            case SchemaParticle.WILDCARD:
                // compute start and excludeNext; canskip is already correct
                start.addAll(partImpl.getWildcardSet());
                break;

            case SchemaParticle.SEQUENCE:
                children = ensureStateMachine(partImpl.getParticleChildren());

                // adjust canskip if all children are skippable
                canskip = true;
                for (int i = 0; canskip && i < children.length; i++) {
                    if (!(children[i]).isSkippable()) {
                        canskip = false;
                    }
                }

                // bubble up nondeterministic bit
                for (SchemaParticle child : children) {
                    if (!((SchemaParticleImpl) child).isDeterministic()) {
                        deterministic = false;
                        break;
                    }
                }

                // verify deterministic and compute excludeNext set
                for (int i = 1; i < children.length; i++) {
                    excludenext.addAll(((SchemaParticleImpl) children[i - 1]).getExcludeNextSet());
                    if (deterministic && !excludenext.isDisjoint((children[i]).acceptedStartNames())) {
                        deterministic = false;
                    }
                    if ((children[i]).isSkippable()) {
                        excludenext.addAll((children[i]).acceptedStartNames());
                    } else {
                        excludenext.clear();
                    }
                }

                // next, compute start set
                for (SchemaParticle child : children) {
                    start.addAll(child.acceptedStartNames());
                    if (!child.isSkippable()) {
                        break;
                    }
                }
                break;

            case SchemaParticle.CHOICE:
                children = ensureStateMachine(partImpl.getParticleChildren());

                // adjust canskip if any children are skippable
                canskip = false;
                for (SchemaParticle schemaParticle : children) {
                    if (schemaParticle.isSkippable()) {
                        canskip = true;
                        break;
                    }
                }

                // bubble up nondeterministic bit
                for (SchemaParticle child : children) {
                    if (!((SchemaParticleImpl) child).isDeterministic()) {
                        deterministic = false;
                        break;
                    }
                }

                // compute start and excludeNext sets, verify deterministic
                for (SchemaParticle child : children) {
                    if (deterministic && !start.isDisjoint(child.acceptedStartNames())) {
                        deterministic = false;
                    }
                    start.addAll(child.acceptedStartNames());
                    excludenext.addAll(((SchemaParticleImpl) child).getExcludeNextSet());
                }

                break;

            case SchemaParticle.ALL:
                children = ensureStateMachine(partImpl.getParticleChildren());

                // adjust canskip if all children are skippable
                canskip = true;
                for (SchemaParticle child : children) {
                    if (!child.isSkippable()) {
                        canskip = false;
                        break;
                    }
                }

                // bubble up nondeterministic bit
                for (SchemaParticle child : children) {
                    if (!((SchemaParticleImpl) child).isDeterministic()) {
                        deterministic = false;
                        break;
                    }
                }

                // compute start and excludeNext sets, verify deterministic
                for (SchemaParticle child : children) {
                    if (deterministic && !start.isDisjoint(child.acceptedStartNames())) {
                        deterministic = false;
                    }
                    start.addAll(child.acceptedStartNames());
                    excludenext.addAll(((SchemaParticleImpl) child).getExcludeNextSet());
                }
                if (canskip) {
                    excludenext.addAll(start);
                }

                break;

            default:
                throw new IllegalStateException("Unrecognized schema particle");
        }

        // apply looping logic

        BigInteger minOccurs = partImpl.getMinOccurs();
        BigInteger maxOccurs = partImpl.getMaxOccurs();
        boolean canloop = (maxOccurs == null || maxOccurs.compareTo(BigInteger.ONE) > 0);
        boolean varloop = (maxOccurs == null || minOccurs.compareTo(maxOccurs) < 0);

        if (canloop && deterministic && !excludenext.isDisjoint(start)) {
            // we have a possible looping nondeterminism.
            // let's take some time now to see if it's actually caused
            // by non-unique-particle-attribute or not.
            QNameSet suspectSet = excludenext.intersect(start);

            // compute the set of all particles that could start this group
            Map<SchemaParticle, QNameSet> startMap = new HashMap<>();
            particlesMatchingStart(partImpl, suspectSet, startMap, new QNameSetBuilder());

            // compute the set of all particles that could have been repeated rather than ending this group
            Map<SchemaParticle, QNameSet> afterMap = new HashMap<>();
            particlesMatchingAfter(partImpl, suspectSet, afterMap, new QNameSetBuilder(), true);

            // see if we can find a member of after that is not a member of start
            // if we can, then particle attribution is not unique
            deterministic = afterMapSubsumedByStartMap(startMap, afterMap);
        }

        if (varloop) {
            excludenext.addAll(start);
        }

        canskip = canskip || minOccurs.signum() == 0;

        partImpl.setTransitionRules(start.toQNameSet(), canskip);
        partImpl.setTransitionNotes(excludenext.toQNameSet(), deterministic);
    }

    private static boolean afterMapSubsumedByStartMap(Map<SchemaParticle, QNameSet> startMap, Map<SchemaParticle, QNameSet> afterMap) {
        if (afterMap.size() > startMap.size()) {
            return false;
        }

        if (afterMap.isEmpty()) {
            return true;
        }

        for (SchemaParticle part : startMap.keySet()) {
            if (part.getParticleType() == SchemaParticle.WILDCARD) {
                if (afterMap.containsKey(part)) {
                    QNameSet startSet = startMap.get(part);
                    QNameSet afterSet = afterMap.get(part);
                    if (!startSet.containsAll(afterSet)) {
                        return false;
                    }
                }
            }
            afterMap.remove(part);
            if (afterMap.isEmpty()) {
                return true;
            }
        }
        return false;
    }

    private static void particlesMatchingStart(SchemaParticle part, QNameSetSpecification suspectSet, Map<SchemaParticle, QNameSet> result, QNameSetBuilder eliminate) {
        switch (part.getParticleType()) {
            case SchemaParticle.ELEMENT:
                if (!suspectSet.contains(part.getName())) {
                    return;
                }
                result.put(part, null);
                eliminate.add(part.getName());
                return;

            case SchemaParticle.WILDCARD:
                if (suspectSet.isDisjoint(part.getWildcardSet())) {
                    return;
                }
                result.put(part, part.getWildcardSet().intersect(suspectSet));
                eliminate.addAll(part.getWildcardSet());
                return;

            case SchemaParticle.CHOICE:
            case SchemaParticle.ALL: {
                SchemaParticle[] children = part.getParticleChildren();
                for (SchemaParticle child : children) {
                    particlesMatchingStart(child, suspectSet, result, eliminate);
                }
                return;
            }

            case SchemaParticle.SEQUENCE: {
                SchemaParticle[] children = part.getParticleChildren();
                if (children.length == 0) {
                    return;
                }
                if (!children[0].isSkippable()) {
                    particlesMatchingStart(children[0], suspectSet, result, eliminate);
                    return;
                }
                QNameSetBuilder remainingSuspects = new QNameSetBuilder(suspectSet);
                QNameSetBuilder suspectsToEliminate = new QNameSetBuilder();
                for (SchemaParticle child : children) {
                    particlesMatchingStart(child, remainingSuspects, result, suspectsToEliminate);
                    eliminate.addAll(suspectsToEliminate);
                    if (!child.isSkippable()) {
                        return;
                    }
                    remainingSuspects.removeAll(suspectsToEliminate);
                    if (remainingSuspects.isEmpty()) {
                        return;
                    }
                    suspectsToEliminate.clear();
                }
            }
        }
    }

    private static void particlesMatchingAfter(SchemaParticle part, QNameSetSpecification suspectSet, Map<SchemaParticle, QNameSet> result, QNameSetBuilder eliminate, boolean top) {
        recurse:
        switch (part.getParticleType()) {
            case SchemaParticle.CHOICE:
            case SchemaParticle.ALL: {
                SchemaParticle[] children = part.getParticleChildren();
                for (SchemaParticle child : children) {
                    particlesMatchingAfter(child, suspectSet, result, eliminate, false);
                }
                break;
            }

            case SchemaParticle.SEQUENCE: {
                SchemaParticle[] children = part.getParticleChildren();
                if (children.length == 0) {
                    break;
                }
                if (!children[children.length - 1].isSkippable()) {
                    particlesMatchingAfter(children[0], suspectSet, result, eliminate, false);
                    break;
                }
                QNameSetBuilder remainingSuspects = new QNameSetBuilder(suspectSet);
                QNameSetBuilder suspectsToEliminate = new QNameSetBuilder();
                for (int i = children.length - 1; i >= 0; i--) {
                    particlesMatchingAfter(children[i], remainingSuspects, result, suspectsToEliminate, false);
                    eliminate.addAll(suspectsToEliminate);
                    if (!children[i].isSkippable()) {
                        break recurse;
                    }
                    remainingSuspects.removeAll(suspectsToEliminate);
                    if (remainingSuspects.isEmpty()) {
                        break recurse;
                    }
                    suspectsToEliminate.clear();
                }
                break;
            }
        }

        if (!top) {
            BigInteger minOccurs = part.getMinOccurs();
            BigInteger maxOccurs = part.getMaxOccurs();
            boolean varloop = (maxOccurs == null || minOccurs.compareTo(maxOccurs) < 0);
            if (varloop) {
                particlesMatchingStart(part, suspectSet, result, eliminate);
            }
        }
    }

    private static class CodeForNameEntry {
        CodeForNameEntry(QName name, int code) {
            this.name = name;
            this.code = code;
        }

        public QName name;
        public int code;
    }

    private static final int MODEL_GROUP_CODE = 100;

    private static final CodeForNameEntry[] particleCodes = {
        new CodeForNameEntry(QNameHelper.forLNS("all", "http://www.w3.org/2001/XMLSchema"), SchemaParticle.ALL),
        new CodeForNameEntry(QNameHelper.forLNS("sequence", "http://www.w3.org/2001/XMLSchema"), SchemaParticle.SEQUENCE),
        new CodeForNameEntry(QNameHelper.forLNS("choice", "http://www.w3.org/2001/XMLSchema"), SchemaParticle.CHOICE),
        new CodeForNameEntry(QNameHelper.forLNS("element", "http://www.w3.org/2001/XMLSchema"), SchemaParticle.ELEMENT),
        new CodeForNameEntry(QNameHelper.forLNS("any", "http://www.w3.org/2001/XMLSchema"), SchemaParticle.WILDCARD),
        new CodeForNameEntry(QNameHelper.forLNS("group", "http://www.w3.org/2001/XMLSchema"), MODEL_GROUP_CODE),
    };

    private static final Map<QName, Integer> particleCodeMap =
        Stream.of(particleCodes).collect(Collectors.toMap(pc -> pc.name, pc -> pc.code));

    private static int translateParticleCode(Group parseEg) {
        if (parseEg == null) {
            return 0;
        }
        return translateParticleCode(parseEg.newCursor().getName());
    }

    private static int translateParticleCode(QName name) {
        return particleCodeMap.getOrDefault(name, 0);
    }

    private static final int ATTRIBUTE_CODE = 100;
    private static final int ATTRIBUTE_GROUP_CODE = 101;
    private static final int ANY_ATTRIBUTE_CODE = 102;

    private static final CodeForNameEntry[] attributeCodes = {
        new CodeForNameEntry(QNameHelper.forLNS("attribute", "http://www.w3.org/2001/XMLSchema"), ATTRIBUTE_CODE),
        new CodeForNameEntry(QNameHelper.forLNS("attributeGroup", "http://www.w3.org/2001/XMLSchema"), ATTRIBUTE_GROUP_CODE),
        new CodeForNameEntry(QNameHelper.forLNS("anyAttribute", "http://www.w3.org/2001/XMLSchema"), ANY_ATTRIBUTE_CODE),
    };

    private static final Map<QName,Integer> attributeCodeMap =
        Stream.of(attributeCodes).collect(Collectors.toMap(ac -> ac.name, ac -> ac.code));

    static int translateAttributeCode(QName currentName) {
        return attributeCodeMap.getOrDefault(currentName, 0);
    }
}
