static SchemaParticle translateContentModel()

in src/main/java/org/apache/xmlbeans/impl/schema/StscComplexTypeResolver.java [1073:1272]


    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.
                try (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) {
            List<SchemaParticle> accumulate = new ArrayList<>();
            try (XmlCursor cur = parseTree.newCursor()) {
                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]));
        }


        SchemaParticle result = filterPointlessParticlesAndVerifyAllParticles(sPart, parseTree);

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