GME  13
SchemaValidator.cpp
Go to the documentation of this file.
00001 /*
00002  * Licensed to the Apache Software Foundation (ASF) under one or more
00003  * contributor license agreements.  See the NOTICE file distributed with
00004  * this work for additional information regarding copyright ownership.
00005  * The ASF licenses this file to You under the Apache License, Version 2.0
00006  * (the "License"); you may not use this file except in compliance with
00007  * the License.  You may obtain a copy of the License at
00008  *
00009  *      http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 /*
00019  * $Id: SchemaValidator.cpp 806488 2009-08-21 10:36:58Z amassari $
00020  */
00021 
00022 // ---------------------------------------------------------------------------
00023 //  Includes
00024 // ---------------------------------------------------------------------------
00025 #include <xercesc/util/Janitor.hpp>
00026 #include <xercesc/framework/XMLDocumentHandler.hpp>
00027 #include <xercesc/framework/XMLSchemaDescription.hpp>
00028 #include <xercesc/framework/psvi/XSAnnotation.hpp>
00029 #include <xercesc/internal/XMLReader.hpp>
00030 #include <xercesc/internal/XMLScanner.hpp>
00031 #include <xercesc/internal/ElemStack.hpp>
00032 #include <xercesc/validators/datatype/DatatypeValidatorFactory.hpp>
00033 #include <xercesc/validators/datatype/ListDatatypeValidator.hpp>
00034 #include <xercesc/validators/datatype/UnionDatatypeValidator.hpp>
00035 #include <xercesc/validators/datatype/ENTITYDatatypeValidator.hpp>
00036 #include <xercesc/validators/datatype/IDDatatypeValidator.hpp>
00037 #include <xercesc/validators/datatype/IDREFDatatypeValidator.hpp>
00038 #include <xercesc/validators/schema/SchemaSymbols.hpp>
00039 #include <xercesc/validators/schema/SchemaValidator.hpp>
00040 #include <xercesc/validators/schema/SubstitutionGroupComparator.hpp>
00041 #include <xercesc/validators/schema/XercesGroupInfo.hpp>
00042 #include <xercesc/validators/schema/XSDLocator.hpp>
00043 #include <xercesc/util/OutOfMemoryException.hpp>
00044 
00045 XERCES_CPP_NAMESPACE_BEGIN
00046 
00047 // ---------------------------------------------------------------------------
00048 //  SchemaValidator: Constructors and Destructor
00049 // ---------------------------------------------------------------------------
00050 SchemaValidator::SchemaValidator( XMLErrorReporter* const errReporter
00051                                 , MemoryManager* const    manager) :
00052 
00053     XMLValidator(errReporter)
00054     , fMemoryManager(manager)
00055     , fSchemaGrammar(0)
00056     , fGrammarResolver(0)
00057     , fXsiType(0)
00058     , fNil(false)
00059     , fNilFound(false)
00060     , fCurrentDatatypeValidator(0)
00061     , fNotationBuf(0)
00062     , fDatatypeBuffer(1023, manager)
00063     , fTrailing(false)
00064     , fSeenNonWhiteSpace(false)
00065     , fSeenId(false)
00066     , fTypeStack(0)
00067     , fMostRecentAttrValidator(0)
00068     , fErrorOccurred(false)
00069     , fElemIsSpecified(false)
00070 {
00071     fTypeStack = new (fMemoryManager) ValueStackOf<ComplexTypeInfo*>(8, fMemoryManager);
00072 }
00073 
00074 SchemaValidator::~SchemaValidator()
00075 {
00076     delete fXsiType;
00077     delete fTypeStack;
00078 
00079     if (fNotationBuf)
00080         delete fNotationBuf;
00081 }
00082 
00083 // ---------------------------------------------------------------------------
00084 //  SchemaValidator: Implementation of the XMLValidator interface
00085 // ---------------------------------------------------------------------------
00086 bool SchemaValidator::checkContent (XMLElementDecl* const elemDecl
00087                                  , QName** const          children
00088                                  , XMLSize_t              childCount
00089                                  , XMLSize_t*             indexFailingChild)
00090 {
00091     fErrorOccurred = false;
00092     fElemIsSpecified = false;
00093 
00094     //
00095     //  Look up the element id in our element decl pool. This will get us
00096     //  the element decl in our own way of looking at them.
00097     //
00098     if (!elemDecl)
00099         ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Val_InvalidElemId, fMemoryManager);
00100 
00101     //
00102     //  Get the content spec type of this element. This will tell us what
00103     //  to do to validate it.
00104     //
00105     // the top of the type stack always knows best...
00106     ComplexTypeInfo* currType = fTypeStack->pop();
00107 
00108     const SchemaElementDecl::ModelTypes modelType = (currType)
00109             ? (SchemaElementDecl::ModelTypes)(currType->getContentType())
00110             : ((SchemaElementDecl*)elemDecl)->getModelType();
00111 
00112     if (modelType == SchemaElementDecl::Empty  ||
00113         modelType == SchemaElementDecl::ElementOnlyEmpty)
00114     {
00115         //
00116         //  We can do this one here. It cannot have any children. If it does
00117         //  we return 0 as the index of the first bad child.
00118         //
00119         if (childCount) {
00120             fErrorOccurred = true;
00121             *indexFailingChild=0;
00122             return false;
00123         }
00124     }
00125     else if ((modelType == SchemaElementDecl::Mixed_Simple)
00126          ||  (modelType == SchemaElementDecl::Mixed_Complex)
00127          ||  (modelType == SchemaElementDecl::Children))
00128     {
00129         // if nillable, it's an error to have value
00130         // XML Schema REC: Validation Rule: Element Locally Valid (Element)
00131         // 3.2.1 The element information item must have no
00132         // character or element information item [children].
00133         //
00134         if (fNil) {
00135             if (childCount > 0 || !XMLString::equals(fDatatypeBuffer.getRawBuffer(), XMLUni::fgZeroLenString)) {
00136                 emitError(XMLValid::NilAttrNotEmpty, elemDecl->getFullName());
00137                 fErrorOccurred = true;
00138             }
00139         }
00140         else {
00141             // Get the element's content model or fault it in
00142             XMLContentModel* elemCM = (currType)
00143                     ? currType->getContentModel()
00144                     : ((SchemaElementDecl*)elemDecl)->getContentModel();
00145 
00146             // Ask it to validate and return its return
00147             unsigned int emptyNS = getScanner()->getEmptyNamespaceId();
00148             bool result = elemCM->validateContent(children, childCount, emptyNS, indexFailingChild, getScanner()->getMemoryManager());
00149             if (!result) {
00150                 result = elemCM->validateContentSpecial(children
00151                                                       , childCount
00152                                                       , emptyNS
00153                                                       , fGrammarResolver
00154                                                       , fGrammarResolver->getStringPool()
00155                                                       , indexFailingChild
00156                                                                                                           , getScanner()->getMemoryManager());
00157             }
00158 
00159             if(!result) {
00160                 fErrorOccurred = true;
00161             }
00162 
00163             return result;
00164         }
00165     }
00166     else if (modelType == SchemaElementDecl::Simple || modelType == SchemaElementDecl::Any)
00167     {
00168         // Normally for SchemaElementDecl::Any, We pass no judgement on it and anything goes
00169         // but if there is a fXsiTypeValidator, we need to use it for validation
00170         if (modelType == SchemaElementDecl::Simple && childCount > 0) {
00171             emitError(XMLValid::SimpleTypeHasChild, elemDecl->getFullName());
00172             fErrorOccurred = true;
00173         }
00174         else
00175         {
00176             XMLCh* value = fDatatypeBuffer.getRawBuffer();
00177             XMLCh* elemDefaultValue = ((SchemaElementDecl*) elemDecl)->getDefaultValue();
00178 
00179             if (fNil)
00180             {
00181                 if ((!XMLString::equals(value, XMLUni::fgZeroLenString))
00182                     || elemDefaultValue)
00183                 {
00184                     emitError(XMLValid::NilAttrNotEmpty, elemDecl->getFullName());
00185                     fErrorOccurred = true;
00186                 }
00187             }
00188                         else if (fCurrentDatatypeValidator)
00189             {
00190                 DatatypeValidator::ValidatorType eleDefDVType = fCurrentDatatypeValidator->getType();
00191                 bool validateCanonical = false;
00192                 if (eleDefDVType == DatatypeValidator::NOTATION)
00193                 {
00194                     // if notation, need to bind URI to notation first
00195                     if (!fNotationBuf)
00196                         fNotationBuf = new (fMemoryManager) XMLBuffer(1023, fMemoryManager);
00197 
00198                     //  Make sure that this value maps to one of the
00199                     //  notation values in the enumList parameter. We don't have to
00200                     //  look it up in the notation pool (if a notation) because we
00201                     //  will look up the enumerated values themselves. If they are in
00202                     //  the notation pool (after the Grammar is parsed), then obviously
00203                     //  this value will be legal since it matches one of them.
00204                     int colonPos = -1;
00205                     unsigned int uriId = getScanner()->resolveQName(value, *fNotationBuf, ElemStack::Mode_Element, colonPos);
00206 
00207                     const XMLCh* uriText = getScanner()->getURIText(uriId);
00208                     if (uriText && *uriText) {
00209                         fNotationBuf->set(uriText);
00210                         fNotationBuf->append(chColon);
00211                         fNotationBuf->append(&value[colonPos + 1]);
00212                         value = fNotationBuf->getRawBuffer();
00213                     }
00214                 }
00215 
00216                 if (elemDefaultValue)
00217                 {
00218                     if (XMLString::equals(value, XMLUni::fgZeroLenString))
00219                     {
00220                         fElemIsSpecified = true;
00221                         // if this element didn't specified any value
00222                         // use default value
00223                         if (getScanner()->getDocHandler())
00224                             getScanner()->getDocHandler()->docCharacters(elemDefaultValue, XMLString::stringLen(elemDefaultValue), false);
00225 
00226                         // Normally for default value, it has been validated already during TraverseSchema
00227                         // But if there was a xsi:type and this validator is fXsiTypeValidator,
00228                         // need to validate again
00229                         // we determine this if the current content dataype validator
00230                         // is neither the one in the element nor the one in the current
00231                         // complex type (if any)
00232                         if ((fCurrentDatatypeValidator != ((SchemaElementDecl*)elemDecl)->getDatatypeValidator())
00233                             && (!fTypeStack->peek() || (fCurrentDatatypeValidator != fTypeStack->peek()->getDatatypeValidator()))) {
00234                             value = elemDefaultValue;
00235                             validateCanonical = true;
00236                         }
00237                         else
00238                             value = 0;
00239                     }
00240                     else
00241                     {
00242                         // this element has specified some value
00243                         // if the flag is FIXED, then this value must be same as default value
00244                         if ((((SchemaElementDecl*)elemDecl)->getMiscFlags() & SchemaSymbols::XSD_FIXED) != 0)
00245                         {
00246                             if (fCurrentDatatypeValidator->compare(value, elemDefaultValue, fMemoryManager) != 0 )
00247                             {
00248                                 emitError(XMLValid::FixedDifferentFromActual, elemDecl->getFullName());
00249                                 fErrorOccurred = true;
00250                             }
00251                         }
00252                     }
00253                 }
00254 
00255                 if ((!fErrorOccurred) && value)
00256                 {
00257                     try {
00258                         fCurrentDatatypeValidator->validate(value, getScanner()->getValidationContext(), fMemoryManager);
00259                         if (validateCanonical) {
00260                             XMLCh* canonical = (XMLCh*) fCurrentDatatypeValidator->getCanonicalRepresentation(value, fMemoryManager);
00261                             ArrayJanitor<XMLCh> tempCanonical(canonical, fMemoryManager);
00262                             fCurrentDatatypeValidator->validate(canonical, getScanner()->getValidationContext(), fMemoryManager);
00263                         }
00264                     }
00265                     catch (XMLException& idve)
00266                     {
00267                         emitError (XMLValid::DatatypeError, idve.getCode(), idve.getMessage());
00268                         fErrorOccurred = true;
00269                     }
00270                     catch(const OutOfMemoryException&) {
00271                         throw;
00272                     }
00273                     catch (...)
00274                     {
00275                         emitError(XMLValid::GenericError);
00276                         throw;
00277                     }
00278                 }
00279             }
00280             else if (modelType == SchemaElementDecl::Simple)
00281             {
00282                 emitError(XMLValid::NoDatatypeValidatorForSimpleType, elemDecl->getFullName());
00283                 fErrorOccurred = true;
00284             }
00285             // modelType is any
00286             else if (elemDefaultValue)
00287             {
00288                 if (XMLString::equals(value, XMLUni::fgZeroLenString))
00289                 {
00290                     fElemIsSpecified = true;
00291                     // if this element didn't specified any value
00292                     // use default value
00293                     if (getScanner()->getDocHandler()) {
00294                         getScanner()->getDocHandler()->docCharacters(elemDefaultValue, XMLString::stringLen(elemDefaultValue), false);
00295                     }
00296                 }
00297             }
00298         }
00299     }
00300     else
00301     {
00302         ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_UnknownCMType, fMemoryManager);
00303     }
00304 
00305     // must rely on scanner to clear fDatatypeBuffer
00306     // since it may need to query its contents after this method completes
00307     fNil = false;
00308     fNilFound = false;
00309     fTrailing=false;
00310     fSeenNonWhiteSpace = false;
00311     fCurrentDatatypeValidator = 0;
00312 
00313     // Went ok, so return success
00314     return true;
00315 }
00316 
00317 void SchemaValidator::faultInAttr (XMLAttr&    toFill, const XMLAttDef&  attDef)   const
00318 {
00319     //
00320     //  At this level, we cannot set the URI id. So we just set it to zero
00321     //  and leave it at that. The scanner, who called us, will look at the
00322     //  prefix we stored (if any), resolve it, and store the URL id if any.
00323     //
00324     SchemaAttDef* schemaAttDef = (SchemaAttDef*) &attDef;
00325     QName* attName = schemaAttDef->getAttName();
00326 
00327     toFill.set
00328     (
00329           attName->getURI()
00330         , attName->getLocalPart()
00331         , attName->getPrefix()
00332         , schemaAttDef->getValue()
00333         , schemaAttDef->getType()
00334     );
00335 }
00336 
00337 void SchemaValidator::reset()
00338 {
00339     fTrailing = false;
00340     fSeenNonWhiteSpace = false;
00341     fSeenId = false;
00342         fTypeStack->removeAllElements();
00343     delete fXsiType;
00344     fXsiType = 0;
00345     fCurrentDatatypeValidator = 0;
00346     fNil = false;
00347     fNilFound = false;
00348     fDatatypeBuffer.reset();
00349     fErrorOccurred = false;
00350 }
00351 
00352 bool SchemaValidator::requiresNamespaces() const
00353 {
00354     return true;
00355 }
00356 
00357 void SchemaValidator::validateAttrValue (const XMLAttDef*      attDef
00358                                        , const XMLCh* const    attrValue
00359                                        , bool                  preValidation
00360                                        , const XMLElementDecl* elemDecl)
00361 {
00362     fErrorOccurred = false;
00363 
00364     //turn on IdRefList checking
00365     getScanner()->getValidationContext()->toCheckIdRefList(true);
00366 
00367     //
00368     //  Get quick refs to lot of the stuff in the passed objects in
00369     //  order to simplify the code below, which will reference them very
00370     //  often.
00371     //
00372     XMLAttDef::AttTypes            type      = attDef->getType();
00373     const XMLAttDef::DefAttTypes   defType   = attDef->getDefaultType();
00374 
00375     //
00376     //  If the default type is fixed, then make sure the passed value maps
00377     //  to the fixed value.
00378     //
00379     //  If during preContentValidation, the value we are validating is the fixed value itself
00380     //  so no need to compare.
00381     //  Only need to do this for regular attribute value validation
00382     //
00383     if ((defType == XMLAttDef::Fixed || defType == XMLAttDef::Required_And_Fixed) && !preValidation)
00384     {
00385         const XMLCh* const valueText = attDef->getValue();
00386         if (!XMLString::equals(attrValue, valueText)) {
00387             emitError(XMLValid::NotSameAsFixedValue, attDef->getFullName(), attrValue, valueText);
00388             fErrorOccurred = true;
00389         }
00390     }
00391 
00392     // An empty string cannot be valid for non_CDATA any of the other types
00393     if (!attrValue[0] && type != XMLAttDef::Simple)
00394     {
00395         emitError(XMLValid::InvalidEmptyAttValue, attDef->getFullName());
00396         // accords with original DOMTypeInfo implementation, but this does not feel right.
00397         fMostRecentAttrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYSIMPLETYPE);
00398         fErrorOccurred = true;
00399         return;
00400     }
00401 
00402     DatatypeValidator* attDefDV = ((SchemaAttDef*) attDef)->getDatatypeValidator();
00403     if (!attDefDV) {
00404         emitError(XMLValid::NoDatatypeValidatorForAttribute, attDef->getFullName());
00405         fErrorOccurred = true;
00406     }
00407     else {
00408         DatatypeValidator::ValidatorType attDefDVType = attDefDV->getType();
00409         ValidationContext *context = getScanner()->getValidationContext();
00410         try {
00411 
00412             // first, if notation, need to bind URI to notation first
00413             if (attDefDVType == DatatypeValidator::NOTATION)
00414             {
00415                 //
00416                 //  Make sure that this value maps to one of the
00417                 //  notation values in the enumList parameter. We don't have to
00418                 //  look it up in the notation pool (if a notation) because we
00419                 //  will look up the enumerated values themselves. If they are in
00420                 //  the notation pool (after the Grammar is parsed), then obviously
00421                 //  this value will be legal since it matches one of them.
00422                 //
00423                 XMLBuffer notationBuf(1023, fMemoryManager);
00424                 int colonPos = -1;
00425                 unsigned int uriId = getScanner()->resolveQName(attrValue, notationBuf, ElemStack::Mode_Element, colonPos);
00426                 const XMLCh* uriText = getScanner()->getURIText(uriId);
00427                 if (uriText && *uriText) {
00428                     notationBuf.set(uriText);
00429                     notationBuf.append(chColon);
00430                     notationBuf.append(&attrValue[colonPos + 1]);
00431                 }
00432                 else {
00433                     notationBuf.set(attrValue);
00434                 }
00435 
00436                 attDefDV->validate(notationBuf.getRawBuffer()
00437                                  , context
00438                                  , fMemoryManager);
00439             }
00440             else {
00441                 attDefDV->validate(attrValue
00442                                  , context
00443                                  , fMemoryManager);
00444             }
00445 
00446         }
00447         catch (XMLException& idve) {
00448             fErrorOccurred = true;
00449             emitError (XMLValid::DatatypeError, idve.getCode(), idve.getMessage());
00450         }
00451         catch(const OutOfMemoryException&)
00452         {
00453             throw;
00454         }
00455         catch (...) {
00456             emitError(XMLValid::GenericError);
00457             fMostRecentAttrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYSIMPLETYPE);
00458             fErrorOccurred = true;
00459             throw;
00460         }
00461         fMostRecentAttrValidator = attDefDV;
00462         // now we can look for ID's, entities, ...
00463 
00464         // set up the entitydeclpool in ENTITYDatatypeValidator
00465         // and the idreflist in ID/IDREFDatatypeValidator
00466 
00467         // indicate if this attribute is of type ID
00468         bool thisIsAnId = false;
00469 
00470         if (attDefDVType == DatatypeValidator::List) {
00471             DatatypeValidator* itemDTV = ((ListDatatypeValidator*)attDefDV)->getItemTypeDTV();
00472             DatatypeValidator::ValidatorType itemDTVType = itemDTV->getType();
00473             if (itemDTVType == DatatypeValidator::ID) {
00474                 thisIsAnId = true;
00475             }
00476             else if (itemDTVType == DatatypeValidator::IDREF) {
00477                 // if in prevalidatoin, do not add attDef to IDREFList
00478                 if (preValidation)
00479                     //todo: when to setIdRefList back to non-null
00480                     getScanner()->getValidationContext()->toCheckIdRefList(false);
00481             }
00482         }
00483         else if (attDefDVType == DatatypeValidator::Union) {
00484             DatatypeValidator *memberDTV = context->getValidatingMemberType();
00485             // actual type for DOMTypeInfo is memberDTV
00486             fMostRecentAttrValidator = memberDTV;
00487             // no member datatype validator if there was an error
00488             if(memberDTV)
00489             {
00490                 DatatypeValidator::ValidatorType memberDTVType = memberDTV->getType();
00491                 if (memberDTVType == DatatypeValidator::ID) {
00492                     thisIsAnId = true;
00493                 }
00494                 else if (memberDTVType == DatatypeValidator::IDREF) {
00495                     // if in prevalidatoin, do not add attDef to IDREFList
00496                     if (preValidation)
00497                         getScanner()->getValidationContext()->toCheckIdRefList(false);
00498                 }
00499             }
00500         }
00501         else if (attDefDVType == DatatypeValidator::ID) {
00502             thisIsAnId = true;
00503         }
00504         else if (attDefDVType == DatatypeValidator::IDREF) {
00505             // if in prevalidation, do not add attDef to IDREFList
00506             if (preValidation)
00507                 getScanner()->getValidationContext()->toCheckIdRefList(false);
00508         }
00509         if (thisIsAnId) {
00510             if (fSeenId) {
00511                 emitError
00512                 (
00513                     XMLValid::MultipleIdAttrs
00514                     , elemDecl->getFullName()
00515                 );
00516                 fErrorOccurred = true;
00517             }
00518             else
00519                 fSeenId = true;
00520         }
00521 
00522     }
00523 
00524     if(fErrorOccurred) {
00525         fMostRecentAttrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYSIMPLETYPE);
00526     }
00527     fTrailing = false;
00528     fSeenNonWhiteSpace = false;
00529 }
00530 
00531 void SchemaValidator::validateElement(const   XMLElementDecl*  elemDef)
00532 {
00533     ComplexTypeInfo* elemTypeInfo = ((SchemaElementDecl*)elemDef)->getComplexTypeInfo();
00534     fTypeStack->push(elemTypeInfo);
00535     fCurrentDatatypeValidator = (elemTypeInfo)
00536             ? elemTypeInfo->getDatatypeValidator()
00537             : ((SchemaElementDecl*)elemDef)->getDatatypeValidator();
00538 
00539     fErrorOccurred = false;
00540 
00541     if (fXsiType) {
00542         // handle "xsi:type" right here
00543         DatatypeValidator *xsiTypeDV = 0;
00544         unsigned int uri = fXsiType->getURI();
00545         const XMLCh* localPart = fXsiType->getLocalPart();
00546 
00547         if (uri != XMLElementDecl::fgInvalidElemId &&
00548             uri != XMLElementDecl::fgPCDataElemId &&
00549             uri != XMLContentModel::gEpsilonFakeId &&
00550             uri != XMLContentModel::gEOCFakeId) {
00551 
00552             // retrieve Grammar for the uri
00553             const XMLCh* uriStr = getScanner()->getURIText(uri);
00554             SchemaGrammar* sGrammar = (SchemaGrammar*) fGrammarResolver->getGrammar(uriStr);
00555             if (!sGrammar) {
00556 
00557                 // Check built-in simple types
00558                 if (XMLString::equals(uriStr, SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) {
00559 
00560                     xsiTypeDV = fGrammarResolver->getDatatypeValidator(uriStr, localPart);
00561 
00562                     if (!xsiTypeDV) {
00563                         emitError(XMLValid::BadXsiType, fXsiType->getRawName());
00564                         fErrorOccurred = true;
00565                     }
00566                     else {
00567                         if (elemTypeInfo || (fCurrentDatatypeValidator
00568                                 && !fCurrentDatatypeValidator->isSubstitutableBy(xsiTypeDV))) {
00569                             // the type is not derived from ancestor
00570                             emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName());
00571                             fErrorOccurred = true;
00572                         }
00573                         else if(fCurrentDatatypeValidator != xsiTypeDV) 
00574                         {
00575                             // the type is derived from ancestor
00576                             if ((((SchemaElementDecl*)elemDef)->getBlockSet() & SchemaSymbols::XSD_RESTRICTION) != 0) {
00577                                 emitError(XMLValid::ElemNoSubforBlock, elemDef->getFullName());
00578                                 fErrorOccurred = true;
00579                             }
00580                             if (elemDef->hasAttDefs()) {
00581                                 // if we have an attribute but xsi:type's type is simple, we have a problem...
00582                                 emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName());
00583                                 fErrorOccurred = true;
00584                             }
00585                         }
00586                         fCurrentDatatypeValidator = xsiTypeDV;
00587                     }
00588                 }
00589                 else {
00590                     // Grammar not found
00591                     emitError(XMLValid::GrammarNotFound, uriStr);
00592                     fErrorOccurred = true;
00593                 }
00594             }
00595             else if (sGrammar->getGrammarType() != Grammar::SchemaGrammarType) {
00596                 emitError(XMLValid::GrammarNotFound, uriStr);
00597                 fErrorOccurred = true;
00598             }
00599             else {
00600                 // retrieve complexType registry and DatatypeValidator registry
00601                 RefHashTableOf<ComplexTypeInfo>* complexTypeRegistry = sGrammar->getComplexTypeRegistry();
00602                 if (!complexTypeRegistry) {
00603                     emitError(XMLValid::BadXsiType, fXsiType->getRawName());
00604                     fErrorOccurred = true;
00605                 }
00606                 else {
00607 
00608                     // retrieve the typeInfo specified in xsi:type
00609                     XMLBuffer aBuffer(1023, fMemoryManager);
00610                     aBuffer.set(uriStr);
00611                     aBuffer.append(chComma);
00612                     aBuffer.append(localPart);
00613                     ComplexTypeInfo* typeInfo = complexTypeRegistry->get(aBuffer.getRawBuffer());
00614 
00615                     if (typeInfo) {
00616                         // typeInfo is found
00617                         if (typeInfo->getAbstract()) {
00618                             emitError(XMLValid::NoAbstractInXsiType, aBuffer.getRawBuffer());
00619                             fErrorOccurred = true;
00620                         }
00621                         else
00622                         {
00623                             if (elemTypeInfo)
00624                             {
00625                                 ComplexTypeInfo* tempType = typeInfo;
00626                                 while (tempType) {
00627                                     if (tempType == elemTypeInfo)
00628                                         break;
00629                                     tempType = tempType->getBaseComplexTypeInfo();
00630                                 }
00631 
00632                                 if (!tempType) {
00633                                     emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName());
00634                                     fErrorOccurred = true;
00635                                 }
00636                                 else if(elemTypeInfo != typeInfo) {
00637                                     // perform the check on the entire inheritance chain
00638                                     ComplexTypeInfo* tempType = typeInfo;
00639                                     while (tempType) {
00640                                         if (tempType == elemTypeInfo)
00641                                             break;
00642                                         int derivationMethod = tempType->getDerivedBy();
00643                                         if ((((SchemaElementDecl*)elemDef)->getBlockSet() & derivationMethod) != 0) {
00644                                             emitError(XMLValid::ElemNoSubforBlock, elemDef->getFullName());
00645                                             fErrorOccurred = true;
00646                                         }
00647                                         if ((elemTypeInfo->getBlockSet() & derivationMethod) != 0) {
00648                                             emitError(XMLValid::TypeNoSubforBlock, elemTypeInfo->getTypeName());
00649                                             fErrorOccurred = true;
00650                                         }
00651                                         tempType = tempType->getBaseComplexTypeInfo();
00652                                     }
00653                                 }
00654                             }
00655                             else
00656                             {
00657                                 // if the original type is a simple type, check derivation ok.
00658                                 if (fCurrentDatatypeValidator && !fCurrentDatatypeValidator->isSubstitutableBy(typeInfo->getDatatypeValidator())) {
00659                                     // the type is not derived from ancestor
00660                                     emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName());
00661                                     fErrorOccurred = true;
00662                                 }
00663                             }
00664 
00665                             if (!fErrorOccurred)
00666                             {
00667                                 fTypeStack->pop();
00668                                 fTypeStack->push(typeInfo);
00669                                 fCurrentDatatypeValidator = typeInfo->getDatatypeValidator();
00670                             }
00671                         }
00672                     }
00673                     else
00674                     {
00675                         // typeInfo not found
00676                         xsiTypeDV = fGrammarResolver->getDatatypeValidator(uriStr, localPart);
00677 
00678                         if (!xsiTypeDV) {
00679                             emitError(XMLValid::BadXsiType, fXsiType->getRawName());
00680                             fErrorOccurred = true;
00681                         }
00682                         else {
00683                             if (fCurrentDatatypeValidator && !fCurrentDatatypeValidator->isSubstitutableBy(xsiTypeDV)) {
00684                                 // the type is not derived from ancestor
00685                                 emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName());
00686                                 fErrorOccurred = true;
00687                             }
00688                             else if(fCurrentDatatypeValidator != xsiTypeDV)
00689                             {
00690                                 DatatypeValidator::ValidatorType derivedType=xsiTypeDV->getType();
00691                                 if((derivedType == DatatypeValidator::List || derivedType == DatatypeValidator::Union) && fCurrentDatatypeValidator==0)
00692                                 {
00693                                     // the substitution is always allowed if the type is list or union and the base type was xs:anySimpleType
00694                                 }
00695                                 else
00696                                 {
00697                                     // the type is derived from ancestor
00698                                     if ((((SchemaElementDecl*)elemDef)->getBlockSet() & SchemaSymbols::XSD_RESTRICTION) != 0) {
00699                                         emitError(XMLValid::ElemNoSubforBlock, elemDef->getFullName());
00700                                         fErrorOccurred = true;
00701                                     }
00702                                     if (elemDef->hasAttDefs()) {
00703                                         // if we have an attribute but xsi:type's type is simple, we have a problem...
00704                                         emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName());
00705                                         fErrorOccurred = true;
00706                                     }
00707                                 }
00708                             }
00709 
00710                             fCurrentDatatypeValidator = xsiTypeDV;
00711                         }
00712                     }
00713                 }
00714             }
00715         }
00716 
00717         delete fXsiType;
00718         fXsiType = 0;
00719     }
00720     else {
00721         //
00722         // xsi:type was not specified...
00723         // If the corresponding type is abstract, detect an error
00724         //
00725         if (elemTypeInfo && elemTypeInfo->getAbstract()) {
00726             emitError(XMLValid::NoUseAbstractType, elemDef->getFullName());
00727             fErrorOccurred = true;
00728         }
00729     }
00730 
00731     //
00732     // Check whether this element is abstract.  If so, an error
00733     //
00734     int miscFlags = ((SchemaElementDecl*)elemDef)->getMiscFlags();
00735     if ((miscFlags & SchemaSymbols::XSD_ABSTRACT) != 0) {
00736         emitError(XMLValid::NoDirectUseAbstractElement, elemDef->getFullName());
00737         fErrorOccurred = true;
00738     }
00739 
00740     //
00741     // Check whether this element allows Nillable
00742     //
00743     if (fNilFound && (miscFlags & SchemaSymbols::XSD_NILLABLE) == 0 ) {
00744         fNil = false;
00745         fNilFound = false;
00746         emitError(XMLValid::NillNotAllowed, elemDef->getFullName());
00747         fErrorOccurred = true;
00748     }
00749 
00750     fDatatypeBuffer.reset();
00751     fTrailing = false;
00752     fSeenNonWhiteSpace = false;
00753     fSeenId = false;
00754 }
00755 
00756 void SchemaValidator::preContentValidation(bool,
00757                                            bool validateDefAttr)
00758 {
00759     //  Lets go through all the grammar in the GrammarResolver
00760     //    and validate those that has not been validated yet
00761     //
00762     //  Lets enumerate all of the elements in the element decl pool
00763     //    and put out an error for any that did not get declared.
00764     //    We also check all of the attributes as well.
00765     //
00766     //  And enumerate all the complextype info in the grammar
00767     //    and do Unique Particle Attribution Checking
00768 
00769     RefHashTableOfEnumerator<Grammar> grammarEnum = fGrammarResolver->getGrammarEnumerator();
00770     while (grammarEnum.hasMoreElements())
00771     {
00772         SchemaGrammar& sGrammar = (SchemaGrammar&) grammarEnum.nextElement();
00773         if (sGrammar.getGrammarType() != Grammar::SchemaGrammarType || sGrammar.getValidated())
00774              continue;
00775 
00776         sGrammar.setValidated(true);
00777 
00778         RefHash3KeysIdPoolEnumerator<SchemaElementDecl> elemEnum = sGrammar.getElemEnumerator();
00779 
00780         while (elemEnum.hasMoreElements())
00781         {
00782             SchemaElementDecl& curElem = elemEnum.nextElement();
00783 
00784             //  First check if declared or not
00785             //
00786             //  See if this element decl was ever marked as declared. If
00787             //  not, then put out an error. In some cases its just
00788             //  a warning, such as being referenced in a content model.
00789             //
00790             const SchemaElementDecl::CreateReasons reason = curElem.getCreateReason();
00791 
00792             if (reason != XMLElementDecl::Declared)
00793             {
00794                 if (reason == XMLElementDecl::AttList)
00795                 {
00796                     getScanner()->emitError
00797                     (
00798                         XMLErrs::UndeclaredElemInAttList
00799                         , curElem.getFullName()
00800                     );
00801                 }
00802                  else if (reason == XMLElementDecl::AsRootElem)
00803                 {
00804                     emitError
00805                     (
00806                         XMLValid::UndeclaredElemInDocType
00807                         , curElem.getFullName()
00808                     );
00809                 }
00810                  else if (reason == XMLElementDecl::InContentModel)
00811                 {
00812                     getScanner()->emitError
00813                     (
00814                         XMLErrs::UndeclaredElemInCM
00815                         , curElem.getFullName()
00816                     );
00817                 }
00818                 else
00819                 {
00820                 }
00821             }
00822 
00823             //
00824             //  Then check all of the attributes of the current element.
00825             //  We check for:
00826             //
00827             //  1) Multiple ID attributes
00828             //  2) That all of the default values of attributes are
00829             //      valid for their type.
00830             //  3) That for any notation types, that their lists
00831             //      of possible values refer to declared notations.
00832             //
00833             if (curElem.hasAttDefs()) {
00834                 XMLAttDefList& attDefList = curElem.getAttDefList();
00835                 bool seenId = false;
00836 
00837                 for(XMLSize_t i=0; i<attDefList.getAttDefCount(); i++)
00838                 {
00839                     const XMLAttDef& curAttDef = attDefList.getAttDef(i);
00840 
00841                     if (curAttDef.getType() == XMLAttDef::ID)
00842                     {
00843                         if (seenId)
00844                         {
00845                             emitError
00846                             (
00847                                 XMLValid::MultipleIdAttrs
00848                                 , curElem.getFullName()
00849                             );
00850                             break;
00851                         }
00852 
00853                         seenId = true;
00854                     }
00855                      else if (curAttDef.getType() == XMLAttDef::Notation && curAttDef.getEnumeration())
00856                     {
00857                         //
00858                         //  We need to verify that all of its possible values
00859                         //  (in the enum list) refer to valid notations.
00860                         //
00861                         XMLCh* list = XMLString::replicate(curAttDef.getEnumeration(), fMemoryManager);
00862                         ArrayJanitor<XMLCh> janList(list, fMemoryManager);
00863 
00864                         //
00865                         //  Search forward for a space or a null. If a null,
00866                         //  we are done. If a space, cap it and look it up.
00867                         //
00868                         bool    breakFlag = false;
00869                         XMLCh*  listPtr = list;
00870                         XMLCh*  lastPtr = listPtr;
00871                         while (true)
00872                         {
00873                             while (*listPtr && (*listPtr != chSpace))
00874                                 listPtr++;
00875 
00876                             //
00877                             //  If at the end, indicate we need to break after
00878                             //  this one. Else, cap it off here.
00879                             //
00880                             if (!*listPtr)
00881                                 breakFlag = true;
00882                             else
00883                                 *listPtr = chNull;
00884 
00885                             if (!sGrammar.getNotationDecl(lastPtr))
00886                             {
00887                                 emitError
00888                                 (
00889                                     XMLValid::UnknownNotRefAttr
00890                                     , curAttDef.getFullName()
00891                                     , lastPtr
00892                                 );
00893                             }
00894 
00895                             // Break out if we hit the end last time
00896                             if (breakFlag)
00897                                 break;
00898 
00899                             // Else move upwards and try again
00900                             listPtr++;
00901                             lastPtr = listPtr;
00902                         }
00903                     }
00904 
00905                     // If it has a default/fixed value, then validate it
00906                     if (validateDefAttr && curAttDef.getValue())
00907                     {
00908                         validateAttrValue
00909                         (
00910                             &curAttDef
00911                             , curAttDef.getValue()
00912                             , true
00913                             , &curElem
00914                         );
00915                     }
00916                 }
00917             }
00918         }
00919 
00920         //  For each complex type info, check the Unique Particle Attribution
00921         if (getScanner()->getValidationSchemaFullChecking()) {
00922             RefHashTableOf<ComplexTypeInfo>* complexTypeRegistry = sGrammar.getComplexTypeRegistry();
00923 
00924             RefHashTableOfEnumerator<ComplexTypeInfo> complexTypeEnum(complexTypeRegistry, false, fMemoryManager);
00925             while (complexTypeEnum.hasMoreElements())
00926             {
00927                 ComplexTypeInfo& curTypeInfo = complexTypeEnum.nextElement();
00928                 curTypeInfo.checkUniqueParticleAttribution(&sGrammar, fGrammarResolver, fGrammarResolver->getStringPool(), this);
00929                 checkParticleDerivation(&sGrammar, &curTypeInfo);
00930                 checkRefElementConsistency(&sGrammar, &curTypeInfo);
00931             }
00932 
00933             RefHashTableOf<XercesGroupInfo>* groupInfoRegistry = sGrammar.getGroupInfoRegistry();
00934             RefHashTableOfEnumerator<XercesGroupInfo> groupEnum(groupInfoRegistry, false, fMemoryManager);
00935 
00936             while (groupEnum.hasMoreElements()) {
00937 
00938                 XercesGroupInfo& curGroup = groupEnum.nextElement();
00939                 XercesGroupInfo* baseGroup = curGroup.getBaseGroup();
00940 
00941                 if (baseGroup) {
00942                     try {
00943                         checkParticleDerivationOk(&sGrammar, curGroup.getContentSpec(), curGroup.getScope(),
00944                                                   baseGroup->getContentSpec(), baseGroup->getScope());
00945                     }
00946                     catch (const XMLException& excep) {
00947                         fSchemaErrorReporter.emitError(excep, curGroup.getLocator());
00948                                         }
00949                 }
00950 
00951                 if (curGroup.getCheckElementConsistency())
00952                     checkRefElementConsistency(&sGrammar, 0, &curGroup);
00953             }
00954         }
00955     }
00956 }
00957 
00958 void SchemaValidator::postParseValidation()
00959 {
00960     //
00961     //  At this time, there is nothing to do here. The scanner itself handles
00962     //  ID/IDREF validation, since that is the same no matter what kind of
00963     //  validator.
00964     //
00965 }
00966 
00967 // ---------------------------------------------------------------------------
00968 //  SchemaValidator: Validator method
00969 // ---------------------------------------------------------------------------
00970 // Do Schema Normalization depends on the WhiteSpace Facet
00971 // preserve : No normalization is done
00972 // replace  : All occurrences of #x9 (tab), #xA (linefeed) and #xD (carriage return)
00973 //            are replaced with #x20 (space).
00974 // collapse : Subsequent to the replacements specified above under replace,
00975 //            contiguous sequences of #x20s are collapsed to a single #x20,
00976 //            and initial and/or final #x20s are deleted.
00977 //
00978 void SchemaValidator::normalizeWhiteSpace(DatatypeValidator* dV, const XMLCh* const value, XMLBuffer& toFill, bool bStandalone /*= false*/)
00979 {
00980     toFill.reset();
00981 
00982     //empty string
00983     if (!*value)
00984         return;
00985 
00986     if(bStandalone)
00987         fTrailing = fSeenNonWhiteSpace = false;
00988 
00989     short wsFacet = dV->getWSFacet();
00990 
00991     //  Loop through the chars of the source value and normalize it
00992     //  according to the whitespace facet
00993     XMLCh nextCh;
00994     const XMLCh* srcPtr = value;
00995     XMLReader* fCurReader = getReaderMgr()->getCurrentReader();
00996 
00997     if (wsFacet == DatatypeValidator::REPLACE)
00998     {
00999         while (*srcPtr)
01000         {
01001             nextCh = *srcPtr++;
01002             if (fCurReader->isWhitespace(nextCh))
01003                 nextCh = chSpace;
01004             // Add this char to the target buffer
01005             toFill.append(nextCh);
01006         }
01007     }
01008     else // COLLAPSE
01009     {
01010         enum States
01011         {
01012             InWhitespace
01013             , InContent
01014         };
01015 
01016         States curState = fTrailing ? InWhitespace : InContent;
01017         while (*srcPtr)
01018         {
01019             nextCh = *srcPtr++;
01020             if (curState == InContent)
01021             {
01022                 if (fCurReader->isWhitespace(nextCh))
01023                 {
01024                     curState = InWhitespace;
01025                     continue;
01026                 }
01027                 fSeenNonWhiteSpace = true;
01028             }
01029             else if (curState == InWhitespace)
01030             {
01031                 if (fCurReader->isWhitespace(nextCh))
01032                     continue;
01033                 if (fSeenNonWhiteSpace)
01034                     toFill.append(chSpace);
01035                 curState = InContent;
01036                 fSeenNonWhiteSpace = true;
01037             }
01038             // Add this char to the target buffer
01039             toFill.append(nextCh);
01040         }
01041 
01042         if (fCurReader->isWhitespace(*(srcPtr-1)))
01043           fTrailing = true;
01044         else
01045           fTrailing = false;
01046     }
01047     if(bStandalone)
01048         fTrailing = fSeenNonWhiteSpace = false;
01049 }
01050 
01051 
01052 // ---------------------------------------------------------------------------
01053 //  SchemaValidator: Particle Derivation Checking
01054 // ---------------------------------------------------------------------------
01055 void SchemaValidator::checkRefElementConsistency(SchemaGrammar* const currentGrammar,
01056                                                  const ComplexTypeInfo* const curTypeInfo,
01057                                                  const XercesGroupInfo* const curGroup) {
01058 
01059     XMLSize_t elemCount = (curTypeInfo) ? curTypeInfo->elementCount() : curGroup->elementCount();
01060     int elemScope = (curTypeInfo) ? curTypeInfo->getScopeDefined() : curGroup->getScope();
01061     XSDLocator* typeInfoLocator = (curTypeInfo) ? curTypeInfo->getLocator() : curGroup->getLocator();
01062 
01063     for (XMLSize_t i=0; i < elemCount; i++) {
01064 
01065         const SchemaElementDecl* elemDecl = (curTypeInfo) ? curTypeInfo->elementAt(i) : curGroup->elementAt(i);
01066 
01067         if (elemDecl->isGlobalDecl()) {
01068 
01069             unsigned int elemURI = elemDecl->getURI();
01070             const XMLCh* elemName = elemDecl->getBaseName();
01071             const SchemaElementDecl* other = (SchemaElementDecl*)
01072                 currentGrammar->getElemDecl(elemURI, elemName, 0, elemScope);
01073 
01074             if (other
01075                 && (elemDecl->getComplexTypeInfo() != other->getComplexTypeInfo() ||
01076                     elemDecl->getDatatypeValidator() != other->getDatatypeValidator())) {
01077                 fSchemaErrorReporter.emitError(XMLErrs::DuplicateElementDeclaration,
01078                                                XMLUni::fgXMLErrDomain, typeInfoLocator, elemName, 0, 0, 0, fMemoryManager);
01079                 continue;
01080             }
01081 
01082             RefHash2KeysTableOf<ElemVector>* validSubsGroups = currentGrammar->getValidSubstitutionGroups();
01083             ValueVectorOf<SchemaElementDecl*>* subsElements = validSubsGroups->get(elemName, elemURI);
01084 
01085             if (subsElements) {
01086 
01087                 XMLSize_t subsElemSize = subsElements->size();
01088 
01089                 for (XMLSize_t j=0; j < subsElemSize; j++) {
01090 
01091                     SchemaElementDecl* subsElem = subsElements->elementAt(j);
01092                     const XMLCh* subsElemName = subsElem->getBaseName();
01093                     other = (SchemaElementDecl*)
01094                         currentGrammar->getElemDecl(subsElem->getURI(), subsElemName, 0, elemScope);
01095 
01096                     if (other
01097                         && (subsElem->getComplexTypeInfo() != other->getComplexTypeInfo()
01098                             || subsElem->getDatatypeValidator() != other->getDatatypeValidator())) {
01099                         fSchemaErrorReporter.emitError(XMLErrs::DuplicateElementDeclaration,
01100                                                        XMLUni::fgXMLErrDomain, typeInfoLocator, elemName, 0, 0, 0, fMemoryManager);
01101                     }
01102                 }
01103             }
01104         }
01105     }
01106 }
01107 
01108 // ---------------------------------------------------------------------------
01109 //  SchemaValidator: Particle Derivation Checking
01110 // ---------------------------------------------------------------------------
01111 void SchemaValidator::checkParticleDerivation(SchemaGrammar* const currentGrammar,
01112                                               const ComplexTypeInfo* const curTypeInfo) {
01113 
01114     ComplexTypeInfo* baseTypeInfo = 0;
01115     ContentSpecNode* curSpecNode = 0;
01116 
01117     if (curTypeInfo->getDerivedBy() == SchemaSymbols::XSD_RESTRICTION
01118         && ((baseTypeInfo = curTypeInfo->getBaseComplexTypeInfo()) != 0)
01119         && ((curSpecNode = curTypeInfo->getContentSpec()) != 0)) {
01120 
01121         try {
01122             checkParticleDerivationOk(currentGrammar, curSpecNode,
01123                                       curTypeInfo->getScopeDefined(),
01124                                       baseTypeInfo->getContentSpec(),
01125                                       baseTypeInfo->getScopeDefined(), baseTypeInfo);
01126         }
01127         catch (const XMLException& excep) {
01128             fSchemaErrorReporter.emitError(excep, curTypeInfo->getLocator());
01129         }
01130     }
01131 }
01132 
01133 ContentSpecNode* SchemaValidator::getNonUnaryGroup(ContentSpecNode* const pNode) {
01134 
01135     int pNodeType = (pNode->getType() & 0x0f);
01136     if (pNodeType == ContentSpecNode::Leaf
01137         || pNodeType == ContentSpecNode::Any
01138         || pNodeType == ContentSpecNode::Any_Other
01139         || pNodeType == ContentSpecNode::Any_NS)
01140         return pNode;
01141 
01142     if (pNode->getMinOccurs() == 1 && pNode->getMaxOccurs() == 1
01143         && pNode->getFirst() && !pNode->getSecond())
01144         return getNonUnaryGroup(pNode->getFirst());
01145 
01146     return pNode;
01147 }
01148 
01149 void SchemaValidator::checkParticleDerivationOk(SchemaGrammar* const aGrammar,
01150                                                 ContentSpecNode* const curNode,
01151                                                 const int derivedScope,
01152                                                 ContentSpecNode* const baseNode,
01153                                                 const int baseScope,
01154                                                 const ComplexTypeInfo* const baseInfo,
01155                                                 const bool toCheckOccurence) {
01156 
01157     // Check for pointless occurrences of all, choice, sequence.  The result is
01158     // the contentspec which is not pointless. If the result is a non-pointless
01159     // group, Vector is filled  in with the children of interest
01160     if (curNode && !baseNode)
01161         ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_EmptyBase, fMemoryManager);
01162 
01163     if (!curNode)
01164         return;
01165 
01166     ContentSpecNode* curSpecNode = getNonUnaryGroup(curNode);
01167     ContentSpecNode* baseSpecNode = getNonUnaryGroup(baseNode);
01168     ValueVectorOf<ContentSpecNode*> curVector(8, fMemoryManager);
01169     ValueVectorOf<ContentSpecNode*> baseVector(8, fMemoryManager);
01170     ContentSpecNode::NodeTypes curNodeType = curSpecNode->getType();
01171     ContentSpecNode::NodeTypes baseNodeType = baseSpecNode->getType();
01172 
01173     if ((curNodeType & 0x0f) == ContentSpecNode::Sequence ||
01174         (curNodeType & 0x0f) == ContentSpecNode::Choice ||
01175         curNodeType == ContentSpecNode::All) {
01176         curSpecNode = checkForPointlessOccurrences(curSpecNode, curNodeType, &curVector);
01177     }
01178 
01179     if ((baseNodeType & 0x0f) == ContentSpecNode::Sequence ||
01180         (baseNodeType & 0x0f) == ContentSpecNode::Choice ||
01181         baseNodeType == ContentSpecNode::All) {
01182         baseSpecNode = checkForPointlessOccurrences(baseSpecNode, baseNodeType, &baseVector);
01183     }
01184 
01185     curNodeType = curSpecNode->getType();
01186     baseNodeType = baseSpecNode->getType();
01187 
01188     switch (curNodeType & 0x0f) {
01189     case ContentSpecNode::Leaf:
01190         {
01191             switch (baseNodeType & 0x0f) {
01192             case ContentSpecNode::Leaf:
01193                 {
01194                     checkNameAndTypeOK(aGrammar, curSpecNode, derivedScope, baseSpecNode, baseScope, baseInfo);
01195                     return;
01196                 }
01197             case ContentSpecNode::Any:
01198             case ContentSpecNode::Any_Other:
01199             case ContentSpecNode::Any_NS:
01200                 {
01201                     checkNSCompat(curSpecNode, baseSpecNode, toCheckOccurence);
01202                     return;
01203                 }
01204             case ContentSpecNode::Choice:
01205             case ContentSpecNode::Sequence:
01206             case ContentSpecNode::All:
01207                 {
01208                     checkRecurseAsIfGroup(aGrammar, curSpecNode, derivedScope,
01209                                           baseSpecNode, baseScope, &baseVector, baseInfo);
01210                     return;
01211                 }
01212             default:
01213                 {
01214                     ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_InvalidContentType, fMemoryManager);
01215                 }
01216             }
01217         }
01218     case ContentSpecNode::Any:
01219     case ContentSpecNode::Any_Other:
01220     case ContentSpecNode::Any_NS:
01221         {
01222             switch (baseNodeType & 0x0f) {
01223             case ContentSpecNode::Any:
01224             case ContentSpecNode::Any_Other:
01225             case ContentSpecNode::Any_NS:
01226                 {
01227                      checkNSSubset(curSpecNode, baseSpecNode);
01228                      return;
01229                 }
01230             case ContentSpecNode::Choice:
01231             case ContentSpecNode::Sequence:
01232             case ContentSpecNode::All:
01233             case ContentSpecNode::Leaf:
01234                 {
01235                     if (baseNodeType == ContentSpecNode::Any_NS_Choice) {
01236                         if (checkNSSubsetChoiceRoot(curSpecNode, baseSpecNode)) {
01237                             return;
01238                         }
01239                     }
01240 
01241                     ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_ForbiddenRes1, fMemoryManager);
01242                 }
01243             default:
01244                 {
01245                     ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_InvalidContentType, fMemoryManager);
01246                 }
01247             }
01248         }
01249     case ContentSpecNode::All:
01250         {
01251             switch (baseNodeType & 0x0f) {
01252             case ContentSpecNode::Any:
01253             case ContentSpecNode::Any_Other:
01254             case ContentSpecNode::Any_NS:
01255                 {
01256                     checkNSRecurseCheckCardinality(aGrammar, curSpecNode, &curVector, derivedScope, baseSpecNode, toCheckOccurence);
01257                     return;
01258                 }
01259             case ContentSpecNode::All:
01260                 {
01261                     checkRecurse(aGrammar, curSpecNode, derivedScope, &curVector,
01262                                  baseSpecNode, baseScope, &baseVector, baseInfo);
01263                     return;
01264                 }
01265             case ContentSpecNode::Choice:
01266             case ContentSpecNode::Sequence:
01267             case ContentSpecNode::Leaf:
01268                 {
01269                     ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_ForbiddenRes2, fMemoryManager);
01270                 }
01271             default:
01272                 {
01273                     ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_InvalidContentType, fMemoryManager);
01274                 }
01275             }
01276         }
01277     case ContentSpecNode::Choice:
01278         {
01279             switch (baseNodeType & 0x0f) {
01280             case ContentSpecNode::Any:
01281             case ContentSpecNode::Any_Other:
01282             case ContentSpecNode::Any_NS:
01283                 {
01284                     checkNSRecurseCheckCardinality(aGrammar, curSpecNode, &curVector, derivedScope, baseSpecNode, toCheckOccurence);
01285                     return;
01286                 }
01287             case ContentSpecNode::Choice:
01288                 {
01289                     checkRecurse(aGrammar, curSpecNode, derivedScope, &curVector,
01290                                  baseSpecNode, baseScope, &baseVector, baseInfo, true);
01291                     return;
01292                 }
01293             case ContentSpecNode::All:
01294             case ContentSpecNode::Sequence:
01295             case ContentSpecNode::Leaf:
01296                 {
01297                     ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_ForbiddenRes3, fMemoryManager);
01298                 }
01299             default:
01300                 {
01301                     ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_InvalidContentType, fMemoryManager);
01302                 }
01303             }
01304         }
01305     case ContentSpecNode::Sequence:
01306         {
01307             switch (baseNodeType & 0x0f) {
01308             case ContentSpecNode::Any:
01309             case ContentSpecNode::Any_Other:
01310             case ContentSpecNode::Any_NS:
01311                 {
01312                     checkNSRecurseCheckCardinality(aGrammar, curSpecNode, &curVector, derivedScope, baseSpecNode, toCheckOccurence);
01313                     return;
01314                 }
01315             case ContentSpecNode::All:
01316                 {
01317                     checkRecurseUnordered(aGrammar, curSpecNode, &curVector, derivedScope,
01318                                           baseSpecNode, &baseVector, baseScope, baseInfo);
01319                     return;
01320                 }
01321             case ContentSpecNode::Sequence:
01322                 {
01323                     checkRecurse(aGrammar, curSpecNode, derivedScope, &curVector,
01324                                  baseSpecNode, baseScope, &baseVector, baseInfo);
01325                     return;
01326                 }
01327             case ContentSpecNode::Choice:
01328                 {
01329                     checkMapAndSum(aGrammar, curSpecNode, &curVector, derivedScope,
01330                                    baseSpecNode, &baseVector, baseScope, baseInfo);
01331                     return;
01332                 }
01333             case ContentSpecNode::Leaf:
01334                 {
01335                     ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_ForbiddenRes4, fMemoryManager);
01336                 }
01337             default:
01338                 {
01339                     ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_InvalidContentType, fMemoryManager);
01340                 }
01341             }
01342         }
01343     }
01344 }
01345 
01346 ContentSpecNode*
01347 SchemaValidator::checkForPointlessOccurrences(ContentSpecNode* const specNode,
01348                                               const ContentSpecNode::NodeTypes nodeType,
01349                                               ValueVectorOf<ContentSpecNode*>* const nodes) {
01350 
01351     ContentSpecNode* rightNode = specNode->getSecond();
01352     int min = specNode->getMinOccurs();
01353     int max = specNode->getMaxOccurs();
01354 
01355     if (!rightNode) {
01356 
01357          gatherChildren(nodeType, specNode->getFirst(), nodes);
01358 
01359          if (nodes->size() == 1 && min == 1 && max == 1) {
01360             return nodes->elementAt(0);
01361         }
01362 
01363         return specNode;
01364     }
01365 
01366     gatherChildren(nodeType, specNode->getFirst(), nodes);
01367     gatherChildren(nodeType, rightNode, nodes);
01368 
01369     return specNode;
01370 }
01371 
01372 void SchemaValidator::gatherChildren(const ContentSpecNode::NodeTypes parentNodeType,
01373                                     ContentSpecNode* const specNode,
01374                                     ValueVectorOf<ContentSpecNode*>* const nodes) {
01375 
01376     if (!specNode) {
01377         return;
01378     }
01379 
01380     int min = specNode->getMinOccurs();
01381     int max = specNode->getMaxOccurs();
01382     ContentSpecNode::NodeTypes nodeType = specNode->getType();
01383     ContentSpecNode* rightNode = specNode->getSecond();
01384 
01385     if (nodeType == ContentSpecNode::Leaf ||
01386         (nodeType & 0x0f) == ContentSpecNode::Any ||
01387         (nodeType & 0x0f) == ContentSpecNode::Any_NS ||
01388         (nodeType & 0x0f) == ContentSpecNode::Any_Other) {
01389         nodes->addElement(specNode);
01390     }
01391     else if (min !=1 || max != 1) {
01392         nodes->addElement(specNode);
01393     }
01394     else if (!rightNode) {
01395         gatherChildren(nodeType, specNode->getFirst(), nodes);
01396     }
01397     else if ((parentNodeType & 0x0f) == (nodeType & 0x0f)) {
01398 
01399         gatherChildren(nodeType, specNode->getFirst(), nodes);
01400         gatherChildren(nodeType, rightNode, nodes);
01401     }
01402     else {
01403         nodes->addElement(specNode);
01404     }
01405 }
01406 
01407 void
01408 SchemaValidator::checkNSCompat(const ContentSpecNode* const derivedSpecNode,
01409                                const ContentSpecNode* const baseSpecNode,
01410                                const bool toCheckOccurence) {
01411 
01412     // check Occurrence ranges
01413     if (toCheckOccurence &&
01414         !isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(),
01415                              baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) {
01416         ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_OccurRangeE,
01417                   derivedSpecNode->getElement()->getLocalPart(), fMemoryManager);
01418     }
01419 
01420     // check wildcard subset
01421     if (!wildcardEltAllowsNamespace(baseSpecNode, derivedSpecNode->getElement()->getURI())) {
01422         ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NSCompat1,
01423                   derivedSpecNode->getElement()->getLocalPart(), fMemoryManager);
01424     }
01425 }
01426 
01427 bool
01428 SchemaValidator::wildcardEltAllowsNamespace(const ContentSpecNode* const baseSpecNode,
01429                                             const unsigned int derivedURI) {
01430 
01431     ContentSpecNode::NodeTypes nodeType = baseSpecNode->getType();
01432 
01433     if ((nodeType & 0x0f) == ContentSpecNode::Any) {
01434         return true;
01435     }
01436 
01437     unsigned int baseURI = baseSpecNode->getElement()->getURI();
01438 
01439     if ((nodeType & 0x0f) == ContentSpecNode::Any_NS) {
01440         if (derivedURI == baseURI) {
01441            return true;
01442         }
01443     }
01444     else { // must be ANY_OTHER
01445         if (derivedURI != baseURI && derivedURI != getScanner()->getEmptyNamespaceId()) {
01446             return true;
01447         }
01448     }
01449 
01450     return false;
01451 }
01452 
01453 void
01454 SchemaValidator::checkNameAndTypeOK(SchemaGrammar* const currentGrammar,
01455                                     const ContentSpecNode* const derivedSpecNode,
01456                                     const int derivedScope,
01457                                     const ContentSpecNode* const baseSpecNode,
01458                                     const int baseScope,
01459                                     const ComplexTypeInfo* const baseInfo) {
01460 
01461     if (derivedSpecNode->getMaxOccurs() == 0)
01462         return;
01463 
01464     unsigned int derivedURI = derivedSpecNode->getElement()->getURI();
01465 
01466     // case of mixed complex types with attributes only
01467     if (derivedURI == XMLElementDecl::fgPCDataElemId) {
01468         return;
01469     }
01470 
01471     SchemaGrammar* dGrammar = currentGrammar;
01472 
01473     if (derivedURI != getScanner()->getEmptyNamespaceId())
01474     {
01475         const XMLCh* dURI = fGrammarResolver->getStringPool()->getValueForId(derivedURI);
01476         dGrammar= (SchemaGrammar*) fGrammarResolver->getGrammar(dURI);
01477     }
01478 
01479     if (!dGrammar) { //something is wrong
01480         return;
01481     }
01482 
01483     const XMLCh* derivedName = derivedSpecNode->getElement()->getLocalPart();
01484 
01485     SchemaElementDecl* derivedElemDecl = findElement(derivedScope, derivedURI, derivedName, dGrammar);
01486 
01487     if (!derivedElemDecl) {
01488         return;
01489     }
01490 
01491     const XMLCh* baseName = baseSpecNode->getElement()->getLocalPart();
01492     unsigned int baseURI = baseSpecNode->getElement()->getURI();
01493     bool subsGroup = false;
01494 
01495     if (!XMLString::equals(derivedName, baseName) || derivedURI != baseURI) {
01496         // Check if derived is substitutable for base.
01497         //
01498         SchemaElementDecl* e = derivedElemDecl->getSubstitutionGroupElem ();
01499 
01500         for (; e != 0; e = e->getSubstitutionGroupElem ()) {
01501             if (XMLString::equals(e->getBaseName (), baseName) && e->getURI () == baseURI) {
01502                 break;
01503             }
01504         }
01505 
01506         if (e == 0) {
01507             ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_NameTypeOK1, fMemoryManager);
01508         }
01509 
01510         subsGroup = true;
01511     }
01512 
01513     if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(),
01514                              baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) {
01515         ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_OccurRangeE, derivedName, fMemoryManager);
01516     }
01517 
01518     // Find the schema grammar for the base element using the base type as
01519     // a reference if it is available (it is unavailable if we are checking
01520     // element group restriction which happens in redefine).
01521     //
01522     SchemaGrammar* bGrammar = dGrammar;
01523 
01524     if (baseInfo)
01525     {
01526         const XMLCh* baseTypeURI = baseInfo->getTypeUri ();
01527 
01528         if (baseTypeURI != 0 && *baseTypeURI != 0) // Non-empty namespace.
01529             bGrammar= (SchemaGrammar*) fGrammarResolver->getGrammar(baseTypeURI);
01530 
01531         if (!bGrammar) { //something is wrong
01532             return;
01533         }
01534     }
01535 
01536     SchemaElementDecl* baseElemDecl =
01537         findElement(baseScope, baseURI, baseName, bGrammar, baseInfo);
01538 
01539     if (!baseElemDecl) {
01540         return;
01541     }
01542 
01543     int derivedFlags = derivedElemDecl->getMiscFlags();
01544     int baseFlags = baseElemDecl->getMiscFlags();
01545 
01546     if (((baseFlags & SchemaSymbols::XSD_NILLABLE) == 0) &&
01547                 ((derivedFlags & SchemaSymbols::XSD_NILLABLE) != 0)) {
01548         ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK2, derivedName, fMemoryManager);
01549     }
01550 
01551     const XMLCh* derivedDefVal = derivedElemDecl->getDefaultValue();
01552     const XMLCh* baseDefVal = baseElemDecl->getDefaultValue();
01553 
01554     if (baseDefVal && (baseFlags & SchemaSymbols::XSD_FIXED) != 0 &&
01555         ((derivedFlags & SchemaSymbols::XSD_FIXED) == 0 ||
01556          !XMLString::equals(derivedDefVal, baseDefVal))) {
01557         ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK3, derivedName, fMemoryManager);
01558     }
01559 
01560     int derivedBlockSet = derivedElemDecl->getBlockSet();
01561     int baseBlockSet = baseElemDecl->getBlockSet();
01562 
01563     if ((derivedBlockSet & baseBlockSet) != baseBlockSet) {
01564         ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK4, derivedName, fMemoryManager);
01565     }
01566 
01567     // check identity constraints
01568     checkICRestriction(derivedElemDecl, baseElemDecl, derivedName, baseName);
01569 
01570     // check that the derived element's type is derived from the base's.
01571     if (!subsGroup)
01572         checkTypesOK(derivedElemDecl, baseElemDecl, derivedName);
01573 }
01574 
01575 SchemaElementDecl*
01576 SchemaValidator::findElement(const int scope, const unsigned int uriIndex,
01577                              const XMLCh* const name,
01578                              SchemaGrammar* const grammar,
01579                              const ComplexTypeInfo* const typeInfo) {
01580 
01581     // check for element at given scope first
01582     SchemaElementDecl* elemDecl = (SchemaElementDecl*) grammar->getElemDecl(uriIndex, name, 0, scope);
01583 
01584     // if not found, check at global scope
01585     if (!elemDecl) {
01586 
01587         elemDecl = (SchemaElementDecl*)
01588             grammar->getElemDecl(uriIndex, name, 0, Grammar::TOP_LEVEL_SCOPE);
01589 
01590         // if still not found, and base is specified, look it up there
01591         if (!elemDecl && typeInfo) {
01592 
01593             const ComplexTypeInfo* baseInfo = typeInfo;
01594 
01595             while (baseInfo) {
01596 
01597                 elemDecl = (SchemaElementDecl*)
01598                     grammar->getElemDecl(uriIndex, name, 0, baseInfo->getScopeDefined());
01599 
01600                 if (elemDecl) {
01601                    break;
01602                 }
01603 
01604                 baseInfo = baseInfo->getBaseComplexTypeInfo();
01605             }
01606         }
01607     }
01608 
01609     return elemDecl;
01610 }
01611 
01612 void
01613 SchemaValidator::checkICRestriction(const SchemaElementDecl* const derivedElemDecl,
01614                                    const SchemaElementDecl* const baseElemDecl,
01615                                    const XMLCh* const derivedElemName,
01616                                    const XMLCh* const baseElemName) {
01617 
01618     // REVIST - need to get more clarification
01619     XMLSize_t derivedICCount = derivedElemDecl->getIdentityConstraintCount();
01620     XMLSize_t baseICCount = baseElemDecl->getIdentityConstraintCount();
01621 
01622     if (derivedICCount > baseICCount) {
01623         ThrowXMLwithMemMgr2(RuntimeException, XMLExcepts::PD_NameTypeOK6, derivedElemName, baseElemName, fMemoryManager);
01624     }
01625 
01626     for (XMLSize_t i=0; i < derivedICCount; i++) {
01627 
01628         bool found = false;
01629         IdentityConstraint* ic= derivedElemDecl->getIdentityConstraintAt(i);
01630 
01631         for (XMLSize_t j=0; j < baseICCount; j++) {
01632             if (*ic == *(baseElemDecl->getIdentityConstraintAt(j))) {
01633 
01634                 found = true;
01635                 break;
01636             }
01637         }
01638 
01639         if (!found) {
01640             ThrowXMLwithMemMgr2(RuntimeException, XMLExcepts::PD_NameTypeOK7, derivedElemName, baseElemName, fMemoryManager);
01641         }
01642     }
01643 }
01644 
01645 void
01646 SchemaValidator::checkTypesOK(const SchemaElementDecl* const derivedElemDecl,
01647                               const SchemaElementDecl* const baseElemDecl,
01648                               const XMLCh* const derivedElemName) {
01649 
01650     SchemaElementDecl::ModelTypes baseType = baseElemDecl->getModelType();
01651 
01652     if (baseType == SchemaElementDecl::Any) {
01653         return;
01654     }
01655 
01656     ComplexTypeInfo* rInfo = derivedElemDecl->getComplexTypeInfo();
01657     ComplexTypeInfo* bInfo = baseElemDecl->getComplexTypeInfo();
01658 
01659     if (derivedElemDecl->getModelType() == SchemaElementDecl::Simple) {
01660 
01661         if (baseType != SchemaElementDecl::Simple) {
01662             ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK5, derivedElemName, fMemoryManager);
01663         }
01664 
01665         if (!rInfo) {
01666 
01667             DatatypeValidator* bDV = baseElemDecl->getDatatypeValidator();
01668 
01669             if (bInfo || bDV == 0 ||
01670                                 !bDV->isSubstitutableBy(derivedElemDecl->getDatatypeValidator())) {
01671                 ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK5, derivedElemName, fMemoryManager);
01672             }
01673 
01674             return;
01675         }
01676     }
01677 
01678     if (rInfo == bInfo)
01679         return;
01680 
01681     for (; rInfo && rInfo != bInfo; rInfo = rInfo->getBaseComplexTypeInfo()) {
01682         if (rInfo->getDerivedBy() != SchemaSymbols::XSD_RESTRICTION) {
01683 
01684             rInfo = 0;
01685             break;
01686         }
01687     }
01688 
01689     if (!rInfo) {
01690         ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK5, derivedElemName, fMemoryManager);
01691     }
01692 }
01693 
01694 void
01695 SchemaValidator::checkRecurseAsIfGroup(SchemaGrammar* const currentGrammar,
01696                                        ContentSpecNode* const derivedSpecNodeIn,
01697                                        const int derivedScope,
01698                                        const ContentSpecNode* const baseSpecNode,
01699                                        const int baseScope,
01700                                        ValueVectorOf<ContentSpecNode*>* const baseNodes,
01701                                        const ComplexTypeInfo* const baseInfo) {
01702 
01703     ContentSpecNode::NodeTypes baseType = baseSpecNode->getType();
01704     bool toLax = false;
01705 
01706     //Treat the element as if it were in a group of the same variety as base
01707     ContentSpecNode derivedGroupNode(baseType, derivedSpecNodeIn, 0, false, true, fMemoryManager);
01708     const ContentSpecNode* const derivedSpecNode = &derivedGroupNode;
01709 
01710     if ((baseSpecNode->getType() & 0x0f) == ContentSpecNode::Choice) {
01711         toLax = true;
01712     }
01713 
01714     // Instead of calling this routine, inline it
01715     // checkRecurse(currentGrammar, &derivedGroupNode, derivedScope, &derivedNodes,
01716     //             baseSpecNode, baseScope, baseNodes, baseInfo, toLax);
01717 
01718     if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(),
01719                              baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) {
01720         ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_Recurse1, fMemoryManager);
01721     }
01722 
01723     // check for mapping of children
01724     XMLExcepts::Codes codeToThrow = XMLExcepts::NoError;
01725     XMLSize_t count2= baseNodes->size();
01726     XMLSize_t current = 0;
01727 
01728     {
01729         bool matched = false;
01730 
01731         for (XMLSize_t j = current; j < count2; j++) {
01732 
01733             ContentSpecNode* baseNode = baseNodes->elementAt(j);
01734             current++;
01735 
01736             bool bDoBreak=false;    // workaround for Borland bug with 'break' in 'catch'
01737             try {
01738 
01739                 checkParticleDerivationOk(currentGrammar, derivedSpecNodeIn,
01740                                           derivedScope, baseNode, baseScope, baseInfo);
01741                 matched = true;
01742                 break;
01743             }
01744             catch(const XMLException&) {
01745                 if (!toLax && baseNode->getMinTotalRange()) {
01746                     bDoBreak=true;
01747                 }
01748             }
01749             if(bDoBreak)
01750                 break;
01751         }
01752 
01753         // did not find a match
01754         if (!matched) {
01755             codeToThrow = XMLExcepts::PD_Recurse2;
01756         }
01757     }
01758 
01759     // Now, see if there are some elements in the base we didn't match up
01760     // in case of Sequence or All
01761     if (!toLax && codeToThrow == XMLExcepts::NoError) {
01762         for (XMLSize_t j = current; j < count2; j++) {
01763             if (baseNodes->elementAt(j)->getMinTotalRange() * baseSpecNode->getMinOccurs()) { 
01764                 codeToThrow =  XMLExcepts::PD_Recurse2;
01765                 break;
01766             }
01767         }
01768     }
01769 
01770     if (codeToThrow != XMLExcepts::NoError) {
01771         ThrowXMLwithMemMgr(RuntimeException, codeToThrow, fMemoryManager);
01772     }
01773 }
01774 
01775 void
01776 SchemaValidator::checkRecurse(SchemaGrammar* const currentGrammar,
01777                               const ContentSpecNode* const derivedSpecNode,
01778                               const int derivedScope,
01779                               ValueVectorOf<ContentSpecNode*>* const derivedNodes,
01780                               const ContentSpecNode* const baseSpecNode,
01781                               const int baseScope,
01782                               ValueVectorOf<ContentSpecNode*>* const baseNodes,
01783                               const ComplexTypeInfo* const baseInfo,
01784                               const bool toLax) {
01785 
01786     if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(),
01787                              baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) {
01788         ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_Recurse1, fMemoryManager);
01789     }
01790 
01791     // check for mapping of children
01792     XMLExcepts::Codes codeToThrow = XMLExcepts::NoError;
01793     XMLSize_t count1= derivedNodes->size();
01794     XMLSize_t count2= baseNodes->size();
01795     XMLSize_t current = 0;
01796 
01797     for (XMLSize_t i=0; i<count1; i++) {
01798 
01799         bool matched = false;
01800 
01801         for (XMLSize_t j = current; j < count2; j++) {
01802 
01803             ContentSpecNode* baseNode = baseNodes->elementAt(j);
01804             current++;
01805 
01806             bool bDoBreak=false;    // workaround for Borland bug with 'break' in 'catch'
01807             try {
01808 
01809                 checkParticleDerivationOk(currentGrammar, derivedNodes->elementAt(i),
01810                                           derivedScope, baseNode, baseScope, baseInfo);
01811                 matched = true;
01812                 break;
01813             }
01814             catch(const XMLException&) {
01815                 if (!toLax && baseNode->getMinTotalRange()) {
01816                     bDoBreak=true;
01817                 }
01818             }
01819             if(bDoBreak)
01820                 break;
01821         }
01822 
01823         // did not find a match
01824         if (!matched) {
01825 
01826             codeToThrow = XMLExcepts::PD_Recurse2;
01827             break;
01828         }
01829     }
01830 
01831     // Now, see if there are some elements in the base we didn't match up
01832     // in case of Sequence or All
01833     if (!toLax && codeToThrow == XMLExcepts::NoError) {
01834         for (XMLSize_t j = current; j < count2; j++) {
01835             if (baseNodes->elementAt(j)->getMinTotalRange()) { 
01836                 codeToThrow =  XMLExcepts::PD_Recurse2;
01837                 break;
01838             }
01839         }
01840     }
01841 
01842     if (codeToThrow != XMLExcepts::NoError) {
01843         ThrowXMLwithMemMgr(RuntimeException, codeToThrow, fMemoryManager);
01844     }
01845 }
01846 
01847 void SchemaValidator::checkNSSubset(const ContentSpecNode* const derivedSpecNode,
01848                                     const ContentSpecNode* const baseSpecNode) {
01849 
01850     // check Occurrence ranges
01851     if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(),
01852                              baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) {
01853         ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_NSSubset1, fMemoryManager);
01854     }
01855 
01856     if (!isWildCardEltSubset(derivedSpecNode, baseSpecNode)) {
01857         ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_NSSubset2, fMemoryManager);
01858     }
01859 }
01860 
01861 bool SchemaValidator::checkNSSubsetChoiceRoot(const ContentSpecNode* const derivedSpecNode,
01862                                     const ContentSpecNode* const baseSpecNode) {
01863     bool found = false;
01864 
01865     if (baseSpecNode->getType() == ContentSpecNode::Any_NS_Choice) {
01866         const ContentSpecNode* first = baseSpecNode->getFirst();
01867         const ContentSpecNode* second = baseSpecNode->getSecond();
01868 
01869         if (first) {
01870             found = checkNSSubsetChoiceRoot(derivedSpecNode, first);
01871             if (found) return true;
01872         }
01873         if (second) {
01874             found = checkNSSubsetChoiceRoot(derivedSpecNode, second);
01875             if (found) return true;
01876         }
01877     }
01878     else { // should be Any_NS
01879         found = checkNSSubsetChoice(derivedSpecNode, baseSpecNode);
01880     }
01881 
01882     return found;
01883 }
01884 
01885 bool SchemaValidator::checkNSSubsetChoice(const ContentSpecNode* const derivedSpecNode,
01886                                     const ContentSpecNode* const baseSpecNode) {
01887 
01888     // check Occurrence ranges
01889     if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(),
01890                              baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) {
01891         return false;
01892     }
01893 
01894     if (!isWildCardEltSubset(derivedSpecNode, baseSpecNode)) {
01895         return false;
01896     }
01897     return true;
01898 }
01899 
01900 bool
01901 SchemaValidator::isWildCardEltSubset(const ContentSpecNode* const derivedSpecNode,
01902                                      const ContentSpecNode* const baseSpecNode) {
01903 
01904     ContentSpecNode::NodeTypes baseType = baseSpecNode->getType();
01905 
01906     if ((baseType & 0x0f) == ContentSpecNode::Any) {
01907         return true;
01908     }
01909 
01910     ContentSpecNode::NodeTypes derivedType = derivedSpecNode->getType();
01911     unsigned int baseURI = baseSpecNode->getElement()->getURI();
01912     unsigned int derivedURI = derivedSpecNode->getElement()->getURI();
01913 
01914     // Below we assume that empty string has id 1.
01915     //
01916     if (((derivedType & 0x0f) == ContentSpecNode::Any_Other) &&
01917         ((baseType & 0x0f) == ContentSpecNode::Any_Other) &&
01918         (baseURI == derivedURI || baseURI == 1)) {
01919         return true;
01920     }
01921 
01922     if ((derivedType & 0x0f) == ContentSpecNode::Any_NS) {
01923 
01924         if (((baseType & 0x0f) == ContentSpecNode::Any_NS) &&
01925             baseURI == derivedURI) {
01926             return true;
01927         }
01928 
01929         if (((baseType & 0x0f) == ContentSpecNode::Any_Other) &&
01930             (derivedURI == 1 || baseURI != derivedURI)) {
01931             return true;
01932         }
01933     }
01934 
01935     return false;
01936 }
01937 
01938 void
01939 SchemaValidator::checkNSRecurseCheckCardinality(SchemaGrammar* const currentGrammar,
01940                                                 const ContentSpecNode* const derivedSpecNode,
01941                                                 ValueVectorOf<ContentSpecNode*>* const derivedNodes,
01942                                                 const int derivedScope,
01943                                                 ContentSpecNode* const baseSpecNode,
01944                                                 const bool toCheckOccurence) {
01945 
01946     // Implement total range check
01947     int derivedMin = derivedSpecNode->getMinTotalRange();
01948     int derivedMax = derivedSpecNode->getMaxTotalRange();
01949 
01950     // check Occurrence ranges
01951     if (toCheckOccurence &&
01952         !isOccurrenceRangeOK(derivedMin, derivedMax, baseSpecNode->getMinOccurs(),
01953                               baseSpecNode->getMaxOccurs())) {
01954         ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_NSRecurseCheckCardinality1, fMemoryManager);
01955     }
01956 
01957     // Check that each member of the group is a valid restriction of the wildcard
01958     XMLSize_t nodesCount = derivedNodes->size();
01959 
01960     for (XMLSize_t i = 0; i < nodesCount; i++) {
01961         checkParticleDerivationOk(currentGrammar, derivedNodes->elementAt(i), derivedScope, baseSpecNode, -1, 0, false);
01962     }
01963 }
01964 
01965 void
01966 SchemaValidator::checkRecurseUnordered(SchemaGrammar* const currentGrammar,
01967                                        const ContentSpecNode* const derivedSpecNode,
01968                                        ValueVectorOf<ContentSpecNode*>* const derivedNodes,
01969                                        const int derivedScope,
01970                                        ContentSpecNode* const baseSpecNode,
01971                                        ValueVectorOf<ContentSpecNode*>* const baseNodes,
01972                                        const int baseScope,
01973                                        const ComplexTypeInfo* const baseInfo) {
01974 
01975     // check Occurrence ranges
01976     if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(),
01977                              baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) {
01978         ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_Recurse1, fMemoryManager);
01979     }
01980 
01981     XMLExcepts::Codes  codeToThrow = XMLExcepts::NoError;
01982     XMLSize_t          derivedCount= derivedNodes->size();
01983     XMLSize_t          baseCount = baseNodes->size();
01984     bool*              foundIt = (bool*) fMemoryManager->allocate
01985     (
01986         baseCount * sizeof(bool)
01987     );//new bool[baseCount];
01988     ArrayJanitor<bool> janFoundIt(foundIt, fMemoryManager);
01989 
01990     for (XMLSize_t k=0; k < baseCount; k++) {
01991         foundIt[k] = false;
01992     }
01993 
01994     // check for mapping of children
01995     for (XMLSize_t i = 0; i < derivedCount; i++) {
01996 
01997         ContentSpecNode* derivedNode = derivedNodes->elementAt(i);
01998         bool matched = false;
01999 
02000         for (XMLSize_t j = 0; j < baseCount; j++) {
02001 
02002             try {
02003 
02004                 checkParticleDerivationOk(currentGrammar, derivedNode, derivedScope,
02005                                           baseNodes->elementAt(j), baseScope, baseInfo);
02006 
02007                 if (foundIt[j]) {
02008                     break;
02009                 }
02010 
02011                 foundIt[j] = true;
02012                 matched = true;
02013                 break;
02014             }
02015             catch (const XMLException&) {
02016             }
02017         }
02018 
02019         // didn't find a match.
02020         if (!matched) {
02021 
02022                 codeToThrow = XMLExcepts::PD_RecurseUnordered;
02023             break;
02024         }
02025     }
02026 
02027     // For all unmapped particles in base, check to see it it's emptiable or not
02028     if (codeToThrow == XMLExcepts::NoError) {
02029         for (XMLSize_t j=0; j < baseCount; j++) {
02030             if (!foundIt[j] && baseNodes->elementAt(j)->getMinTotalRange()) {
02031 
02032                     codeToThrow = XMLExcepts::PD_RecurseUnordered;
02033                 break;
02034             }
02035         }
02036     }
02037 
02038     if (codeToThrow != XMLExcepts::NoError) {
02039         ThrowXMLwithMemMgr(RuntimeException, codeToThrow, fMemoryManager);
02040     }
02041 }
02042 
02043 void
02044 SchemaValidator::checkMapAndSum(SchemaGrammar* const currentGrammar,
02045                                 const ContentSpecNode* const derivedSpecNode,
02046                                 ValueVectorOf<ContentSpecNode*>* const derivedNodes,
02047                                 const int derivedScope,
02048                                 ContentSpecNode* const baseSpecNode,
02049                                 ValueVectorOf<ContentSpecNode*>* const baseNodes,
02050                                 const int baseScope,
02051                                 const ComplexTypeInfo* const baseInfo) {
02052 
02053     // check Occurrence ranges
02054     XMLSize_t derivedCount = derivedNodes->size();
02055     XMLSize_t baseCount = baseNodes->size();
02056     int derivedMin = derivedSpecNode->getMinOccurs() * (unsigned int)derivedCount;
02057     int derivedMax = derivedSpecNode->getMaxOccurs();
02058 
02059     if (derivedMax != SchemaSymbols::XSD_UNBOUNDED) {
02060         derivedMax *= (unsigned int)derivedCount;
02061     }
02062 
02063     if (!isOccurrenceRangeOK(derivedMin, derivedMax, baseSpecNode->getMinOccurs(),
02064                              baseSpecNode->getMaxOccurs())) {
02065         ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_Recurse1, fMemoryManager);
02066     }
02067 
02068     // check for mapping of children
02069     for (XMLSize_t i = 0; i < derivedCount; i++) {
02070 
02071         ContentSpecNode* derivedNode = derivedNodes->elementAt(i);
02072         bool matched = false;
02073 
02074         for (XMLSize_t j = 0; j < baseCount && !matched; j++) {
02075 
02076             try {
02077 
02078                 checkParticleDerivationOk(currentGrammar, derivedNode, derivedScope,
02079                                           baseNodes->elementAt(j), baseScope, baseInfo);
02080                 matched = true;
02081             }
02082             catch (const XMLException&) {
02083             }
02084         }
02085 
02086         // didn't find a match.
02087         if (!matched) {
02088                 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_MapAndSum, fMemoryManager);
02089         }
02090     }
02091 
02092 }
02093 
02094 XERCES_CPP_NAMESPACE_END