diff --git a/src/xercesc/internal/XMLScanner.cpp b/src/xercesc/internal/XMLScanner.cpp index 2fd2ade99f0f3f8cd29a09ee007e9abc71b6120e..2b6fb05cd425ed4ea54eff47ce7eab04dd472d77 100644 --- a/src/xercesc/internal/XMLScanner.cpp +++ b/src/xercesc/internal/XMLScanner.cpp @@ -1042,8 +1042,12 @@ void XMLScanner::initValidator(XMLValidator* theValidator) { theValidator->setScannerInfo(this, &fReaderMgr, &fBufMgr); theValidator->setErrorReporter(fErrorReporter); - if (theValidator->handlesSchema()) + if (theValidator->handlesSchema()) { + ((SchemaValidator*) theValidator)->setGrammarResolver(fGrammarResolver); + ((SchemaValidator*) theValidator)->setErrorHandler(fErrorHandler); + ((SchemaValidator*) theValidator)->setExitOnFirstFatal(fExitOnFirstFatal); + } } void XMLScanner::resetEntityDeclPool() { diff --git a/src/xercesc/internal/XMLScanner.hpp b/src/xercesc/internal/XMLScanner.hpp index e0f107cd202e372c92dff5ca24c9efd6992546f6..25743c369a81da646efea5829e2358e108ed415a 100644 --- a/src/xercesc/internal/XMLScanner.hpp +++ b/src/xercesc/internal/XMLScanner.hpp @@ -56,8 +56,11 @@ /* * $Log$ - * Revision 1.1 2002/02/01 22:22:03 peiyongz - * Initial revision + * Revision 1.2 2002/03/25 20:25:32 knoaman + * Move particle derivation checking from TraverseSchema to SchemaValidator. + * + * Revision 1.1.1.1 2002/02/01 22:22:03 peiyongz + * sane_include * * Revision 1.38 2001/11/30 22:19:15 peiyongz * cleanUp function made member function @@ -1190,6 +1193,7 @@ inline void XMLScanner::setErrorReporter(XMLErrorReporter* const errHandler) inline void XMLScanner::setErrorHandler(ErrorHandler* const handler) { fErrorHandler = handler; + fSchemaValidator->setErrorHandler(handler); } inline void XMLScanner::setEntityHandler(XMLEntityHandler* const entityHandler) @@ -1206,6 +1210,7 @@ inline void XMLScanner::setEntityResolver(EntityResolver* const handler) inline void XMLScanner::setExitOnFirstFatal(const bool newValue) { fExitOnFirstFatal = newValue; + fSchemaValidator->setExitOnFirstFatal(newValue); } inline void XMLScanner::setValidationConstraintFatal(const bool newValue) diff --git a/src/xercesc/validators/schema/SchemaValidator.cpp b/src/xercesc/validators/schema/SchemaValidator.cpp index 380efa1c794a687d06531007e0dedfb0f2edce0e..cf315a281245d74bb7fa38621a10be7fdb87e11e 100644 --- a/src/xercesc/validators/schema/SchemaValidator.cpp +++ b/src/xercesc/validators/schema/SchemaValidator.cpp @@ -56,6 +56,9 @@ /* * $Log$ + * Revision 1.6 2002/03/25 20:25:32 knoaman + * Move particle derivation checking from TraverseSchema to SchemaValidator. + * * Revision 1.5 2002/02/26 14:26:10 tng * [Bug 6672] SAXValidator results in an access violation when validating against schema with empty element that has default value. * @@ -170,6 +173,8 @@ #include <xercesc/validators/schema/SchemaSymbols.hpp> #include <xercesc/validators/schema/SchemaValidator.hpp> #include <xercesc/validators/schema/SubstitutionGroupComparator.hpp> +#include <xercesc/validators/schema/XercesGroupInfo.hpp> +#include <xercesc/validators/schema/XSDLocator.hpp> // --------------------------------------------------------------------------- // SchemaValidator: Constructors and Destructor @@ -827,6 +832,26 @@ void SchemaValidator::preContentValidation(bool reuseGrammar) { ComplexTypeInfo& curTypeInfo = complexTypeEnum.nextElement(); curTypeInfo.checkUniqueParticleAttribution(&sGrammar, fGrammarResolver, getScanner()->getURIStringPool(), this); + checkParticleDerivation(&sGrammar, &curTypeInfo); + } + + RefHashTableOf<XercesGroupInfo>* groupInfoRegistry = sGrammar.getGroupInfoRegistry(); + RefHashTableOfEnumerator<XercesGroupInfo> groupEnum(groupInfoRegistry); + + while (groupEnum.hasMoreElements()) { + + XercesGroupInfo& curGroup = groupEnum.nextElement(); + XercesGroupInfo* baseGroup = curGroup.getBaseGroup(); + + if (baseGroup) { + try { + checkParticleDerivationOk(&sGrammar, curGroup.getContentSpec(), curGroup.getScope(), + baseGroup->getContentSpec(), baseGroup->getScope()); + } + catch (const XMLException& excep) { + fSchemaErrorReporter.emitError(XMLErrs::DisplayErrorMessage, XMLUni::fgXMLErrDomain, curGroup.getLocator(), excep.getMessage()); + } + } } } } @@ -936,3 +961,819 @@ void SchemaValidator::normalizeWhiteSpace(DatatypeValidator* dV, const XMLCh* co fDatatypeBuffer.append(toFill.getRawBuffer()); } + +// --------------------------------------------------------------------------- +// SchemaValidator: Particle Derivation Checking +// --------------------------------------------------------------------------- +void SchemaValidator::checkParticleDerivation(SchemaGrammar* const currentGrammar, + const ComplexTypeInfo* const curTypeInfo) { + + ComplexTypeInfo* baseTypeInfo = 0; + ContentSpecNode* curSpecNode = 0; + + if (curTypeInfo->getDerivedBy() == SchemaSymbols::RESTRICTION + && ((baseTypeInfo = curTypeInfo->getBaseComplexTypeInfo()) != 0) + && ((curSpecNode = curTypeInfo->getContentSpec()) != 0)) { + + try { + checkParticleDerivationOk(currentGrammar, curSpecNode, + curTypeInfo->getScopeDefined(), + baseTypeInfo->getContentSpec(), + baseTypeInfo->getScopeDefined(), baseTypeInfo); + } + catch (const XMLException& excep) { + fSchemaErrorReporter.emitError(XMLErrs::DisplayErrorMessage, XMLUni::fgXMLErrDomain, curTypeInfo->getLocator(), excep.getMessage()); + } + } +} + +void SchemaValidator::checkParticleDerivationOk(SchemaGrammar* const aGrammar, + ContentSpecNode* const curNode, + const int derivedScope, + ContentSpecNode* const baseNode, + const int baseScope, + const ComplexTypeInfo* const baseInfo) { + + // Check for pointless occurrences of all, choice, sequence. The result is + // the contentspec which is not pointless. If the result is a non-pointless + // group, Vector is filled in with the children of interest + if (!curNode || !baseNode) + return; + + ContentSpecNode* curSpecNode = curNode; + ContentSpecNode* baseSpecNode = baseNode; + ValueVectorOf<ContentSpecNode*> curVector(8); + ValueVectorOf<ContentSpecNode*> baseVector(8); + ContentSpecNode::NodeTypes curNodeType = curSpecNode->getType(); + ContentSpecNode::NodeTypes baseNodeType = baseSpecNode->getType(); + + if (curNodeType == ContentSpecNode::Sequence || + curNodeType == ContentSpecNode::Choice || + curNodeType == ContentSpecNode::All) { + curSpecNode = checkForPointlessOccurrences(curSpecNode, curNodeType, &curVector); + } + + if (baseNodeType == ContentSpecNode::Sequence || + baseNodeType == ContentSpecNode::Choice || + baseNodeType == ContentSpecNode::All) { + baseSpecNode = checkForPointlessOccurrences(baseSpecNode, baseNodeType, &baseVector); + } + + curNodeType = curSpecNode->getType(); + baseNodeType = baseSpecNode->getType(); + + switch (curNodeType & 0x0f) { + case ContentSpecNode::Leaf: + { + switch (baseNodeType & 0x0f) { + case ContentSpecNode::Leaf: + { + checkNameAndTypeOK(aGrammar, curSpecNode, derivedScope, baseSpecNode, baseScope, baseInfo); + return; + } + case ContentSpecNode::Any: + case ContentSpecNode::Any_Other: + case ContentSpecNode::Any_NS: + { + checkNSCompat(curSpecNode, baseSpecNode); + return; + } + case ContentSpecNode::Choice: + case ContentSpecNode::Sequence: + case ContentSpecNode::All: + { + checkRecurseAsIfGroup(aGrammar, curSpecNode, derivedScope, + baseSpecNode, baseScope, &baseVector, baseInfo); + return; + } + default: + { + ThrowXML(RuntimeException, XMLExcepts::PD_InvalidContentType); + } + } + } + case ContentSpecNode::Any: + case ContentSpecNode::Any_Other: + case ContentSpecNode::Any_NS: + { + switch (baseNodeType & 0x0f) { + case ContentSpecNode::Any: + case ContentSpecNode::Any_Other: + case ContentSpecNode::Any_NS: + { + checkNSSubset(curSpecNode, baseSpecNode); + return; + } + case ContentSpecNode::Choice: + case ContentSpecNode::Sequence: + case ContentSpecNode::All: + case ContentSpecNode::Leaf: + { + ThrowXML(RuntimeException, XMLExcepts::PD_ForbiddenRes1); + } + default: + { + ThrowXML(RuntimeException, XMLExcepts::PD_InvalidContentType); + } + } + } + case ContentSpecNode::All: + { + switch (baseNodeType & 0x0f) { + case ContentSpecNode::Any: + case ContentSpecNode::Any_Other: + case ContentSpecNode::Any_NS: + { + checkNSRecurseCheckCardinality(aGrammar, curSpecNode, &curVector, derivedScope, baseSpecNode); + return; + } + case ContentSpecNode::All: + { + checkRecurse(aGrammar, curSpecNode, derivedScope, &curVector, + baseSpecNode, baseScope, &baseVector, baseInfo); + return; + } + case ContentSpecNode::Choice: + case ContentSpecNode::Sequence: + case ContentSpecNode::Leaf: + { + ThrowXML(RuntimeException, XMLExcepts::PD_ForbiddenRes2); + } + default: + { + ThrowXML(RuntimeException, XMLExcepts::PD_InvalidContentType); + } + } + } + case ContentSpecNode::Choice: + { + switch (baseNodeType & 0x0f) { + case ContentSpecNode::Any: + case ContentSpecNode::Any_Other: + case ContentSpecNode::Any_NS: + { + checkNSRecurseCheckCardinality(aGrammar, curSpecNode, &curVector, derivedScope, baseSpecNode); + return; + } + case ContentSpecNode::Choice: + { + checkRecurse(aGrammar, curSpecNode, derivedScope, &curVector, + baseSpecNode, baseScope, &baseVector, baseInfo, true); + return; + } + case ContentSpecNode::All: + case ContentSpecNode::Sequence: + case ContentSpecNode::Leaf: + { + ThrowXML(RuntimeException, XMLExcepts::PD_ForbiddenRes3); + } + default: + { + ThrowXML(RuntimeException, XMLExcepts::PD_InvalidContentType); + } + } + } + case ContentSpecNode::Sequence: + { + switch (baseNodeType & 0x0f) { + case ContentSpecNode::Any: + case ContentSpecNode::Any_Other: + case ContentSpecNode::Any_NS: + { + checkNSRecurseCheckCardinality(aGrammar, curSpecNode, &curVector, derivedScope, baseSpecNode); + return; + } + case ContentSpecNode::All: + { + checkRecurseUnordered(aGrammar, curSpecNode, &curVector, derivedScope, + baseSpecNode, &baseVector, baseScope, baseInfo); + return; + } + case ContentSpecNode::Sequence: + { + checkRecurse(aGrammar, curSpecNode, derivedScope, &curVector, + baseSpecNode, baseScope, &baseVector, baseInfo); + return; + } + case ContentSpecNode::Choice: + { + checkMapAndSum(aGrammar, curSpecNode, &curVector, derivedScope, + baseSpecNode, &baseVector, baseScope, baseInfo); + return; + } + case ContentSpecNode::Leaf: + { + ThrowXML(RuntimeException, XMLExcepts::PD_ForbiddenRes4); + } + default: + { + ThrowXML(RuntimeException, XMLExcepts::PD_InvalidContentType); + } + } + } + } +} + +ContentSpecNode* +SchemaValidator::checkForPointlessOccurrences(ContentSpecNode* const specNode, + const ContentSpecNode::NodeTypes nodeType, + ValueVectorOf<ContentSpecNode*>* const nodes) { + + ContentSpecNode* rightNode = specNode->getSecond(); + int min = specNode->getMinOccurs(); + int max = specNode->getMaxOccurs(); + + if (!rightNode) { + + gatherChildren(nodeType, specNode->getFirst(), nodes); + + if (nodes->size() == 1 && min == 1 && max == 1) { + return nodes->elementAt(0); + } + + return specNode; + } + + gatherChildren(nodeType, specNode->getFirst(), nodes); + gatherChildren(nodeType, rightNode, nodes); + + return specNode; +} + +void SchemaValidator::gatherChildren(const ContentSpecNode::NodeTypes parentNodeType, + ContentSpecNode* const specNode, + ValueVectorOf<ContentSpecNode*>* const nodes) { + + if (!specNode) { + return; + } + + int min = specNode->getMinOccurs(); + int max = specNode->getMaxOccurs(); + ContentSpecNode::NodeTypes nodeType = specNode->getType(); + ContentSpecNode* rightNode = specNode->getSecond(); + + if (nodeType == ContentSpecNode::Leaf || + (nodeType & 0x0f) == ContentSpecNode::Any || + (nodeType & 0x0f) == ContentSpecNode::Any_NS || + (nodeType & 0x0f) == ContentSpecNode::Any_Other) { + nodes->addElement(specNode); + } + else if (min !=1 || max != 1) { + nodes->addElement(specNode); + } + else if (!rightNode) { + gatherChildren(nodeType, specNode->getFirst(), nodes); + } + else if (parentNodeType == nodeType) { + + gatherChildren(nodeType, specNode->getFirst(), nodes); + gatherChildren(nodeType, rightNode, nodes); + } + else { + nodes->addElement(specNode); + } +} + +void +SchemaValidator::checkNSCompat(const ContentSpecNode* const derivedSpecNode, + const ContentSpecNode* const baseSpecNode) { + + // check Occurrence ranges + if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(), + baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) { + ThrowXML1(RuntimeException, XMLExcepts::PD_OccurRangeE, + derivedSpecNode->getElement()->getLocalPart()); + } + + // check wildcard subset + if (!wildcardEltAllowsNamespace(baseSpecNode, derivedSpecNode->getElement()->getURI())) { + ThrowXML1(RuntimeException, XMLExcepts::PD_NSCompat1, + derivedSpecNode->getElement()->getLocalPart()); + } +} + +bool +SchemaValidator::wildcardEltAllowsNamespace(const ContentSpecNode* const baseSpecNode, + const unsigned int derivedURI) { + + ContentSpecNode::NodeTypes nodeType = baseSpecNode->getType(); + + if ((nodeType & 0x0f) == ContentSpecNode::Any) { + return true; + } + + unsigned int baseURI = baseSpecNode->getElement()->getURI(); + + if ((nodeType & 0x0f) == ContentSpecNode::Any_NS) { + if (derivedURI == baseURI) { + return true; + } + } + else { // must be ANY_OTHER + if (derivedURI != baseURI && derivedURI != getScanner()->getEmptyNamespaceId()) { + return true; + } + } + + return false; +} + +void +SchemaValidator::checkNameAndTypeOK(SchemaGrammar* const currentGrammar, + const ContentSpecNode* const derivedSpecNode, + const int derivedScope, + const ContentSpecNode* const baseSpecNode, + const int baseScope, + const ComplexTypeInfo* const baseInfo) { + + unsigned int derivedURI = derivedSpecNode->getElement()->getURI(); + unsigned int baseURI = baseSpecNode->getElement()->getURI(); + const XMLCh* derivedName = derivedSpecNode->getElement()->getLocalPart(); + const XMLCh* baseName = baseSpecNode->getElement()->getLocalPart(); + + if (XMLString::compareString(derivedName, baseName) || derivedURI != baseURI) { + ThrowXML(RuntimeException, XMLExcepts::PD_NameTypeOK1); + } + + // case of mixed complex types with attributes only + if (derivedURI == XMLElementDecl::fgPCDataElemId) { + return; + } + + if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(), + baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) { + ThrowXML1(RuntimeException, XMLExcepts::PD_OccurRangeE, derivedName); + } + + SchemaGrammar* aGrammar = currentGrammar; + const XMLCh* schemaURI = getScanner()->getURIStringPool()->getValueForId(derivedURI); + + if (derivedURI != getScanner()->getEmptyNamespaceId()) { + aGrammar= (SchemaGrammar*) fGrammarResolver->getGrammar(schemaURI); + } + + if (!aGrammar) { //something is wrong + return; + } + + SchemaElementDecl* derivedElemDecl = findElement(derivedScope, derivedURI, derivedName, aGrammar); + + if (!derivedElemDecl) { + return; + } + + SchemaElementDecl* baseElemDecl = + findElement(baseScope, baseURI, baseName, aGrammar, baseInfo); + + if (!baseElemDecl) { + return; + } + + int derivedFlags = derivedElemDecl->getMiscFlags(); + int baseFlags = baseElemDecl->getMiscFlags(); + + if (((baseFlags & SchemaSymbols::NILLABLE) == 0) && + ((derivedFlags & SchemaSymbols::NILLABLE) != 0)) { + ThrowXML1(RuntimeException, XMLExcepts::PD_NameTypeOK2, derivedName); + } + + const XMLCh* derivedDefVal = derivedElemDecl->getDefaultValue(); + const XMLCh* baseDefVal = baseElemDecl->getDefaultValue(); + + if (baseDefVal && (baseFlags & SchemaSymbols::FIXED) != 0 && + ((derivedFlags & SchemaSymbols::FIXED) == 0 || + XMLString::compareString(derivedDefVal, baseDefVal))) { + ThrowXML1(RuntimeException, XMLExcepts::PD_NameTypeOK3, derivedName); + } + + int derivedBlockSet = derivedElemDecl->getBlockSet(); + int baseBlockSet = baseElemDecl->getBlockSet(); + + if ((derivedBlockSet & baseBlockSet) != baseBlockSet) { + ThrowXML1(RuntimeException, XMLExcepts::PD_NameTypeOK4, derivedName); + } + + // check identity constraints + checkICRestriction(derivedElemDecl, baseElemDecl, derivedName, baseName); + + // check that the derived element's type is derived from the base's. + checkTypesOK(derivedElemDecl, baseElemDecl, derivedName); +} + +SchemaElementDecl* +SchemaValidator::findElement(const int scope, const unsigned int uriIndex, + const XMLCh* const name, + SchemaGrammar* const grammar, + const ComplexTypeInfo* const typeInfo) { + + // check for element at given scope first + SchemaElementDecl* elemDecl = (SchemaElementDecl*) grammar->getElemDecl(uriIndex, name, 0, scope); + + // if not found, check at global scope + if (!elemDecl) { + + elemDecl = (SchemaElementDecl*) + grammar->getElemDecl(uriIndex, name, 0, Grammar::TOP_LEVEL_SCOPE); + + // if still not found, and base is specified, look it up there + if (!elemDecl && typeInfo) { + + const ComplexTypeInfo* baseInfo = typeInfo; + + while (baseInfo) { + + elemDecl = (SchemaElementDecl*) + grammar->getElemDecl(uriIndex, name, 0, baseInfo->getScopeDefined()); + + if (elemDecl) { + break; + } + + baseInfo = baseInfo->getBaseComplexTypeInfo(); + } + } + } + + return elemDecl; +} + +void +SchemaValidator::checkICRestriction(const SchemaElementDecl* const derivedElemDecl, + const SchemaElementDecl* const baseElemDecl, + const XMLCh* const derivedElemName, + const XMLCh* const baseElemName) { + + // REVIST - need to get more clarification + unsigned int derivedICCount = derivedElemDecl->getIdentityConstraintCount(); + unsigned int baseICCount = baseElemDecl->getIdentityConstraintCount(); + + if (derivedICCount > baseICCount) { + ThrowXML2(RuntimeException, XMLExcepts::PD_NameTypeOK6, derivedElemName, baseElemName); + } + + for (unsigned int i=0; i < derivedICCount; i++) { + + bool found = false; + IdentityConstraint* ic= derivedElemDecl->getIdentityConstraintAt(i); + + for (unsigned int j=0; j < baseICCount; j++) { + if (*ic == *(baseElemDecl->getIdentityConstraintAt(j))) { + + found = true; + break; + } + } + + if (!found) { + ThrowXML2(RuntimeException, XMLExcepts::PD_NameTypeOK7, derivedElemName, baseElemName); + } + } +} + +void +SchemaValidator::checkTypesOK(const SchemaElementDecl* const derivedElemDecl, + const SchemaElementDecl* const baseElemDecl, + const XMLCh* const derivedElemName) { + + SchemaElementDecl::ModelTypes baseType = baseElemDecl->getModelType(); + + if (baseType == SchemaElementDecl::Any) { + return; + } + + ComplexTypeInfo* rInfo = derivedElemDecl->getComplexTypeInfo(); + ComplexTypeInfo* bInfo = baseElemDecl->getComplexTypeInfo(); + + if (derivedElemDecl->getModelType() == SchemaElementDecl::Simple) { + + if (baseType != SchemaElementDecl::Simple) { + ThrowXML1(RuntimeException, XMLExcepts::PD_NameTypeOK5, derivedElemName); + } + + if (!rInfo) { + + DatatypeValidator* bDV = baseElemDecl->getDatatypeValidator(); + + if (bInfo || bDV == 0 || + !bDV->isSubstitutableBy(derivedElemDecl->getDatatypeValidator())) { + ThrowXML1(RuntimeException, XMLExcepts::PD_NameTypeOK5, derivedElemName); + } + + return; + } + } + + if (rInfo == bInfo) + return; + + for (; rInfo && rInfo != bInfo; rInfo = rInfo->getBaseComplexTypeInfo()) { + if (rInfo->getDerivedBy() != SchemaSymbols::RESTRICTION) { + + rInfo = 0; + break; + } + } + + if (!rInfo) { + ThrowXML1(RuntimeException, XMLExcepts::PD_NameTypeOK5, derivedElemName); + } +} + +void +SchemaValidator::checkRecurseAsIfGroup(SchemaGrammar* const currentGrammar, + ContentSpecNode* const derivedSpecNode, + const int derivedScope, + const ContentSpecNode* const baseSpecNode, + const int baseScope, + ValueVectorOf<ContentSpecNode*>* const baseNodes, + const ComplexTypeInfo* const baseInfo) { + + ContentSpecNode::NodeTypes baseType = baseSpecNode->getType(); + ValueVectorOf<ContentSpecNode*> derivedNodes(1); + bool toLax = false; + + //Treat the element as if it were in a group of the same variety as base + ContentSpecNode derivedGroupNode(baseType, derivedSpecNode, 0, false); + + derivedNodes.addElement(derivedSpecNode); + + if (baseSpecNode->getType() == ContentSpecNode::Choice) { + toLax = true; + } + + checkRecurse(currentGrammar, &derivedGroupNode, derivedScope, &derivedNodes, + baseSpecNode, baseScope, baseNodes, baseInfo, toLax); +} + +void +SchemaValidator::checkRecurse(SchemaGrammar* const currentGrammar, + const ContentSpecNode* const derivedSpecNode, + const int derivedScope, + ValueVectorOf<ContentSpecNode*>* const derivedNodes, + const ContentSpecNode* const baseSpecNode, + const int baseScope, + ValueVectorOf<ContentSpecNode*>* const baseNodes, + const ComplexTypeInfo* const baseInfo, + const bool toLax) { + + if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(), + baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) { + ThrowXML(RuntimeException, XMLExcepts::PD_Recurse1); + } + + // check for mapping of children + XMLExcepts::Codes codeToThrow = XMLExcepts::NoError; + unsigned int count1= derivedNodes->size(); + unsigned int count2= baseNodes->size(); + unsigned int current = 0; + + for (unsigned int i=0; i<count1; i++) { + + bool matched = false; + + for (unsigned int j = current; j < count2; j++) { + + ContentSpecNode* baseNode = baseNodes->elementAt(j); + current++; + + try { + + checkParticleDerivationOk(currentGrammar, derivedNodes->elementAt(i), + derivedScope, baseNode, baseScope, baseInfo); + matched = true; + break; + } + catch(const XMLException&) { + if (!toLax && baseNode->getMinTotalRange()) { + break; + } + } + } + + // did not find a match + if (!matched) { + + codeToThrow = XMLExcepts::PD_Recurse2; + break; + } + } + + // Now, see if there are some elements in the base we didn't match up + // in case of Sequence or All + if (!toLax && codeToThrow == XMLExcepts::NoError) { + for (unsigned int j = current; j < count2; j++) { + if (baseNodes->elementAt(j)->getMinTotalRange()) { //!emptiable + + codeToThrow = XMLExcepts::PD_Recurse2; + break; + } + } + } + + if (codeToThrow != XMLExcepts::NoError) { + ThrowXML(RuntimeException, codeToThrow); + } +} + +void SchemaValidator::checkNSSubset(const ContentSpecNode* const derivedSpecNode, + const ContentSpecNode* const baseSpecNode) { + + // check Occurrence ranges + if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(), + baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) { + ThrowXML(RuntimeException, XMLExcepts::PD_NSSubset1); + } + + if (!isWildCardEltSubset(derivedSpecNode, baseSpecNode)) { + ThrowXML(RuntimeException, XMLExcepts::PD_NSSubset2); + } +} + +bool +SchemaValidator::isWildCardEltSubset(const ContentSpecNode* const derivedSpecNode, + const ContentSpecNode* const baseSpecNode) { + + ContentSpecNode::NodeTypes baseType = baseSpecNode->getType(); + + if ((baseType & 0x0f) == ContentSpecNode::Any) { + return true; + } + + ContentSpecNode::NodeTypes derivedType = derivedSpecNode->getType(); + unsigned int baseURI = baseSpecNode->getElement()->getURI(); + unsigned int derivedURI = derivedSpecNode->getElement()->getURI(); + + if (((derivedType & 0x0f) == ContentSpecNode::Any_Other) && + ((baseType & 0x0f) == ContentSpecNode::Any_Other) && + baseURI == derivedURI) { + return true; + } + + if ((derivedType & 0x0f) == ContentSpecNode::Any_NS) { + + if (((baseType & 0x0f) == ContentSpecNode::Any_NS) && + baseURI == derivedURI) { + return true; + } + + if (((baseType & 0x0f) == ContentSpecNode::Any_Other) && + baseURI != derivedURI) { + return true; + } + } + + return false; +} + +void +SchemaValidator::checkNSRecurseCheckCardinality(SchemaGrammar* const currentGrammar, + const ContentSpecNode* const derivedSpecNode, + ValueVectorOf<ContentSpecNode*>* const derivedNodes, + const int derivedScope, + ContentSpecNode* const baseSpecNode) { + + // Implement total range check + int derivedMin = derivedSpecNode->getMinTotalRange(); + int derivedMax = derivedSpecNode->getMaxTotalRange(); + + // check Occurrence ranges + if (!isOccurrenceRangeOK(derivedMin, derivedMax, baseSpecNode->getMinOccurs(), + baseSpecNode->getMaxOccurs())) { + ThrowXML(RuntimeException, XMLExcepts::PD_NSRecurseCheckCardinality1); + } + + // Check that each member of the group is a valid restriction of the wildcard + unsigned int nodesCount = derivedNodes->size(); + + for (unsigned int i = 0; i < nodesCount; i++) { + checkParticleDerivationOk(currentGrammar, derivedNodes->elementAt(i), derivedScope, baseSpecNode, -1); + } +} + +void +SchemaValidator::checkRecurseUnordered(SchemaGrammar* const currentGrammar, + const ContentSpecNode* const derivedSpecNode, + ValueVectorOf<ContentSpecNode*>* const derivedNodes, + const int derivedScope, + ContentSpecNode* const baseSpecNode, + ValueVectorOf<ContentSpecNode*>* const baseNodes, + const int baseScope, + const ComplexTypeInfo* const baseInfo) { + + // check Occurrence ranges + if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(), + baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) { + ThrowXML(RuntimeException, XMLExcepts::PD_Recurse1); + } + + XMLExcepts::Codes codeToThrow = XMLExcepts::NoError; + unsigned int derivedCount= derivedNodes->size(); + unsigned int baseCount = baseNodes->size(); + bool* foundIt = new bool[baseCount]; + ArrayJanitor<bool> janFoundIt(foundIt); + + for (unsigned k=0; k < baseCount; k++) { + foundIt[k] = false; + } + + // check for mapping of children + for (unsigned int i = 0; i < derivedCount; i++) { + + ContentSpecNode* derivedNode = derivedNodes->elementAt(i); + bool matched = false; + + for (unsigned int j = 0; j < baseCount; j++) { + + try { + + checkParticleDerivationOk(currentGrammar, derivedNode, derivedScope, + baseNodes->elementAt(j), baseScope, baseInfo); + + if (foundIt[j]) { + break; + } + + foundIt[j] = true; + matched = true; + break; + } + catch (const XMLException&) { + } + } + + // didn't find a match. + if (!matched) { + + codeToThrow = XMLExcepts::PD_RecurseUnordered; + break; + } + } + + // For all unmapped particles in base, check to see it it's emptiable or not + if (codeToThrow == XMLExcepts::NoError) { + for (unsigned int j=0; j < baseCount; j++) { + if (!foundIt[j] && baseNodes->elementAt(j)->getMinTotalRange()) { + + codeToThrow = XMLExcepts::PD_RecurseUnordered; + break; + } + } + } + + if (codeToThrow != XMLExcepts::NoError) { + ThrowXML(RuntimeException, codeToThrow); + } +} + +void +SchemaValidator::checkMapAndSum(SchemaGrammar* const currentGrammar, + const ContentSpecNode* const derivedSpecNode, + ValueVectorOf<ContentSpecNode*>* const derivedNodes, + const int derivedScope, + ContentSpecNode* const baseSpecNode, + ValueVectorOf<ContentSpecNode*>* const baseNodes, + const int baseScope, + const ComplexTypeInfo* const baseInfo) { + + // check Occurrence ranges + int derivedCount = derivedNodes->size(); + int baseCount = baseNodes->size(); + int derivedMin = derivedSpecNode->getMinOccurs() * derivedCount; + int derivedMax = derivedSpecNode->getMaxOccurs(); + + if (derivedMax != SchemaSymbols::UNBOUNDED) { + derivedMax *= derivedCount; + } + + if (!isOccurrenceRangeOK(derivedMin, derivedMax, baseSpecNode->getMinOccurs(), + baseSpecNode->getMaxOccurs())) { + ThrowXML(RuntimeException, XMLExcepts::PD_Recurse1); + } + + // check for mapping of children + for (int i = 0; i < derivedCount; i++) { + + ContentSpecNode* derivedNode = derivedNodes->elementAt(i); + bool matched = false; + + for (int j = 0; j < baseCount && !matched; j++) { + + try { + + checkParticleDerivationOk(currentGrammar, derivedNode, derivedScope, + baseNodes->elementAt(j), baseScope, baseInfo); + matched = true; + } + catch (const XMLException&) { + } + } + + // didn't find a match. + if (!matched) { + ThrowXML(RuntimeException, XMLExcepts::PD_MapAndSum); + } + } + +} + diff --git a/src/xercesc/validators/schema/SchemaValidator.hpp b/src/xercesc/validators/schema/SchemaValidator.hpp index 0baee38d3de8ab31dda8b2ec043ae252b1eae0d5..1f7d61c8e74ac3bb66955e2574a2032130d48175 100644 --- a/src/xercesc/validators/schema/SchemaValidator.hpp +++ b/src/xercesc/validators/schema/SchemaValidator.hpp @@ -56,8 +56,11 @@ /* * $Log$ - * Revision 1.1 2002/02/01 22:22:47 peiyongz - * Initial revision + * Revision 1.2 2002/03/25 20:25:32 knoaman + * Move particle derivation checking from TraverseSchema to SchemaValidator. + * + * Revision 1.1.1.1 2002/02/01 22:22:47 peiyongz + * sane_include * * Revision 1.8 2001/11/13 13:25:08 tng * Deprecate function XMLValidator::checkRootElement. @@ -94,9 +97,11 @@ #include <xercesc/framework/XMLValidator.hpp> #include <xercesc/util/RefVectorOf.hpp> #include <xercesc/validators/common/GrammarResolver.hpp> +#include <xercesc/validators/common/ContentSpecNode.hpp> #include <xercesc/validators/datatype/DatatypeValidator.hpp> #include <xercesc/validators/schema/SchemaElementDecl.hpp> #include <xercesc/validators/schema/SchemaGrammar.hpp> +#include <xercesc/validators/schema/XSDErrorReporter.hpp> // // This is a derivative of the abstract validator interface. This class @@ -177,6 +182,91 @@ public: // ----------------------------------------------------------------------- void normalizeWhiteSpace(DatatypeValidator* dV, const XMLCh* const value, XMLBuffer& toFill); + // ----------------------------------------------------------------------- + // Particle Derivation Checking methods + // ----------------------------------------------------------------------- + void checkParticleDerivation(SchemaGrammar* const currentGrammar, + const ComplexTypeInfo* const typeInfo); + void checkParticleDerivationOk(SchemaGrammar* const currentGrammar, + ContentSpecNode* const curNode, + const int derivedScope, + ContentSpecNode* const baseNode, + const int baseScope, + const ComplexTypeInfo* const baseInfo = 0); + ContentSpecNode* checkForPointlessOccurrences(ContentSpecNode* const specNode, + const ContentSpecNode::NodeTypes nodeType, + ValueVectorOf<ContentSpecNode*>* const nodes); + void gatherChildren(const ContentSpecNode::NodeTypes parentNodeType, + ContentSpecNode* const specNode, + ValueVectorOf<ContentSpecNode*>* const nodes); + bool isOccurrenceRangeOK(const int min1, const int max1, const int min2, const int max2); + void checkNSCompat(const ContentSpecNode* const derivedSpecNode, + const ContentSpecNode* const baseSpecNode); + bool wildcardEltAllowsNamespace(const ContentSpecNode* const baseSpecNode, + const unsigned int derivedURI); + void checkNameAndTypeOK(SchemaGrammar* const currentGrammar, + const ContentSpecNode* const derivedSpecNode, + const int derivedScope, + const ContentSpecNode* const baseSpecNode, + const int baseScope, + const ComplexTypeInfo* const baseInfo = 0); + SchemaElementDecl* findElement(const int scope, + const unsigned int uriIndex, + const XMLCh* const name, + SchemaGrammar* const grammar, + const ComplexTypeInfo* const typeInfo = 0); + void checkICRestriction(const SchemaElementDecl* const derivedElemDecl, + const SchemaElementDecl* const baseElemDecl, + const XMLCh* const derivedElemName, + const XMLCh* const baseElemName); + void checkTypesOK(const SchemaElementDecl* const derivedElemDecl, + const SchemaElementDecl* const baseElemDecl, + const XMLCh* const derivedElemName); + void checkRecurseAsIfGroup(SchemaGrammar* const currentGrammar, + ContentSpecNode* const derivedSpecNode, + const int derivedScope, + const ContentSpecNode* const baseSpecNode, + const int baseScope, + ValueVectorOf<ContentSpecNode*>* const nodes, + const ComplexTypeInfo* const baseInfo); + void checkRecurse(SchemaGrammar* const currentGrammar, + const ContentSpecNode* const derivedSpecNode, + const int derivedScope, + ValueVectorOf<ContentSpecNode*>* const derivedNodes, + const ContentSpecNode* const baseSpecNode, + const int baseScope, + ValueVectorOf<ContentSpecNode*>* const baseNodes, + const ComplexTypeInfo* const baseInfo, + const bool toLax = false); + void checkNSSubset(const ContentSpecNode* const derivedSpecNode, + const ContentSpecNode* const baseSpecNode); + bool isWildCardEltSubset(const ContentSpecNode* const derivedSpecNode, + const ContentSpecNode* const baseSpecNode); + void checkNSRecurseCheckCardinality(SchemaGrammar* const currentGrammar, + const ContentSpecNode* const derivedSpecNode, + ValueVectorOf<ContentSpecNode*>* const derivedNodes, + const int derivedScope, + ContentSpecNode* const baseSpecNode); + void checkRecurseUnordered(SchemaGrammar* const currentGrammar, + const ContentSpecNode* const derivedSpecNode, + ValueVectorOf<ContentSpecNode*>* const derivedNodes, + const int derivedScope, + ContentSpecNode* const baseSpecNode, + ValueVectorOf<ContentSpecNode*>* const baseNodes, + const int baseScope, + const ComplexTypeInfo* const baseInfo); + void checkMapAndSum(SchemaGrammar* const currentGrammar, + const ContentSpecNode* const derivedSpecNode, + ValueVectorOf<ContentSpecNode*>* const derivedNodes, + const int derivedScope, + ContentSpecNode* const baseSpecNode, + ValueVectorOf<ContentSpecNode*>* const baseNodes, + const int baseScope, + const ComplexTypeInfo* const baseInfo); + + void setErrorHandler(ErrorHandler* const handler); + void setExitOnFirstFatal(const bool newValue); + private: // ----------------------------------------------------------------------- // Private data members @@ -205,6 +295,9 @@ private: // // fTrailing // Previous chunk had a trailing space + // + // fSchemaErrorReporter + // Report schema process errors // ----------------------------------------------------------------------- SchemaGrammar* fSchemaGrammar; GrammarResolver* fGrammarResolver; @@ -215,6 +308,7 @@ private: XMLBuffer fDatatypeBuffer; bool fTrailing; + XSDErrorReporter fSchemaErrorReporter; }; @@ -265,4 +359,29 @@ inline bool SchemaValidator::handlesSchema() const return true; } +// --------------------------------------------------------------------------- +// SchemaValidator: Particle derivation checking +// --------------------------------------------------------------------------- +inline bool +SchemaValidator::isOccurrenceRangeOK(const int min1, const int max1, + const int min2, const int max2) { + + if (min1 >= min2 && + (max2 == SchemaSymbols::UNBOUNDED || + (max1 != SchemaSymbols::UNBOUNDED && max1 <= max2))) { + return true; + } + return false; +} + +inline void SchemaValidator::setErrorHandler(ErrorHandler* const handler) { + + fSchemaErrorReporter.setErrorHandler(handler); +} + +inline void SchemaValidator::setExitOnFirstFatal(const bool newValue) { + + fSchemaErrorReporter.setExitOnFirstFatal(newValue); +} + #endif diff --git a/src/xercesc/validators/schema/TraverseSchema.cpp b/src/xercesc/validators/schema/TraverseSchema.cpp index c35a7ac1d9fa4937502da3a0c3118d79a374581e..bfd3212f770d305584c706a3ceb07c68e3a728be 100644 --- a/src/xercesc/validators/schema/TraverseSchema.cpp +++ b/src/xercesc/validators/schema/TraverseSchema.cpp @@ -179,15 +179,15 @@ const XMLCh* fgIdentityConstraints[] = // --------------------------------------------------------------------------- // TraverseSchema: Constructors and Destructor // --------------------------------------------------------------------------- -TraverseSchema::TraverseSchema( IDOM_Element* const schemaRoot - , XMLStringPool* const uriStringPool - , SchemaGrammar* const schemaGrammar - , GrammarResolver* const grammarResolver - , XMLScanner* const xmlScanner - , XMLValidator* const xmlValidator - , const XMLCh* const schemaURL - , EntityResolver* const entityResolver - , ErrorHandler* const errorHandler) +TraverseSchema::TraverseSchema( IDOM_Element* const schemaRoot + , XMLStringPool* const uriStringPool + , SchemaGrammar* const schemaGrammar + , GrammarResolver* const grammarResolver + , XMLScanner* const xmlScanner + , XMLValidator* const xmlValidator + , const XMLCh* const schemaURL + , EntityResolver* const entityResolver + , ErrorHandler* const errorHandler) : fFullConstraintChecking(false) , fTargetNSURI(-1) , fEmptyNamespaceURI(-1) @@ -299,7 +299,6 @@ void TraverseSchema::doTraverseSchema(const IDOM_Element* const schemaRoot) { // Element consistency checks - substitution groups if (fFullConstraintChecking) { checkRefElementConsistency(); - checkParticleDerivation(); } } @@ -1445,18 +1444,22 @@ TraverseSchema::traverseGroupDecl(const IDOM_Element* const elem, fCurrentGroupInfo = saveGroupInfo; fCurrentScope = saveScope; - if (fRedefineComponents && fRedefineComponents->get(SchemaSymbols::fgELT_GROUP, nameIndex)) { + if (fFullConstraintChecking && fRedefineComponents && + fRedefineComponents->get(SchemaSymbols::fgELT_GROUP, nameIndex)) { fBuffer.set(fullName); fBuffer.append(SchemaSymbols::fgRedefIdentifier); XercesGroupInfo* baseGroupInfo = fGroupRegistry->get(fBuffer.getRawBuffer()); - try { - checkParticleDerivationOk(groupInfo->getContentSpec(), groupInfo->getScope(), - baseGroupInfo->getContentSpec(), baseGroupInfo->getScope()); - } - catch (const XMLException& excep) { - reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DisplayErrorMessage, excep.getMessage()); + if (baseGroupInfo) { + + XSDLocator* aLocator = new XSDLocator(); + aLocator->setValues(fStringPool->getValueForId(fStringPool->addOrFind(fSchemaInfo->getCurrentSchemaURL())), + 0, ((XSDElementNSImpl*) elem)->getLineNo(), + ((XSDElementNSImpl*) elem)->getColumnNo()); + + groupInfo->setBaseGroup(baseGroupInfo); + groupInfo->setLocator(aLocator); } } @@ -4533,6 +4536,7 @@ QName* TraverseSchema::processElementDeclRef(const IDOM_Element* const elem, return eltName; } else { + // restore schema information fSchemaInfo = saveInfo; } @@ -6732,9 +6736,7 @@ void TraverseSchema::copyGroupElements(const IDOM_Element* const elem, } } else { - if (!toGroup->containsElement(elemDecl)) { - toGroup->addElement(elemDecl); - } + toGroup->addElement(elemDecl); } } } @@ -7746,808 +7748,6 @@ void TraverseSchema::fixRedefinedSchema(const IDOM_Element* const elem, } } -void TraverseSchema::checkParticleDerivation() { - - RefHashTableOfEnumerator<ComplexTypeInfo> complexTypeEnum(fComplexTypeRegistry); - - while (complexTypeEnum.hasMoreElements()) { - - ComplexTypeInfo& curTypeInfo = complexTypeEnum.nextElement(); - ComplexTypeInfo* baseTypeInfo = 0; - ContentSpecNode* curSpecNode = 0; - - if (curTypeInfo.getDerivedBy() == SchemaSymbols::RESTRICTION - && ((baseTypeInfo = curTypeInfo.getBaseComplexTypeInfo()) != 0) - && ((curSpecNode = curTypeInfo.getContentSpec()) != 0)) { - - try { - checkParticleDerivationOk(curSpecNode, curTypeInfo.getScopeDefined(), - baseTypeInfo->getContentSpec(), - baseTypeInfo->getScopeDefined(), baseTypeInfo); - } - catch (const XMLException& excep) { - reportSchemaError(curTypeInfo.getLocator(), XMLUni::fgXMLErrDomain, XMLErrs::DisplayErrorMessage, excep.getMessage()); - } - } - } -} - -void TraverseSchema::checkParticleDerivationOk(ContentSpecNode* const curNode, - const int derivedScope, - ContentSpecNode* const baseNode, - const int baseScope, - const ComplexTypeInfo* const baseInfo) { - - // Check for pointless occurrences of all, choice, sequence. The result is - // the contentspec which is not pointless. If the result is a non-pointless - // group, Vector is filled in with the children of interest - if (!curNode || !baseNode) - return; - - ContentSpecNode* curSpecNode = curNode; - ContentSpecNode* baseSpecNode = baseNode; - ValueVectorOf<ContentSpecNode*> curVector(8); - ValueVectorOf<ContentSpecNode*> baseVector(8); - ContentSpecNode::NodeTypes curNodeType = curSpecNode->getType(); - ContentSpecNode::NodeTypes baseNodeType = baseSpecNode->getType(); - - if (curNodeType == ContentSpecNode::Sequence || - curNodeType == ContentSpecNode::Choice || - curNodeType == ContentSpecNode::All) { - curSpecNode = checkForPointlessOccurrences(curSpecNode, curNodeType, &curVector); - } - - if (baseNodeType == ContentSpecNode::Sequence || - baseNodeType == ContentSpecNode::Choice || - baseNodeType == ContentSpecNode::All) { - baseSpecNode = checkForPointlessOccurrences(baseSpecNode, baseNodeType, &baseVector); - } - - curNodeType = curSpecNode->getType(); - baseNodeType = baseSpecNode->getType(); - - switch (curNodeType & 0x0f) { - case ContentSpecNode::Leaf: - { - switch (baseNodeType & 0x0f) { - case ContentSpecNode::Leaf: - { - checkNameAndTypeOK(curSpecNode, derivedScope, baseSpecNode, baseScope, baseInfo); - return; - } - case ContentSpecNode::Any: - case ContentSpecNode::Any_Other: - case ContentSpecNode::Any_NS: - { - checkNSCompat(curSpecNode, baseSpecNode); - return; - } - case ContentSpecNode::Choice: - case ContentSpecNode::Sequence: - case ContentSpecNode::All: - { - checkRecurseAsIfGroup(curSpecNode, derivedScope, baseSpecNode, baseScope, &baseVector, baseInfo); - return; - } - default: - { - ThrowXML(RuntimeException, XMLExcepts::PD_InvalidContentType); - } - } - } - case ContentSpecNode::Any: - case ContentSpecNode::Any_Other: - case ContentSpecNode::Any_NS: - { - switch (baseNodeType & 0x0f) { - case ContentSpecNode::Any: - case ContentSpecNode::Any_Other: - case ContentSpecNode::Any_NS: - { - checkNSSubset(curSpecNode, baseSpecNode); - return; - } - case ContentSpecNode::Choice: - case ContentSpecNode::Sequence: - case ContentSpecNode::All: - case ContentSpecNode::Leaf: - { - ThrowXML(RuntimeException, XMLExcepts::PD_ForbiddenRes1); - } - default: - { - ThrowXML(RuntimeException, XMLExcepts::PD_InvalidContentType); - } - } - } - case ContentSpecNode::All: - { - switch (baseNodeType & 0x0f) { - case ContentSpecNode::Any: - case ContentSpecNode::Any_Other: - case ContentSpecNode::Any_NS: - { - checkNSRecurseCheckCardinality(curSpecNode, &curVector, derivedScope, baseSpecNode); - return; - } - case ContentSpecNode::All: - { - checkRecurse(curSpecNode, derivedScope, &curVector, baseSpecNode, baseScope, &baseVector, baseInfo); - return; - } - case ContentSpecNode::Choice: - case ContentSpecNode::Sequence: - case ContentSpecNode::Leaf: - { - ThrowXML(RuntimeException, XMLExcepts::PD_ForbiddenRes2); - } - default: - { - ThrowXML(RuntimeException, XMLExcepts::PD_InvalidContentType); - } - } - } - case ContentSpecNode::Choice: - { - switch (baseNodeType & 0x0f) { - case ContentSpecNode::Any: - case ContentSpecNode::Any_Other: - case ContentSpecNode::Any_NS: - { - checkNSRecurseCheckCardinality(curSpecNode, &curVector, derivedScope, baseSpecNode); - return; - } - case ContentSpecNode::Choice: - { - checkRecurse(curSpecNode, derivedScope, &curVector, baseSpecNode, baseScope, &baseVector, baseInfo, true); - return; - } - case ContentSpecNode::All: - case ContentSpecNode::Sequence: - case ContentSpecNode::Leaf: - { - ThrowXML(RuntimeException, XMLExcepts::PD_ForbiddenRes3); - } - default: - { - ThrowXML(RuntimeException, XMLExcepts::PD_InvalidContentType); - } - } - } - case ContentSpecNode::Sequence: - { - switch (baseNodeType & 0x0f) { - case ContentSpecNode::Any: - case ContentSpecNode::Any_Other: - case ContentSpecNode::Any_NS: - { - checkNSRecurseCheckCardinality(curSpecNode, &curVector, derivedScope, baseSpecNode); - return; - } - case ContentSpecNode::All: - { - checkRecurseUnordered(curSpecNode, &curVector, derivedScope, baseSpecNode, &baseVector, baseScope, baseInfo); - return; - } - case ContentSpecNode::Sequence: - { - checkRecurse(curSpecNode, derivedScope, &curVector, baseSpecNode, baseScope, &baseVector, baseInfo); - return; - } - case ContentSpecNode::Choice: - { - checkMapAndSum(curSpecNode, &curVector, derivedScope, baseSpecNode, &baseVector, baseScope, baseInfo); - return; - } - case ContentSpecNode::Leaf: - { - ThrowXML(RuntimeException, XMLExcepts::PD_ForbiddenRes4); - } - default: - { - ThrowXML(RuntimeException, XMLExcepts::PD_InvalidContentType); - } - } - } - } -} - -ContentSpecNode* -TraverseSchema::checkForPointlessOccurrences(ContentSpecNode* const specNode, - const ContentSpecNode::NodeTypes nodeType, - ValueVectorOf<ContentSpecNode*>* const nodes) { - - ContentSpecNode* rightNode = specNode->getSecond(); - int min = specNode->getMinOccurs(); - int max = specNode->getMaxOccurs(); - - if (!rightNode) { - - gatherChildren(nodeType, specNode->getFirst(), nodes); - - if (nodes->size() == 1 && min == 1 && max == 1) { - return nodes->elementAt(0); - } - - return specNode; - } - - gatherChildren(nodeType, specNode->getFirst(), nodes); - gatherChildren(nodeType, rightNode, nodes); - - return specNode; -} - -void TraverseSchema::gatherChildren(const ContentSpecNode::NodeTypes parentNodeType, - ContentSpecNode* const specNode, - ValueVectorOf<ContentSpecNode*>* const nodes) { - - if (!specNode) { - return; - } - - int min = specNode->getMinOccurs(); - int max = specNode->getMaxOccurs(); - ContentSpecNode::NodeTypes nodeType = specNode->getType(); - ContentSpecNode* rightNode = specNode->getSecond(); - - if (nodeType == ContentSpecNode::Leaf || - (nodeType & 0x0f) == ContentSpecNode::Any || - (nodeType & 0x0f) == ContentSpecNode::Any_NS || - (nodeType & 0x0f) == ContentSpecNode::Any_Other) { - nodes->addElement(specNode); - } - else if (min !=1 || max != 1) { - nodes->addElement(specNode); - } - else if (!rightNode) { - gatherChildren(nodeType, specNode->getFirst(), nodes); - } - else if (parentNodeType == nodeType) { - - gatherChildren(nodeType, specNode->getFirst(), nodes); - gatherChildren(nodeType, rightNode, nodes); - } - else { - nodes->addElement(specNode); - } -} - -void -TraverseSchema::checkNSCompat(const ContentSpecNode* const derivedSpecNode, - const ContentSpecNode* const baseSpecNode) { - - // check Occurrence ranges - if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(), - baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) { - ThrowXML1(RuntimeException, XMLExcepts::PD_OccurRangeE, - derivedSpecNode->getElement()->getLocalPart()); - } - - // check wildcard subset - if (!wildcardEltAllowsNamespace(baseSpecNode, derivedSpecNode->getElement()->getURI())) { - ThrowXML1(RuntimeException, XMLExcepts::PD_NSCompat1, - derivedSpecNode->getElement()->getLocalPart()); - } -} - -bool -TraverseSchema::wildcardEltAllowsNamespace(const ContentSpecNode* const baseSpecNode, - const unsigned int derivedURI) { - - ContentSpecNode::NodeTypes nodeType = baseSpecNode->getType(); - - if ((nodeType & 0x0f) == ContentSpecNode::Any) { - return true; - } - - unsigned int baseURI = baseSpecNode->getElement()->getURI(); - - if ((nodeType & 0x0f) == ContentSpecNode::Any_NS) { - if (derivedURI == baseURI) { - return true; - } - } - else { // must be ANY_OTHER - if (derivedURI != baseURI && derivedURI != (unsigned int) fEmptyNamespaceURI) { - return true; - } - } - - return false; -} - -void -TraverseSchema::checkNameAndTypeOK(const ContentSpecNode* const derivedSpecNode, - const int derivedScope, - const ContentSpecNode* const baseSpecNode, - const int baseScope, - const ComplexTypeInfo* const baseInfo) { - - unsigned int derivedURI = derivedSpecNode->getElement()->getURI(); - unsigned int baseURI = baseSpecNode->getElement()->getURI(); - const XMLCh* derivedName = derivedSpecNode->getElement()->getLocalPart(); - const XMLCh* baseName = baseSpecNode->getElement()->getLocalPart(); - - if (XMLString::compareString(derivedName, baseName) || derivedURI != baseURI) { - ThrowXML(RuntimeException, XMLExcepts::PD_NameTypeOK1); - } - - // case of mixed complex types with attributes only - if (derivedURI == XMLElementDecl::fgPCDataElemId) { - return; - } - - if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(), - baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) { - ThrowXML1(RuntimeException, XMLExcepts::PD_OccurRangeE, derivedName); - } - - SchemaGrammar* aGrammar = fSchemaGrammar; - const XMLCh* schemaURI = fURIStringPool->getValueForId(derivedURI); - - if ((derivedURI != (unsigned int) fTargetNSURI) && - (derivedURI != (unsigned int) fEmptyNamespaceURI)) { - aGrammar= (SchemaGrammar*) fGrammarResolver->getGrammar(schemaURI); - } - - if (!aGrammar) { //something is wrong - return; - } - - SchemaElementDecl* derivedElemDecl = findElement(derivedScope, derivedURI, derivedName, aGrammar); - - if (!derivedElemDecl) { - return; - } - - SchemaElementDecl* baseElemDecl = - findElement(baseScope, baseURI, baseName, aGrammar, baseInfo); - - if (!baseElemDecl) { - return; - } - - int derivedFlags = derivedElemDecl->getMiscFlags(); - int baseFlags = baseElemDecl->getMiscFlags(); - - if (((baseFlags & SchemaSymbols::NILLABLE) == 0) && - ((derivedFlags & SchemaSymbols::NILLABLE) != 0)) { - ThrowXML1(RuntimeException, XMLExcepts::PD_NameTypeOK2, derivedName); - } - - const XMLCh* derivedDefVal = derivedElemDecl->getDefaultValue(); - const XMLCh* baseDefVal = baseElemDecl->getDefaultValue(); - - if (baseDefVal && (baseFlags & SchemaSymbols::FIXED) != 0 && - ((derivedFlags & SchemaSymbols::FIXED) == 0 || - XMLString::compareString(derivedDefVal, baseDefVal))) { - ThrowXML1(RuntimeException, XMLExcepts::PD_NameTypeOK3, derivedName); - } - - int derivedBlockSet = derivedElemDecl->getBlockSet(); - int baseBlockSet = baseElemDecl->getBlockSet(); - - if ((derivedBlockSet & baseBlockSet) != baseBlockSet) { - ThrowXML1(RuntimeException, XMLExcepts::PD_NameTypeOK4, derivedName); - } - - // check identity constraints - checkICRestriction(derivedElemDecl, baseElemDecl, derivedName, baseName); - - // check that the derived element's type is derived from the base's. - checkTypesOK(derivedElemDecl, baseElemDecl, derivedName); - -} - -SchemaElementDecl* -TraverseSchema::findElement(const int scope, const unsigned int uriIndex, - const XMLCh* const name, - SchemaGrammar* const grammar, - const ComplexTypeInfo* const typeInfo) { - - // check for element at given scope first - SchemaElementDecl* elemDecl = (SchemaElementDecl*) grammar->getElemDecl(uriIndex, name, 0, scope); - - // if not found, check at global scope - if (!elemDecl) { - - elemDecl = (SchemaElementDecl*) - grammar->getElemDecl(uriIndex, name, 0, Grammar::TOP_LEVEL_SCOPE); - - // if still not found, and base is specified, look it up there - if (!elemDecl && typeInfo) { - - const ComplexTypeInfo* baseInfo = typeInfo; - - while (baseInfo) { - - elemDecl = (SchemaElementDecl*) - grammar->getElemDecl(uriIndex, name, 0, baseInfo->getScopeDefined()); - - if (elemDecl) { - break; - } - - baseInfo = baseInfo->getBaseComplexTypeInfo(); - } - } - } - - return elemDecl; -} - -void -TraverseSchema::checkICRestriction(const SchemaElementDecl* const derivedElemDecl, - const SchemaElementDecl* const baseElemDecl, - const XMLCh* const derivedElemName, - const XMLCh* const baseElemName) { - - // REVIST - need to get more clarification - unsigned int derivedICCount = derivedElemDecl->getIdentityConstraintCount(); - unsigned int baseICCount = baseElemDecl->getIdentityConstraintCount(); - - if (derivedICCount > baseICCount) { - ThrowXML2(RuntimeException, XMLExcepts::PD_NameTypeOK6, derivedElemName, baseElemName); - } - - for (unsigned int i=0; i < derivedICCount; i++) { - - bool found = false; - IdentityConstraint* ic= derivedElemDecl->getIdentityConstraintAt(i); - - for (unsigned int j=0; j < baseICCount; j++) { - if (*ic == *(baseElemDecl->getIdentityConstraintAt(j))) { - - found = true; - break; - } - } - - if (!found) { - ThrowXML2(RuntimeException, XMLExcepts::PD_NameTypeOK7, derivedElemName, baseElemName); - } - } -} - -void -TraverseSchema::checkTypesOK(const SchemaElementDecl* const derivedElemDecl, - const SchemaElementDecl* const baseElemDecl, - const XMLCh* const derivedElemName) { - - SchemaElementDecl::ModelTypes baseType = baseElemDecl->getModelType(); - - if (baseType == SchemaElementDecl::Any) { - return; - } - - ComplexTypeInfo* rInfo = derivedElemDecl->getComplexTypeInfo(); - ComplexTypeInfo* bInfo = baseElemDecl->getComplexTypeInfo(); - - if (derivedElemDecl->getModelType() == SchemaElementDecl::Simple) { - - if (baseType != SchemaElementDecl::Simple) { - ThrowXML1(RuntimeException, XMLExcepts::PD_NameTypeOK5, derivedElemName); - } - - if (!rInfo) { - - DatatypeValidator* bDV = baseElemDecl->getDatatypeValidator(); - - if (bInfo || bDV == 0 || - !bDV->isSubstitutableBy(derivedElemDecl->getDatatypeValidator())) { - ThrowXML1(RuntimeException, XMLExcepts::PD_NameTypeOK5, derivedElemName); - } - - return; - } - } - - if (rInfo == bInfo) - return; - - for (; rInfo && rInfo != bInfo; rInfo = rInfo->getBaseComplexTypeInfo()) { - if (rInfo->getDerivedBy() != SchemaSymbols::RESTRICTION) { - - rInfo = 0; - break; - } - } - - if (!rInfo) { - ThrowXML1(RuntimeException, XMLExcepts::PD_NameTypeOK5, derivedElemName); - } -} - -void -TraverseSchema::checkRecurseAsIfGroup(ContentSpecNode* const derivedSpecNode, - const int derivedScope, - const ContentSpecNode* const baseSpecNode, - const int baseScope, - ValueVectorOf<ContentSpecNode*>* const baseNodes, - const ComplexTypeInfo* const baseInfo) { - - ContentSpecNode::NodeTypes baseType = baseSpecNode->getType(); - ValueVectorOf<ContentSpecNode*> derivedNodes(1); - bool toLax = false; - - //Treat the element as if it were in a group of the same variety as base - ContentSpecNode derivedGroupNode(baseType, derivedSpecNode, 0, false); - - derivedNodes.addElement(derivedSpecNode); - - if (baseSpecNode->getType() == ContentSpecNode::Choice) { - toLax = true; - } - - checkRecurse(&derivedGroupNode, derivedScope, &derivedNodes, - baseSpecNode, baseScope, baseNodes, baseInfo, toLax); -} - -void -TraverseSchema::checkRecurse(const ContentSpecNode* const derivedSpecNode, - const int derivedScope, - ValueVectorOf<ContentSpecNode*>* const derivedNodes, - const ContentSpecNode* const baseSpecNode, - const int baseScope, - ValueVectorOf<ContentSpecNode*>* const baseNodes, - const ComplexTypeInfo* const baseInfo, - const bool toLax) { - - if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(), - baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) { - ThrowXML(RuntimeException, XMLExcepts::PD_Recurse1); - } - - // check for mapping of children - XMLExcepts::Codes codeToThrow = XMLExcepts::NoError; - unsigned int count1= derivedNodes->size(); - unsigned int count2= baseNodes->size(); - unsigned int current = 0; - - for (unsigned int i=0; i<count1; i++) { - - bool matched = false; - - for (unsigned int j = current; j < count2; j++) { - - ContentSpecNode* baseNode = baseNodes->elementAt(j); - current++; - - try { - - checkParticleDerivationOk(derivedNodes->elementAt(i), derivedScope, baseNode, baseScope, baseInfo); - matched = true; - break; - } - catch(const XMLException&) { - if (!toLax && !emptiableParticle(baseNode)) { - break; - } - } - } - - // did not find a match - if (!matched) { - - codeToThrow = XMLExcepts::PD_Recurse2; - break; - } - } - - // Now, see if there are some elements in the base we didn't match up - // in case of Sequence or All - if (!toLax && codeToThrow == XMLExcepts::NoError) { - for (unsigned int j = current; j < count2; j++) { - if (!emptiableParticle(baseNodes->elementAt(j))) { - - codeToThrow = XMLExcepts::PD_Recurse2; - break; - } - } - } - - if (codeToThrow != XMLExcepts::NoError) { - ThrowXML(RuntimeException, codeToThrow); - } -} - -void TraverseSchema::checkNSSubset(const ContentSpecNode* const derivedSpecNode, - const ContentSpecNode* const baseSpecNode) { - - // check Occurrence ranges - if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(), - baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) { - ThrowXML(RuntimeException, XMLExcepts::PD_NSSubset1); - } - - if (!isWildCardEltSubset(derivedSpecNode, baseSpecNode)) { - ThrowXML(RuntimeException, XMLExcepts::PD_NSSubset2); - } -} - -bool -TraverseSchema::isWildCardEltSubset(const ContentSpecNode* const derivedSpecNode, - const ContentSpecNode* const baseSpecNode) { - - ContentSpecNode::NodeTypes baseType = baseSpecNode->getType(); - - if ((baseType & 0x0f) == ContentSpecNode::Any) { - return true; - } - - ContentSpecNode::NodeTypes derivedType = derivedSpecNode->getType(); - unsigned int baseURI = baseSpecNode->getElement()->getURI(); - unsigned int derivedURI = derivedSpecNode->getElement()->getURI(); - - if (((derivedType & 0x0f) == ContentSpecNode::Any_Other) && - ((baseType & 0x0f) == ContentSpecNode::Any_Other) && - baseURI == derivedURI) { - return true; - } - - if ((derivedType & 0x0f) == ContentSpecNode::Any_NS) { - - if (((baseType & 0x0f) == ContentSpecNode::Any_NS) && - baseURI == derivedURI) { - return true; - } - - if (((baseType & 0x0f) == ContentSpecNode::Any_Other) && - baseURI != derivedURI) { - return true; - } - } - - return false; -} - -void -TraverseSchema::checkNSRecurseCheckCardinality(const ContentSpecNode* const derivedSpecNode, - ValueVectorOf<ContentSpecNode*>* const derivedNodes, - const int derivedScope, - ContentSpecNode* const baseSpecNode) { - - // Implement total range check - int derivedMin = derivedSpecNode->getMinTotalRange(); - int derivedMax = derivedSpecNode->getMaxTotalRange(); - - // check Occurrence ranges - if (!isOccurrenceRangeOK(derivedMin, derivedMax, baseSpecNode->getMinOccurs(), - baseSpecNode->getMaxOccurs())) { - ThrowXML(RuntimeException, XMLExcepts::PD_NSRecurseCheckCardinality1); - } - - // Check that each member of the group is a valid restriction of the wildcard - unsigned int nodesCount = derivedNodes->size(); - - for (unsigned int i = 0; i < nodesCount; i++) { - checkParticleDerivationOk(derivedNodes->elementAt(i), derivedScope, baseSpecNode, -1); - } -} - -void -TraverseSchema::checkRecurseUnordered(const ContentSpecNode* const derivedSpecNode, - ValueVectorOf<ContentSpecNode*>* const derivedNodes, - const int derivedScope, - ContentSpecNode* const baseSpecNode, - ValueVectorOf<ContentSpecNode*>* const baseNodes, - const int baseScope, - const ComplexTypeInfo* const baseInfo) { - - // check Occurrence ranges - if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(), - baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) { - ThrowXML(RuntimeException, XMLExcepts::PD_Recurse1); - } - - XMLExcepts::Codes codeToThrow = XMLExcepts::NoError; - unsigned int derivedCount= derivedNodes->size(); - unsigned int baseCount = baseNodes->size(); - bool* foundIt = new bool[baseCount]; - ArrayJanitor<bool> janFoundIt(foundIt); - - for (unsigned k=0; k < baseCount; k++) { - foundIt[k] = false; - } - - // check for mapping of children - for (unsigned int i = 0; i < derivedCount; i++) { - - ContentSpecNode* derivedNode = derivedNodes->elementAt(i); - bool matched = false; - - for (unsigned int j = 0; j < baseCount; j++) { - - try { - - checkParticleDerivationOk(derivedNode, derivedScope, baseNodes->elementAt(j), baseScope, baseInfo); - - if (foundIt[j]) { - break; - } - - foundIt[j] = true; - matched = true; - break; - } - catch (const XMLException&) { - } - } - - // didn't find a match. - if (!matched) { - - codeToThrow = XMLExcepts::PD_RecurseUnordered; - break; - } - } - - // For all unmapped particles in base, check to see it it's emptiable or not - if (codeToThrow == XMLExcepts::NoError) { - for (unsigned int j=0; j < baseCount; j++) { - if (!foundIt[j] && !emptiableParticle(baseNodes->elementAt(j))) { - - codeToThrow = XMLExcepts::PD_RecurseUnordered; - break; - } - } - } - - if (codeToThrow != XMLExcepts::NoError) { - ThrowXML(RuntimeException, codeToThrow); - } -} - -void -TraverseSchema::checkMapAndSum(const ContentSpecNode* const derivedSpecNode, - ValueVectorOf<ContentSpecNode*>* const derivedNodes, - const int derivedScope, - ContentSpecNode* const baseSpecNode, - ValueVectorOf<ContentSpecNode*>* const baseNodes, - const int baseScope, - const ComplexTypeInfo* const baseInfo) { - - // check Occurrence ranges - int derivedCount = derivedNodes->size(); - int baseCount = baseNodes->size(); - int derivedMin = derivedSpecNode->getMinOccurs() * derivedCount; - int derivedMax = derivedSpecNode->getMaxOccurs(); - - if (derivedMax != SchemaSymbols::UNBOUNDED) { - derivedMax *= derivedCount; - } - - if (!isOccurrenceRangeOK(derivedMin, derivedMax, baseSpecNode->getMinOccurs(), - baseSpecNode->getMaxOccurs())) { - ThrowXML(RuntimeException, XMLExcepts::PD_Recurse1); - } - - // check for mapping of children - for (int i = 0; i < derivedCount; i++) { - - ContentSpecNode* derivedNode = derivedNodes->elementAt(i); - bool matched = false; - - for (int j = 0; j < baseCount && !matched; j++) { - - try { - - checkParticleDerivationOk(derivedNode, derivedScope, baseNodes->elementAt(j), baseScope, baseInfo); - matched = true; - } - catch (const XMLException&) { - } - } - - // didn't find a match. - if (!matched) { - ThrowXML(RuntimeException, XMLExcepts::PD_MapAndSum); - } - } - -} - // --------------------------------------------------------------------------- // TraverseSchema: Error reporting methods // --------------------------------------------------------------------------- diff --git a/src/xercesc/validators/schema/TraverseSchema.hpp b/src/xercesc/validators/schema/TraverseSchema.hpp index b0ffa99f0308b7755459dbebda293f548d130323..cb4b9a50479e18a9689ea27077e928d9f617312c 100644 --- a/src/xercesc/validators/schema/TraverseSchema.hpp +++ b/src/xercesc/validators/schema/TraverseSchema.hpp @@ -95,7 +95,6 @@ class DatatypeValidatorFactory; class QName; class ComplexTypeInfo; class XMLAttDef; -class ContentSpecNode; class NamespaceScope; class SchemaAttDef; class InputSource; @@ -704,80 +703,6 @@ private: void processKeyRefFor(SchemaInfo* const aSchemaInfo, ValueVectorOf<SchemaInfo*>* const infoList); - // ----------------------------------------------------------------------- - // Particle Derivation Checking methods - // ----------------------------------------------------------------------- - void checkParticleDerivation(); - void checkParticleDerivationOk(ContentSpecNode* const curNode, - const int derivedScope, - ContentSpecNode* const baseNode, - const int baseScope, - const ComplexTypeInfo* const baseInfo = 0); - ContentSpecNode* checkForPointlessOccurrences(ContentSpecNode* const specNode, - const ContentSpecNode::NodeTypes nodeType, - ValueVectorOf<ContentSpecNode*>* const nodes); - void gatherChildren(const ContentSpecNode::NodeTypes parentNodeType, - ContentSpecNode* const specNode, - ValueVectorOf<ContentSpecNode*>* const nodes); - bool isOccurrenceRangeOK(const int min1, const int max1, const int min2, const int max2); - void checkNSCompat(const ContentSpecNode* const derivedSpecNode, - const ContentSpecNode* const baseSpecNode); - bool wildcardEltAllowsNamespace(const ContentSpecNode* const baseSpecNode, - const unsigned int derivedURI); - void checkNameAndTypeOK(const ContentSpecNode* const derivedSpecNode, - const int derivedScope, - const ContentSpecNode* const baseSpecNode, - const int baseScope, - const ComplexTypeInfo* const baseInfo = 0); - SchemaElementDecl* findElement(const int scope, - const unsigned int uriIndex, - const XMLCh* const name, - SchemaGrammar* const grammar, - const ComplexTypeInfo* const typeInfo = 0); - void checkICRestriction(const SchemaElementDecl* const derivedElemDecl, - const SchemaElementDecl* const baseElemDecl, - const XMLCh* const derivedElemName, - const XMLCh* const baseElemName); - void checkTypesOK(const SchemaElementDecl* const derivedElemDecl, - const SchemaElementDecl* const baseElemDecl, - const XMLCh* const derivedElemName); - void checkRecurseAsIfGroup(ContentSpecNode* const derivedSpecNode, - const int derivedScope, - const ContentSpecNode* const baseSpecNode, - const int baseScope, - ValueVectorOf<ContentSpecNode*>* const nodes, - const ComplexTypeInfo* const baseInfo); - void checkRecurse(const ContentSpecNode* const derivedSpecNode, - const int derivedScope, - ValueVectorOf<ContentSpecNode*>* const derivedNodes, - const ContentSpecNode* const baseSpecNode, - const int baseScope, - ValueVectorOf<ContentSpecNode*>* const baseNodes, - const ComplexTypeInfo* const baseInfo, - const bool toLax = false); - void checkNSSubset(const ContentSpecNode* const derivedSpecNode, - const ContentSpecNode* const baseSpecNode); - bool isWildCardEltSubset(const ContentSpecNode* const derivedSpecNode, - const ContentSpecNode* const baseSpecNode); - void checkNSRecurseCheckCardinality(const ContentSpecNode* const derivedSpecNode, - ValueVectorOf<ContentSpecNode*>* const derivedNodes, - const int derivedScope, - ContentSpecNode* const baseSpecNode); - void checkRecurseUnordered(const ContentSpecNode* const derivedSpecNode, - ValueVectorOf<ContentSpecNode*>* const derivedNodes, - const int derivedScope, - ContentSpecNode* const baseSpecNode, - ValueVectorOf<ContentSpecNode*>* const baseNodes, - const int baseScope, - const ComplexTypeInfo* const baseInfo); - void checkMapAndSum(const ContentSpecNode* const derivedSpecNode, - ValueVectorOf<ContentSpecNode*>* const derivedNodes, - const int derivedScope, - ContentSpecNode* const baseSpecNode, - ValueVectorOf<ContentSpecNode*>* const baseNodes, - const int baseScope, - const ComplexTypeInfo* const baseInfo); - // ----------------------------------------------------------------------- // Private constants // ----------------------------------------------------------------------- @@ -1018,18 +943,6 @@ inline void TraverseSchema::getRedefineNewTypeName(const XMLCh* const oldTypeNam } } -inline bool -TraverseSchema::isOccurrenceRangeOK(const int min1, const int max1, - const int min2, const int max2) { - - if (min1 >= min2 && - (max2 == SchemaSymbols::UNBOUNDED || - (max1 != SchemaSymbols::UNBOUNDED && max1 <= max2))) { - return true; - } - return false; -} - #endif /** diff --git a/src/xercesc/validators/schema/XercesGroupInfo.cpp b/src/xercesc/validators/schema/XercesGroupInfo.cpp index 40a28bed63204ac29c457c7a604ff33a9f0a7d7d..55b456747214877ad65502260fa1e758128f01f5 100644 --- a/src/xercesc/validators/schema/XercesGroupInfo.cpp +++ b/src/xercesc/validators/schema/XercesGroupInfo.cpp @@ -56,8 +56,11 @@ /* * $Log$ - * Revision 1.1 2002/02/01 22:22:50 peiyongz - * Initial revision + * Revision 1.2 2002/03/25 20:25:32 knoaman + * Move particle derivation checking from TraverseSchema to SchemaValidator. + * + * Revision 1.1.1.1 2002/02/01 22:22:50 peiyongz + * sane_include * * Revision 1.2 2001/08/24 20:36:37 knoaman * Add support for <redefine>. @@ -72,6 +75,7 @@ // --------------------------------------------------------------------------- #include <xercesc/validators/schema/XercesGroupInfo.hpp> #include <xercesc/validators/common/ContentSpecNode.hpp> +#include <xercesc/validators/schema/XSDLocator.hpp> // --------------------------------------------------------------------------- // XercesGroupInfo: Constructors and Destructor @@ -80,6 +84,8 @@ XercesGroupInfo::XercesGroupInfo() : fScope(-1) , fContentSpec(0) , fElements(0) + , fBaseGroup(0) + , fLocator(0) { fElements = new RefVectorOf<SchemaElementDecl>(4, false); } @@ -89,6 +95,19 @@ XercesGroupInfo::~XercesGroupInfo() { delete fElements; delete fContentSpec; + delete fLocator; +} + + +// --------------------------------------------------------------------------- +// XercesGroupInfo: Constructors and Destructor +// --------------------------------------------------------------------------- +void XercesGroupInfo::setLocator(XSDLocator* const aLocator) { + + if (fLocator) + delete fLocator; + + fLocator = aLocator; } /** diff --git a/src/xercesc/validators/schema/XercesGroupInfo.hpp b/src/xercesc/validators/schema/XercesGroupInfo.hpp index 408b2b6b532c2650255acffd6765cb0a55f74cbe..3be34e1d3f7cfe2721032122e5456a21a31d0415 100644 --- a/src/xercesc/validators/schema/XercesGroupInfo.hpp +++ b/src/xercesc/validators/schema/XercesGroupInfo.hpp @@ -79,6 +79,7 @@ // Forward Declarations // --------------------------------------------------------------------------- class ContentSpecNode; +class XSDLocator; class VALIDATORS_EXPORT XercesGroupInfo @@ -93,11 +94,13 @@ public: // ----------------------------------------------------------------------- // Getter methods // ----------------------------------------------------------------------- - int getScope() const; - unsigned int elementCount() const; - ContentSpecNode* getContentSpec() const; - SchemaElementDecl* elementAt(const unsigned int index); - const SchemaElementDecl* elementAt(const unsigned int index) const; + int getScope() const; + unsigned int elementCount() const; + ContentSpecNode* getContentSpec() const; + SchemaElementDecl* elementAt(const unsigned int index); + const SchemaElementDecl* elementAt(const unsigned int index) const; + XSDLocator* getLocator() const; + XercesGroupInfo* getBaseGroup() const; // ----------------------------------------------------------------------- // Setter methods @@ -105,11 +108,8 @@ public: void setScope(const int other); void setContentSpec(ContentSpecNode* const other); void addElement(SchemaElementDecl* const toAdd); - - // ----------------------------------------------------------------------- - // Query methods - // ----------------------------------------------------------------------- - bool containsElement(const SchemaElementDecl* const elem); + void setLocator(XSDLocator* const aLocator); + void setBaseGroup(XercesGroupInfo* const baseGroup); private: // ----------------------------------------------------------------------- @@ -124,6 +124,8 @@ private: int fScope; ContentSpecNode* fContentSpec; RefVectorOf<SchemaElementDecl>* fElements; + XercesGroupInfo* fBaseGroup; // redefine by restriction + XSDLocator* fLocator; }; // --------------------------------------------------------------------------- @@ -156,6 +158,16 @@ XercesGroupInfo::elementAt(const unsigned int index) const { return fElements->elementAt(index); } +inline XSDLocator* XercesGroupInfo::getLocator() const { + + return fLocator; +} + +inline XercesGroupInfo* XercesGroupInfo::getBaseGroup() const { + + return fBaseGroup; +} + // --------------------------------------------------------------------------- // XercesGroupInfo: Setter methods // ---------------------------------------------------------------------------} @@ -171,24 +183,13 @@ inline void XercesGroupInfo::setContentSpec(ContentSpecNode* const other) { inline void XercesGroupInfo::addElement(SchemaElementDecl* const elem) { - fElements->addElement(elem); + if (!fElements->containsElement(elem)) + fElements->addElement(elem); } +inline void XercesGroupInfo::setBaseGroup(XercesGroupInfo* const baseGroup) { -// --------------------------------------------------------------------------- -// XercesGroupInfo: Query methods -// ---------------------------------------------------------------------------} -inline bool XercesGroupInfo::containsElement(const SchemaElementDecl* const elem) { - - unsigned int elemSize = fElements->size(); - - for (unsigned int i=0; i < elemSize; i++) { - if (fElements->elementAt(i) == elem) { - return true; - } - } - - return false; + fBaseGroup = baseGroup; } #endif