in src/xercesc/validators/schema/TraverseSchema.cpp [1334:1544]
int TraverseSchema::traverseComplexTypeDecl(const DOMElement* const elem,
const bool topLevel,
const XMLCh* const recursingTypeName) {
NamespaceScopeManager nsMgr(elem, fSchemaInfo, this);
// Get the attributes of the complexType
const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName);
bool isAnonymous = false;
if (!name || !*name) {
if (topLevel) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::TopLevelNoNameComplexType);
return -1;
}
if (recursingTypeName)
name = recursingTypeName;
else {
name = genAnonTypeName(fgAnonCNamePrefix);
isAnonymous = true;
}
}
if (!XMLChar1_0::isValidNCName(name, XMLString::stringLen(name)) ) {
//REVISIT - Should we return or continue and save type with wrong name?
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidDeclarationName,
SchemaSymbols::fgELT_COMPLEXTYPE, name);
return -1;
}
// ------------------------------------------------------------------
// Check if the type has already been registered
// ------------------------------------------------------------------
fBuffer.set(fTargetNSURIString);
fBuffer.append(chComma);
fBuffer.append(name);
int typeNameIndex = fStringPool->addOrFind(fBuffer.getRawBuffer());
const XMLCh* fullName = fStringPool->getValueForId(typeNameIndex);
ComplexTypeInfo* typeInfo = 0;
if (topLevel || recursingTypeName) {
typeInfo = fComplexTypeRegistry->get(fullName);
if (typeInfo && !typeInfo->getPreprocessed()) {
return typeNameIndex;
}
}
// -----------------------------------------------------------------------
// Check Attributes
// -----------------------------------------------------------------------
bool preProcessFlag = (typeInfo) ? typeInfo->getPreprocessed() : false;
if (!preProcessFlag) {
fAttributeCheck.checkAttributes(
elem, (topLevel) ? GeneralAttributeCheck::E_ComplexTypeGlobal
: GeneralAttributeCheck::E_ComplexTypeLocal
, this, topLevel, fNonXSAttList
);
}
// -----------------------------------------------------------------------
// Create a new instance
// -----------------------------------------------------------------------
XMLSize_t previousCircularCheckIndex = fCircularCheckIndex;
unsigned int previousScope = fCurrentScope;
if (preProcessFlag) {
fCurrentScope = typeInfo->getScopeDefined();
typeInfo->setPreprocessed(false);
}
else {
// ------------------------------------------------------------------
// Register the type
// ------------------------------------------------------------------
typeInfo = new (fGrammarPoolMemoryManager) ComplexTypeInfo(fGrammarPoolMemoryManager);
if(isAnonymous) {
typeInfo->setAnonymous();
}
fCurrentScope = fScopeCount++;
fComplexTypeRegistry->put((void*) fullName, typeInfo);
typeInfo->setTypeName(fullName);
typeInfo->setScopeDefined(fCurrentScope);
if (fFullConstraintChecking) {
XSDLocator* aLocator = new (fGrammarPoolMemoryManager) XSDLocator();
aLocator->setValues(fStringPool->getValueForId(fStringPool->addOrFind(fSchemaInfo->getCurrentSchemaURL())),
0, ((XSDElementNSImpl*) elem)->getLineNo(),
((XSDElementNSImpl*) elem)->getColumnNo());
typeInfo->setLocator(aLocator);
}
}
fCurrentTypeNameStack->addElement(typeNameIndex);
ComplexTypeInfo* saveTypeInfo = fCurrentComplexType;
fCurrentComplexType = typeInfo;
// ------------------------------------------------------------------
// First, handle any ANNOTATION declaration and get next child
// ------------------------------------------------------------------
DOMElement* child = checkContent(elem, XUtil::getFirstChildElement(elem), true, !preProcessFlag);
if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size())
{
fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList);
}
Janitor<XSAnnotation> janAnnot(fAnnotation);
// ------------------------------------------------------------------
// Process the content of the complex type declaration
// ------------------------------------------------------------------
try {
const XMLCh* mixedVal = getElementAttValue(elem,SchemaSymbols::fgATT_MIXED, DatatypeValidator::Boolean);
bool isMixed = false;
if ((mixedVal && *mixedVal)
&& (XMLString::equals(SchemaSymbols::fgATTVAL_TRUE, mixedVal)
|| XMLString::equals(fgValueOne, mixedVal))) {
isMixed = true;
}
if (child == 0) {
// EMPTY complexType with complexContent
processComplexContent(elem, name, child, typeInfo, 0, isMixed);
}
else {
const XMLCh* childName = child->getLocalName();
if (XMLString::equals(childName, SchemaSymbols::fgELT_SIMPLECONTENT)) {
// SIMPLE CONTENT element
traverseSimpleContentDecl(name, fullName, child, typeInfo, &janAnnot);
if (XUtil::getNextSiblingElement(child) != 0) {
reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::InvalidChildFollowingSimpleContent);
}
}
else if (XMLString::equals(childName, SchemaSymbols::fgELT_COMPLEXCONTENT)) {
// COMPLEX CONTENT element
traverseComplexContentDecl(name, child, typeInfo, isMixed, &janAnnot);
if (XUtil::getNextSiblingElement(child) != 0) {
reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::InvalidChildFollowingConplexContent);
}
}
else if (fCurrentGroupInfo) {
typeInfo->setPreprocessed(true);
}
else {
// We must have ....
// GROUP, ALL, SEQUENCE or CHOICE, followed by optional attributes
// Note that it's possible that only attributes are specified.
processComplexContent(elem, name, child, typeInfo, 0, isMixed);
}
}
}
catch(const TraverseSchema::ExceptionCodes aCode) {
if (aCode == TraverseSchema::InvalidComplexTypeInfo)
defaultComplexTypeInfo(typeInfo);
else if (aCode == TraverseSchema::RecursingElement)
typeInfo->setPreprocessed();
}
// ------------------------------------------------------------------
// Finish the setup of the typeInfo
// ------------------------------------------------------------------
if (!preProcessFlag) {
const XMLCh* abstractAttVal = getElementAttValue(elem, SchemaSymbols::fgATT_ABSTRACT, DatatypeValidator::Boolean);
int blockSet = parseBlockSet(elem, C_Block);
int finalSet = parseFinalSet(elem, EC_Final);
typeInfo->setBlockSet(blockSet);
typeInfo->setFinalSet(finalSet);
if ((abstractAttVal && *abstractAttVal)
&& (XMLString::equals(abstractAttVal, SchemaSymbols::fgATTVAL_TRUE)
|| XMLString::equals(abstractAttVal, fgValueOne))) {
typeInfo->setAbstract(true);
}
else {
typeInfo->setAbstract(false);
}
}
// Store Annotation
if (!janAnnot.isDataNull())
fSchemaGrammar->putAnnotation(typeInfo, janAnnot.release());
// ------------------------------------------------------------------
// Before exiting, restore the scope, mainly for nested anonymous types
// ------------------------------------------------------------------
popCurrentTypeNameStack();
fCircularCheckIndex = previousCircularCheckIndex;
fCurrentScope = previousScope;
fCurrentComplexType = saveTypeInfo;
return typeNameIndex;
}