in src/main/java/org/apache/xmlbeans/impl/schema/StscComplexTypeResolver.java [391:548]
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);
}