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