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;
}