diff --git a/src/validators/schema/ComplexTypeInfo.cpp b/src/validators/schema/ComplexTypeInfo.cpp index 86066d0b29d05b0c93136f91a12c5d4ab97418eb..38e9f7c74e5a3a179b6477e72fff54583a8ad7fa 100644 --- a/src/validators/schema/ComplexTypeInfo.cpp +++ b/src/validators/schema/ComplexTypeInfo.cpp @@ -56,6 +56,9 @@ /* * $Log$ + * Revision 1.27 2002/01/15 19:09:16 knoaman + * Fix for bug 5807. + * * Revision 1.26 2002/01/02 15:20:22 tng * Schema Fix: should not store a temp value as the key in the element pool and the attribute pool. * @@ -156,12 +159,14 @@ ComplexTypeInfo::ComplexTypeInfo() : fAbstract(false) , fAdoptContentSpec(true) , fAttWithTypeId(false) + , fPreprocessed(false) , fDerivedBy(0) , fBlockSet(0) , fFinalSet(0) , fScopeDefined(Grammar::TOP_LEVEL_SCOPE) , fElementId(XMLElementDecl::fgInvalidElemId) , fContentType(SchemaElementDecl::Empty) + , fRecursingTypeIndex(-1) , fTypeName(0) , fBaseDatatypeValidator(0) , fDatatypeValidator(0) diff --git a/src/validators/schema/ComplexTypeInfo.hpp b/src/validators/schema/ComplexTypeInfo.hpp index acfee522289942d9e4255baea4e5dbd2f9202c77..f1bb4ea215f3283c85e52dd796cc7d61ddc28414 100644 --- a/src/validators/schema/ComplexTypeInfo.hpp +++ b/src/validators/schema/ComplexTypeInfo.hpp @@ -104,6 +104,7 @@ public: bool getAbstract() const; bool getAdoptContentSpec() const; bool containsAttWithTypeId() const; + bool getPreprocessed() const; int getDerivedBy() const; int getBlockSet() const; int getFinalSet() const; @@ -127,7 +128,7 @@ public: SchemaElementDecl* elementAt(const unsigned int index); XMLContentModel* getContentModel(const bool checkUPA = false); const XMLCh* getFormattedContentModel () const; - + int getRecursingTypeIndex() const; // ----------------------------------------------------------------------- // Setter methods @@ -135,6 +136,7 @@ public: void setAbstract(const bool isAbstract); void setAdoptContentSpec(const bool toAdopt); void setAttWithTypeId(const bool value); + void setPreprocessed(const bool aValue = true); void setDerivedBy(const int derivedBy); void setBlockSet(const int blockSet); void setFinalSet(const int finalSet); @@ -150,6 +152,7 @@ public: void addAttDef(SchemaAttDef* const toAdd); void addElement(SchemaElementDecl* const toAdd); void setContentModel(XMLContentModel* const newModelToAdopt); + void setRecursingTypeIndex(const int anIndex); // ----------------------------------------------------------------------- // Helper methods @@ -198,12 +201,14 @@ private: bool fAbstract; bool fAdoptContentSpec; bool fAttWithTypeId; + bool fPreprocessed; int fDerivedBy; int fBlockSet; int fFinalSet; int fScopeDefined; unsigned int fElementId; int fContentType; + int fRecursingTypeIndex; XMLCh* fTypeName; DatatypeValidator* fBaseDatatypeValidator; DatatypeValidator* fDatatypeValidator; @@ -239,6 +244,11 @@ inline bool ComplexTypeInfo::containsAttWithTypeId() const { return fAttWithTypeId; } +inline bool ComplexTypeInfo::getPreprocessed() const { + + return fPreprocessed; +} + inline int ComplexTypeInfo::getDerivedBy() const { return fDerivedBy; @@ -361,6 +371,11 @@ inline XMLContentModel* ComplexTypeInfo::getContentModel(const bool checkUPA) return fContentModel; } +inline int ComplexTypeInfo::getRecursingTypeIndex() const { + + return fRecursingTypeIndex; +} + // --------------------------------------------------------------------------- // ComplexTypeInfo: Setter methods // --------------------------------------------------------------------------- @@ -379,6 +394,11 @@ inline void ComplexTypeInfo::setAttWithTypeId(const bool value) { fAttWithTypeId = value; } +inline void ComplexTypeInfo::setPreprocessed(const bool aValue) { + + fPreprocessed = aValue; +} + inline void ComplexTypeInfo::setDerivedBy(const int derivedBy) { fDerivedBy = derivedBy; @@ -462,6 +482,11 @@ ComplexTypeInfo::setContentModel(XMLContentModel* const newModelToAdopt) fContentModel = newModelToAdopt; } +inline void ComplexTypeInfo::setRecursingTypeIndex(const int anIndex) { + + fRecursingTypeIndex = anIndex; +} + // --------------------------------------------------------------------------- // ComplexTypeInfo: Helper methods // --------------------------------------------------------------------------- diff --git a/src/validators/schema/TraverseSchema.cpp b/src/validators/schema/TraverseSchema.cpp index 63320060600b15f7f47a37445ecfe919eb65b03a..003a0ce45cbe835fc29b9b5334a3a36b2f1cc792 100644 --- a/src/validators/schema/TraverseSchema.cpp +++ b/src/validators/schema/TraverseSchema.cpp @@ -189,11 +189,12 @@ TraverseSchema::TraverseSchema( const DOM_Element& schemaRoot , fTargetNSURI(-1) , fEmptyNamespaceURI(-1) , fCurrentScope(Grammar::TOP_LEVEL_SCOPE) - , fAnonXSTypeCount(0) - , fCircularCheckIndex(0) , fFinalDefault(0) , fBlockDefault(0) , fScopeCount(0) + , fRecursingElemIndex(0) + , fAnonXSTypeCount(0) + , fCircularCheckIndex(0) , fTargetNSURIString(0) , fDatatypeRegistry(0) , fGrammarResolver(grammarResolver) @@ -229,6 +230,8 @@ TraverseSchema::TraverseSchema( const DOM_Element& schemaRoot , fIC_NodeListNS(0) , fIC_ElementsNS(0) , fIC_NamespaceDepthNS(0) + , fRecursingAnonTypes(0) + , fRecursingTypeNames(0) { try { @@ -1060,7 +1063,8 @@ int TraverseSchema::traverseSimpleTypeDecl(const DOM_Element& childElem, * ( (attribute | attributeGroup)* , anyAttribute?)))) * </complexType> */ -int TraverseSchema::traverseComplexTypeDecl(const DOM_Element& elem) { +int TraverseSchema::traverseComplexTypeDecl(const DOM_Element& elem, + const XMLCh* const recursingTypeName) { // Get the attributes of the complexType const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME); @@ -1074,7 +1078,10 @@ int TraverseSchema::traverseComplexTypeDecl(const DOM_Element& elem) { return -1; } - name = genAnonTypeName(fgAnonCNamePrefix); + if (recursingTypeName) + name = recursingTypeName; + else + name = genAnonTypeName(fgAnonCNamePrefix); } if (!XMLString::isValidNCName(name)) { @@ -1094,11 +1101,13 @@ int TraverseSchema::traverseComplexTypeDecl(const DOM_Element& elem) { int typeNameIndex = fStringPool->addOrFind(fBuffer.getRawBuffer()); const XMLCh* fullName = fStringPool->getValueForId(typeNameIndex); - if (topLevel) { + ComplexTypeInfo* typeInfo = 0; + + if (topLevel || recursingTypeName) { - ComplexTypeInfo* temp = fComplexTypeRegistry->get(fullName); + typeInfo = fComplexTypeRegistry->get(fullName); - if (temp != 0 ) { + if (typeInfo && !typeInfo->getPreprocessed()) { return typeNameIndex; } } @@ -1113,10 +1122,30 @@ int TraverseSchema::traverseComplexTypeDecl(const DOM_Element& elem) { // ----------------------------------------------------------------------- // Create a new instance // ----------------------------------------------------------------------- - ComplexTypeInfo* typeInfo = new ComplexTypeInfo(); + bool preProcessFlag = (typeInfo) ? typeInfo->getPreprocessed() : false; unsigned int previousCircularCheckIndex = fCircularCheckIndex; int previousScope = fCurrentScope; - fCurrentScope = fScopeCount++; + + if (preProcessFlag) { + + fCurrentScope = typeInfo->getScopeDefined(); + typeInfo->setPreprocessed(false); + } + else { + + // ------------------------------------------------------------------ + // Register the type + // ------------------------------------------------------------------ + typeInfo = new ComplexTypeInfo(); + fCurrentScope = fScopeCount++; + fComplexTypeRegistry->put((void*) fullName, typeInfo); + typeInfo->setTypeName(fullName); + typeInfo->setScopeDefined(fCurrentScope); + } + + fCurrentTypeNameStack->addElement(typeNameIndex); + ComplexTypeInfo* saveTypeInfo = fCurrentComplexType; + fCurrentComplexType = typeInfo; // ------------------------------------------------------------------ // First, handle any ANNOTATION declaration and get next child @@ -1124,18 +1153,6 @@ int TraverseSchema::traverseComplexTypeDecl(const DOM_Element& elem) { DOM_Element child = checkContent(elem, XUtil::getFirstChildElement(elem), true); - // ------------------------------------------------------------------ - // Register the type - // ------------------------------------------------------------------ - // Register the type first, so that in case of a recursive element type - // declaration, we can retrieve the complexType info (though the rest of - fComplexTypeRegistry->put((void*) fullName, typeInfo); - typeInfo->setTypeName(fullName); - typeInfo->setScopeDefined(fCurrentScope); - fCurrentTypeNameStack->addElement(typeNameIndex); - ComplexTypeInfo* saveTypeInfo = fCurrentComplexType; - fCurrentComplexType = typeInfo; - // ------------------------------------------------------------------ // Process the content of the complex type declaration // ------------------------------------------------------------------ @@ -1182,39 +1199,62 @@ int TraverseSchema::traverseComplexTypeDecl(const DOM_Element& elem) { } } } - catch(TraverseSchema::ExceptionCodes) { - defaultComplexTypeInfo(typeInfo); + catch(const TraverseSchema::ExceptionCodes aCode) { + if (aCode == TraverseSchema::InvalidComplexTypeInfo) + defaultComplexTypeInfo(typeInfo); + else if (aCode == TraverseSchema::RecursingElement) + typeInfo->setPreprocessed(); } // ------------------------------------------------------------------ // Finish the setup of the typeInfo // ------------------------------------------------------------------ - const XMLCh* blockAttVal = getElementAttValue(elem, SchemaSymbols::fgATT_BLOCK); - const XMLCh* finalAttVal = getElementAttValue(elem, SchemaSymbols::fgATT_FINAL); - const XMLCh* abstractAttVal = getElementAttValue(elem, SchemaSymbols::fgATT_ABSTRACT); - int blockSet = parseBlockSet(blockAttVal, C_Block); - int finalSet = parseFinalSet(finalAttVal, EC_Final); + if (!preProcessFlag) { - typeInfo->setBlockSet(blockSet); - typeInfo->setFinalSet(finalSet); + const XMLCh* blockAttVal = getElementAttValue(elem, SchemaSymbols::fgATT_BLOCK); + const XMLCh* finalAttVal = getElementAttValue(elem, SchemaSymbols::fgATT_FINAL); + const XMLCh* abstractAttVal = getElementAttValue(elem, SchemaSymbols::fgATT_ABSTRACT); + int blockSet = parseBlockSet(blockAttVal, C_Block); + int finalSet = parseFinalSet(finalAttVal, EC_Final); - if (XMLString::stringLen(abstractAttVal) - && (!XMLString::compareString(abstractAttVal, SchemaSymbols::fgATTVAL_TRUE) - || !XMLString::compareString(abstractAttVal, fgValueOne))) { - typeInfo->setAbstract(true); - } - else { - typeInfo->setAbstract(false); + typeInfo->setBlockSet(blockSet); + typeInfo->setFinalSet(finalSet); + + if (XMLString::stringLen(abstractAttVal) + && (!XMLString::compareString(abstractAttVal, SchemaSymbols::fgATTVAL_TRUE) + || !XMLString::compareString(abstractAttVal, fgValueOne))) { + typeInfo->setAbstract(true); + } + else { + typeInfo->setAbstract(false); + } } + // ------------------------------------------------------------------ + // Traverse anonymous complex types for recursing elements + // ------------------------------------------------------------------ + resetCurrentTypeNameStack(0); + fCircularCheckIndex = previousCircularCheckIndex; + + int i = fRecursingElemIndex - 1; + int recursingTypeIndex = typeInfo->getRecursingTypeIndex(); + + for (; i >= recursingTypeIndex && recursingTypeIndex != -1; i--) { + + DOM_Element elem = fRecursingAnonTypes->elementAt(i); + const XMLCh* typeName = fRecursingTypeNames->elementAt(i); + + fRecursingAnonTypes->removeElementAt(i); + fRecursingTypeNames->removeElementAt(i); + fRecursingElemIndex--; + traverseComplexTypeDecl(elem, typeName); + } + // ------------------------------------------------------------------ // Before exiting, restore the scope, mainly for nested anonymous types // ------------------------------------------------------------------ fCurrentScope = previousScope; fCurrentComplexType = saveTypeInfo; - fCircularCheckIndex = previousCircularCheckIndex; - resetCurrentTypeNameStack(0); - return typeNameIndex; } @@ -2280,7 +2320,24 @@ QName* TraverseSchema::traverseElementDecl(const DOM_Element& elem, bool& toDele noErrorFound = false; } else if (!isDuplicate) { + typeInfo->setElementId(elemDecl->getId()); + + //Recursing element + if (typeInfo->getPreprocessed()) { + + const XMLCh* typeInfoName = typeInfo->getTypeName(); + + if (!fRecursingAnonTypes) { + fRecursingAnonTypes = new ValueVectorOf<DOM_Element>(8); + fRecursingTypeNames = new ValueVectorOf<const XMLCh*>(8); + } + + fRecursingAnonTypes->addElement(content); + fRecursingTypeNames->addElement(typeInfoName + XMLString::indexOf(typeInfoName, chComma) + 1); + typeInfo->getBaseComplexTypeInfo()->setRecursingTypeIndex(fRecursingElemIndex); + fRecursingElemIndex++; + } } anonymousType = true; @@ -5621,11 +5678,21 @@ void TraverseSchema::processBaseTypeInfo(const XMLCh* const baseName, baseComplexTypeInfo = fComplexTypeRegistry->get(fullBaseName); // Circular check - if (baseComplexTypeInfo && - fCurrentTypeNameStack->containsElement(fStringPool->addOrFind(fullBaseName), fCircularCheckIndex)) { + if (baseComplexTypeInfo) { - reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::NoCircularDefinition, fullBaseName); - throw TraverseSchema::InvalidComplexTypeInfo; + if (fCurrentTypeNameStack->containsElement(fStringPool->addOrFind(fullBaseName), fCircularCheckIndex)) { + + reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::NoCircularDefinition, fullBaseName); + throw TraverseSchema::InvalidComplexTypeInfo; + } + else if (fCurrentTypeNameStack->containsElement(fStringPool->addOrFind(fullBaseName))) { + + typeInfo->setBaseComplexTypeInfo(baseComplexTypeInfo); + throw TraverseSchema::RecursingElement; + } + else if (baseComplexTypeInfo->getPreprocessed()) { + baseComplexTypeInfo = 0; + } } } @@ -8502,6 +8569,8 @@ void TraverseSchema::cleanUp() { delete fIC_ElementsNS; delete fIC_NamespaceDepthNS; delete fIC_NodeListNS; + delete fRecursingAnonTypes; + delete fRecursingTypeNames; } /** diff --git a/src/validators/schema/TraverseSchema.hpp b/src/validators/schema/TraverseSchema.hpp index 4a9f4c92953d7ccc7876769e3f99edb241c4a39e..2222edd5f687c633a090f732d3b7ff123e215293 100644 --- a/src/validators/schema/TraverseSchema.hpp +++ b/src/validators/schema/TraverseSchema.hpp @@ -181,7 +181,7 @@ private: const bool isMixed); int traverseSimpleTypeDecl(const DOM_Element& childElem, int baseRefContext = SchemaSymbols::EMPTY_SET); - int traverseComplexTypeDecl(const DOM_Element& childElem); + int traverseComplexTypeDecl(const DOM_Element& childElem, const XMLCh* const recursingTypeName = 0); int traverseByList(const DOM_Element& rootElem, const DOM_Element& contentElem, const int typeNameIndex, @@ -757,8 +757,7 @@ private: { NoException = 0, InvalidComplexTypeInfo = 1, - ParticleDerivationNotOK = 2, - InvalidContentSpecType = 3 + RecursingElement = 2 }; enum @@ -777,7 +776,8 @@ private: int fCurrentScope; int fFinalDefault; int fBlockDefault; - int fScopeCount; + int fScopeCount; + int fRecursingElemIndex; unsigned int fAnonXSTypeCount; unsigned int fCircularCheckIndex; const XMLCh* fTargetNSURIString; @@ -817,6 +817,8 @@ private: RefHashTableOf<ValueVectorOf<DOM_Element> >* fIC_NodeListNS; RefHashTableOf<ElemVector>* fIC_ElementsNS; RefHashTableOf<ValueVectorOf<unsigned int> >* fIC_NamespaceDepthNS; + ValueVectorOf<DOM_Element>* fRecursingAnonTypes; + ValueVectorOf<const XMLCh*>* fRecursingTypeNames; friend class GeneralAttributeCheck; };