Ignore:
Timestamp:
Dec 4, 2012, 6:02:04 PM (6 years ago)
Author:
cameron
Message:

Script for generating link files.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • icXML/icXML-devel/src/xercesc/validators/schema/SchemaValidator.cpp

    r2734 r2747  
    1 /*
    2  * Licensed to the Apache Software Foundation (ASF) under one or more
    3  * contributor license agreements.  See the NOTICE file distributed with
    4  * this work for additional information regarding copyright ownership.
    5  * The ASF licenses this file to You under the Apache License, Version 2.0
    6  * (the "License"); you may not use this file except in compliance with
    7  * the License.  You may obtain a copy of the License at
    8  *
    9  *      http://www.apache.org/licenses/LICENSE-2.0
    10  *
    11  * Unless required by applicable law or agreed to in writing, software
    12  * distributed under the License is distributed on an "AS IS" BASIS,
    13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  * See the License for the specific language governing permissions and
    15  * limitations under the License.
    16  */
    17 
    18 /*
    19  * $Id: SchemaValidator.cpp 806488 2009-08-21 10:36:58Z amassari $
    20  */
    21 
    22 // ---------------------------------------------------------------------------
    23 //  Includes
    24 // ---------------------------------------------------------------------------
    25 #include <xercesc/util/Janitor.hpp>
    26 #include <xercesc/framework/XMLDocumentHandler.hpp>
    27 #include <xercesc/framework/XMLSchemaDescription.hpp>
    28 #include <xercesc/framework/psvi/XSAnnotation.hpp>
    29 #include <icxercesc/internal/XMLReader.hpp>
    30 #include <icxercesc/internal/XMLScanner.hpp>
    31 #include <icxercesc/internal/ElemStack.hpp>
    32 #include <icxercesc/validators/datatype/DatatypeValidatorFactory.hpp>
    33 #include <xercesc/validators/datatype/ListDatatypeValidator.hpp>
    34 #include <xercesc/validators/datatype/UnionDatatypeValidator.hpp>
    35 #include <xercesc/validators/datatype/ENTITYDatatypeValidator.hpp>
    36 #include <xercesc/validators/datatype/IDDatatypeValidator.hpp>
    37 #include <xercesc/validators/datatype/IDREFDatatypeValidator.hpp>
    38 #include <icxercesc/validators/schema/SchemaSymbols.hpp>
    39 #include <icxercesc/validators/schema/SchemaValidator.hpp>
    40 #include <icxercesc/validators/schema/SubstitutionGroupComparator.hpp>
    41 #include <xercesc/validators/schema/XercesGroupInfo.hpp>
    42 #include <xercesc/validators/schema/XSDLocator.hpp>
    43 #include <xercesc/util/OutOfMemoryException.hpp>
    44 
    45 XERCES_CPP_NAMESPACE_BEGIN
    46 
    47 // ---------------------------------------------------------------------------
    48 //  SchemaValidator: Constructors and Destructor
    49 // ---------------------------------------------------------------------------
    50 SchemaValidator::SchemaValidator( XMLErrorReporter* const errReporter
    51                                 , MemoryManager* const    manager) :
    52 
    53     XMLValidator(errReporter)
    54     , fMemoryManager(manager)
    55     , fSchemaGrammar(0)
    56     , fGrammarResolver(0)
    57     , fXsiType(0)
    58     , fNil(false)
    59     , fNilFound(false)
    60     , fCurrentDatatypeValidator(0)
    61     , fNotationBuf(0)
    62     , fDatatypeBuffer(1023, manager)
    63     , fTrailing(false)
    64     , fSeenNonWhiteSpace(false)
    65     , fSeenId(false)
    66     , fTypeStack(0)
    67     , fMostRecentAttrValidator(0)
    68     , fErrorOccurred(false)
    69     , fElemIsSpecified(false)
    70 {
    71     fTypeStack = new (fMemoryManager) ValueStackOf<ComplexTypeInfo*>(8, fMemoryManager);
    72 }
    73 
    74 SchemaValidator::~SchemaValidator()
    75 {
    76     delete fXsiType;
    77     delete fTypeStack;
    78 
    79     if (fNotationBuf)
    80         delete fNotationBuf;
    81 }
    82 
    83 // ---------------------------------------------------------------------------
    84 //  SchemaValidator: Implementation of the XMLValidator interface
    85 // ---------------------------------------------------------------------------
    86 bool SchemaValidator::checkContent (XMLElementDecl* const elemDecl
    87                                  , QName** const          children
    88                                  , XMLSize_t              childCount
    89                                  , XMLSize_t*             indexFailingChild)
    90 {
    91     fErrorOccurred = false;
    92     fElemIsSpecified = false;
    93 
    94     //
    95     //  Look up the element id in our element decl pool. This will get us
    96     //  the element decl in our own way of looking at them.
    97     //
    98     if (!elemDecl)
    99         ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Val_InvalidElemId, fMemoryManager);
    100 
    101     //
    102     //  Get the content spec type of this element. This will tell us what
    103     //  to do to validate it.
    104     //
    105     // the top of the type stack always knows best...
    106     ComplexTypeInfo* currType = fTypeStack->pop();
    107 
    108     const SchemaElementDecl::ModelTypes modelType = (currType)
    109             ? (SchemaElementDecl::ModelTypes)(currType->getContentType())
    110             : ((SchemaElementDecl*)elemDecl)->getModelType();
    111 
    112     if (modelType == SchemaElementDecl::Empty  ||
    113         modelType == SchemaElementDecl::ElementOnlyEmpty)
    114     {
    115         //
    116         //  We can do this one here. It cannot have any children. If it does
    117         //  we return 0 as the index of the first bad child.
    118         //
    119         if (childCount) {
    120             fErrorOccurred = true;
    121             *indexFailingChild=0;
    122             return false;
    123         }
    124     }
    125     else if ((modelType == SchemaElementDecl::Mixed_Simple)
    126          ||  (modelType == SchemaElementDecl::Mixed_Complex)
    127          ||  (modelType == SchemaElementDecl::Children))
    128     {
    129         // if nillable, it's an error to have value
    130         // XML Schema REC: Validation Rule: Element Locally Valid (Element)
    131         // 3.2.1 The element information item must have no
    132         // character or element information item [children].
    133         //
    134         if (fNil) {
    135             if (childCount > 0 || !XMLString::equals(fDatatypeBuffer.getRawBuffer(), XMLUni::fgZeroLenString)) {
    136                 emitError(XMLValid::NilAttrNotEmpty, elemDecl->getFullName());
    137                 fErrorOccurred = true;
    138             }
    139         }
    140         else {
    141             // Get the element's content model or fault it in
    142             XMLContentModel* elemCM = (currType)
    143                     ? currType->getContentModel()
    144                     : ((SchemaElementDecl*)elemDecl)->getContentModel();
    145 
    146             // Ask it to validate and return its return
    147             unsigned int emptyNS = getScanner()->getEmptyNamespaceId();
    148             bool result = elemCM->validateContent(children, childCount, emptyNS, indexFailingChild, getScanner()->getMemoryManager());
    149             if (!result) {
    150                 result = elemCM->validateContentSpecial(children
    151                                                       , childCount
    152                                                       , emptyNS
    153                                                       , fGrammarResolver
    154                                                       , fGrammarResolver->getStringPool()
    155                                                       , indexFailingChild
    156                                                                                                           , getScanner()->getMemoryManager());
    157             }
    158 
    159             if(!result) {
    160                 fErrorOccurred = true;
    161             }
    162 
    163             return result;
    164         }
    165     }
    166     else if (modelType == SchemaElementDecl::Simple || modelType == SchemaElementDecl::Any)
    167     {
    168         // Normally for SchemaElementDecl::Any, We pass no judgement on it and anything goes
    169         // but if there is a fXsiTypeValidator, we need to use it for validation
    170         if (modelType == SchemaElementDecl::Simple && childCount > 0) {
    171             emitError(XMLValid::SimpleTypeHasChild, elemDecl->getFullName());
    172             fErrorOccurred = true;
    173         }
    174         else
    175         {
    176             XMLCh* value = fDatatypeBuffer.getRawBuffer();
    177             XMLCh* elemDefaultValue = ((SchemaElementDecl*) elemDecl)->getDefaultValue();
    178 
    179             if (fNil)
    180             {
    181                 if ((!XMLString::equals(value, XMLUni::fgZeroLenString))
    182                     || elemDefaultValue)
    183                 {
    184                     emitError(XMLValid::NilAttrNotEmpty, elemDecl->getFullName());
    185                     fErrorOccurred = true;
    186                 }
    187             }
    188                         else if (fCurrentDatatypeValidator)
    189             {
    190                 DatatypeValidator::ValidatorType eleDefDVType = fCurrentDatatypeValidator->getType();
    191                 bool validateCanonical = false;
    192                 if (eleDefDVType == DatatypeValidator::NOTATION)
    193                 {
    194                     // if notation, need to bind URI to notation first
    195                     if (!fNotationBuf)
    196                         fNotationBuf = new (fMemoryManager) XMLBuffer(1023, fMemoryManager);
    197 
    198                     //  Make sure that this value maps to one of the
    199                     //  notation values in the enumList parameter. We don't have to
    200                     //  look it up in the notation pool (if a notation) because we
    201                     //  will look up the enumerated values themselves. If they are in
    202                     //  the notation pool (after the Grammar is parsed), then obviously
    203                     //  this value will be legal since it matches one of them.
    204                     int colonPos = -1;
    205                     unsigned int uriId = getScanner()->resolveQName(value, *fNotationBuf, ElemStack::Mode_Element, colonPos);
    206 
    207                     const XMLCh* uriText = getScanner()->getURIText(uriId);
    208                     if (uriText && *uriText) {
    209                         fNotationBuf->set(uriText);
    210                         fNotationBuf->append(chColon);
    211                         fNotationBuf->append(&value[colonPos + 1]);
    212                         value = fNotationBuf->getRawBuffer();
    213                     }
    214                 }
    215 
    216                 if (elemDefaultValue)
    217                 {
    218                     if (XMLString::equals(value, XMLUni::fgZeroLenString))
    219                     {
    220                         fElemIsSpecified = true;
    221                         // if this element didn't specified any value
    222                         // use default value
    223                         if (getScanner()->getDocHandler())
    224                             getScanner()->getDocHandler()->docCharacters(elemDefaultValue, XMLString::stringLen(elemDefaultValue), false);
    225 
    226                         // Normally for default value, it has been validated already during TraverseSchema
    227                         // But if there was a xsi:type and this validator is fXsiTypeValidator,
    228                         // need to validate again
    229                         // we determine this if the current content dataype validator
    230                         // is neither the one in the element nor the one in the current
    231                         // complex type (if any)
    232                         if ((fCurrentDatatypeValidator != ((SchemaElementDecl*)elemDecl)->getDatatypeValidator())
    233                             && (!fTypeStack->peek() || (fCurrentDatatypeValidator != fTypeStack->peek()->getDatatypeValidator()))) {
    234                             value = elemDefaultValue;
    235                             validateCanonical = true;
    236                         }
    237                         else
    238                             value = 0;
    239                     }
    240                     else
    241                     {
    242                         // this element has specified some value
    243                         // if the flag is FIXED, then this value must be same as default value
    244                         if ((((SchemaElementDecl*)elemDecl)->getMiscFlags() & SchemaSymbols::XSD_FIXED) != 0)
    245                         {
    246                             if (fCurrentDatatypeValidator->compare(value, elemDefaultValue, fMemoryManager) != 0 )
    247                             {
    248                                 emitError(XMLValid::FixedDifferentFromActual, elemDecl->getFullName());
    249                                 fErrorOccurred = true;
    250                             }
    251                         }
    252                     }
    253                 }
    254 
    255                 if ((!fErrorOccurred) && value)
    256                 {
    257                     try {
    258                         fCurrentDatatypeValidator->validate(value, getScanner()->getValidationContext(), fMemoryManager);
    259                         if (validateCanonical) {
    260                             XMLCh* canonical = (XMLCh*) fCurrentDatatypeValidator->getCanonicalRepresentation(value, fMemoryManager);
    261                             ArrayJanitor<XMLCh> tempCanonical(canonical, fMemoryManager);
    262                             fCurrentDatatypeValidator->validate(canonical, getScanner()->getValidationContext(), fMemoryManager);
    263                         }
    264                     }
    265                     catch (XMLException& idve)
    266                     {
    267                         emitError (XMLValid::DatatypeError, idve.getCode(), idve.getMessage());
    268                         fErrorOccurred = true;
    269                     }
    270                     catch(const OutOfMemoryException&) {
    271                         throw;
    272                     }
    273                     catch (...)
    274                     {
    275                         emitError(XMLValid::GenericError);
    276                         throw;
    277                     }
    278                 }
    279             }
    280             else if (modelType == SchemaElementDecl::Simple)
    281             {
    282                 emitError(XMLValid::NoDatatypeValidatorForSimpleType, elemDecl->getFullName());
    283                 fErrorOccurred = true;
    284             }
    285             // modelType is any
    286             else if (elemDefaultValue)
    287             {
    288                 if (XMLString::equals(value, XMLUni::fgZeroLenString))
    289                 {
    290                     fElemIsSpecified = true;
    291                     // if this element didn't specified any value
    292                     // use default value
    293                     if (getScanner()->getDocHandler()) {
    294                         getScanner()->getDocHandler()->docCharacters(elemDefaultValue, XMLString::stringLen(elemDefaultValue), false);
    295                     }
    296                 }
    297             }
    298         }
    299     }
    300     else
    301     {
    302         ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_UnknownCMType, fMemoryManager);
    303     }
    304 
    305     // must rely on scanner to clear fDatatypeBuffer
    306     // since it may need to query its contents after this method completes
    307     fNil = false;
    308     fNilFound = false;
    309     fTrailing=false;
    310     fSeenNonWhiteSpace = false;
    311     fCurrentDatatypeValidator = 0;
    312 
    313     // Went ok, so return success
    314     return true;
    315 }
    316 
    317 void SchemaValidator::faultInAttr (XMLAttr&    toFill, const XMLAttDef&  attDef)   const
    318 {
    319     //
    320     //  At this level, we cannot set the URI id. So we just set it to zero
    321     //  and leave it at that. The scanner, who called us, will look at the
    322     //  prefix we stored (if any), resolve it, and store the URL id if any.
    323     //
    324     SchemaAttDef* schemaAttDef = (SchemaAttDef*) &attDef;
    325     QName* attName = schemaAttDef->getAttName();
    326 
    327     toFill.set
    328     (
    329           attName->getURI()
    330         , attName->getLocalPart()
    331         , attName->getPrefix()
    332         , schemaAttDef->getValue()
    333         , schemaAttDef->getType()
    334     );
    335 }
    336 
    337 void SchemaValidator::reset()
    338 {
    339     fTrailing = false;
    340     fSeenNonWhiteSpace = false;
    341     fSeenId = false;
    342         fTypeStack->removeAllElements();
    343     delete fXsiType;
    344     fXsiType = 0;
    345     fCurrentDatatypeValidator = 0;
    346     fNil = false;
    347     fNilFound = false;
    348     fDatatypeBuffer.reset();
    349     fErrorOccurred = false;
    350 }
    351 
    352 bool SchemaValidator::requiresNamespaces() const
    353 {
    354     return true;
    355 }
    356 
    357 void SchemaValidator::validateAttrValue (const XMLAttDef*      attDef
    358                                        , const XMLCh* const    attrValue
    359                                        , bool                  preValidation
    360                                        , const XMLElementDecl* elemDecl)
    361 {
    362     fErrorOccurred = false;
    363 
    364     //turn on IdRefList checking
    365     getScanner()->getValidationContext()->toCheckIdRefList(true);
    366 
    367     //
    368     //  Get quick refs to lot of the stuff in the passed objects in
    369     //  order to simplify the code below, which will reference them very
    370     //  often.
    371     //
    372     XMLAttDef::AttTypes            type      = attDef->getType();
    373     const XMLAttDef::DefAttTypes   defType   = attDef->getDefaultType();
    374 
    375     //
    376     //  If the default type is fixed, then make sure the passed value maps
    377     //  to the fixed value.
    378     //
    379     //  If during preContentValidation, the value we are validating is the fixed value itself
    380     //  so no need to compare.
    381     //  Only need to do this for regular attribute value validation
    382     //
    383     if ((defType == XMLAttDef::Fixed || defType == XMLAttDef::Required_And_Fixed) && !preValidation)
    384     {
    385         const XMLCh* const valueText = attDef->getValue();
    386         if (!XMLString::equals(attrValue, valueText)) {
    387             emitError(XMLValid::NotSameAsFixedValue, attDef->getFullName(), attrValue, valueText);
    388             fErrorOccurred = true;
    389         }
    390     }
    391 
    392     // An empty string cannot be valid for non_CDATA any of the other types
    393     if (!attrValue[0] && type != XMLAttDef::Simple)
    394     {
    395         emitError(XMLValid::InvalidEmptyAttValue, attDef->getFullName());
    396         // accords with original DOMTypeInfo implementation, but this does not feel right.
    397         fMostRecentAttrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYSIMPLETYPE);
    398         fErrorOccurred = true;
    399         return;
    400     }
    401 
    402     DatatypeValidator* attDefDV = ((SchemaAttDef*) attDef)->getDatatypeValidator();
    403     if (!attDefDV) {
    404         emitError(XMLValid::NoDatatypeValidatorForAttribute, attDef->getFullName());
    405         fErrorOccurred = true;
    406     }
    407     else {
    408         DatatypeValidator::ValidatorType attDefDVType = attDefDV->getType();
    409         ValidationContext *context = getScanner()->getValidationContext();
    410         try {
    411 
    412             // first, if notation, need to bind URI to notation first
    413             if (attDefDVType == DatatypeValidator::NOTATION)
    414             {
    415                 //
    416                 //  Make sure that this value maps to one of the
    417                 //  notation values in the enumList parameter. We don't have to
    418                 //  look it up in the notation pool (if a notation) because we
    419                 //  will look up the enumerated values themselves. If they are in
    420                 //  the notation pool (after the Grammar is parsed), then obviously
    421                 //  this value will be legal since it matches one of them.
    422                 //
    423                 XMLBuffer notationBuf(1023, fMemoryManager);
    424                 int colonPos = -1;
    425                 unsigned int uriId = getScanner()->resolveQName(attrValue, notationBuf, ElemStack::Mode_Element, colonPos);
    426                 const XMLCh* uriText = getScanner()->getURIText(uriId);
    427                 if (uriText && *uriText) {
    428                     notationBuf.set(uriText);
    429                     notationBuf.append(chColon);
    430                     notationBuf.append(&attrValue[colonPos + 1]);
    431                 }
    432                 else {
    433                     notationBuf.set(attrValue);
    434                 }
    435 
    436                 attDefDV->validate(notationBuf.getRawBuffer()
    437                                  , context
    438                                  , fMemoryManager);
    439             }
    440             else {
    441                 attDefDV->validate(attrValue
    442                                  , context
    443                                  , fMemoryManager);
    444             }
    445 
    446         }
    447         catch (XMLException& idve) {
    448             fErrorOccurred = true;
    449             emitError (XMLValid::DatatypeError, idve.getCode(), idve.getMessage());
    450         }
    451         catch(const OutOfMemoryException&)
    452         {
    453             throw;
    454         }
    455         catch (...) {
    456             emitError(XMLValid::GenericError);
    457             fMostRecentAttrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYSIMPLETYPE);
    458             fErrorOccurred = true;
    459             throw;
    460         }
    461         fMostRecentAttrValidator = attDefDV;
    462         // now we can look for ID's, entities, ...
    463 
    464         // set up the entitydeclpool in ENTITYDatatypeValidator
    465         // and the idreflist in ID/IDREFDatatypeValidator
    466 
    467         // indicate if this attribute is of type ID
    468         bool thisIsAnId = false;
    469 
    470         if (attDefDVType == DatatypeValidator::List) {
    471             DatatypeValidator* itemDTV = ((ListDatatypeValidator*)attDefDV)->getItemTypeDTV();
    472             DatatypeValidator::ValidatorType itemDTVType = itemDTV->getType();
    473             if (itemDTVType == DatatypeValidator::ID) {
    474                 thisIsAnId = true;
    475             }
    476             else if (itemDTVType == DatatypeValidator::IDREF) {
    477                 // if in prevalidatoin, do not add attDef to IDREFList
    478                 if (preValidation)
    479                     //todo: when to setIdRefList back to non-null
    480                     getScanner()->getValidationContext()->toCheckIdRefList(false);
    481             }
    482         }
    483         else if (attDefDVType == DatatypeValidator::Union) {
    484             DatatypeValidator *memberDTV = context->getValidatingMemberType();
    485             // actual type for DOMTypeInfo is memberDTV
    486             fMostRecentAttrValidator = memberDTV;
    487             // no member datatype validator if there was an error
    488             if(memberDTV)
    489             {
    490                 DatatypeValidator::ValidatorType memberDTVType = memberDTV->getType();
    491                 if (memberDTVType == DatatypeValidator::ID) {
    492                     thisIsAnId = true;
    493                 }
    494                 else if (memberDTVType == DatatypeValidator::IDREF) {
    495                     // if in prevalidatoin, do not add attDef to IDREFList
    496                     if (preValidation)
    497                         getScanner()->getValidationContext()->toCheckIdRefList(false);
    498                 }
    499             }
    500         }
    501         else if (attDefDVType == DatatypeValidator::ID) {
    502             thisIsAnId = true;
    503         }
    504         else if (attDefDVType == DatatypeValidator::IDREF) {
    505             // if in prevalidation, do not add attDef to IDREFList
    506             if (preValidation)
    507                 getScanner()->getValidationContext()->toCheckIdRefList(false);
    508         }
    509         if (thisIsAnId) {
    510             if (fSeenId) {
    511                 emitError
    512                 (
    513                     XMLValid::MultipleIdAttrs
    514                     , elemDecl->getFullName()
    515                 );
    516                 fErrorOccurred = true;
    517             }
    518             else
    519                 fSeenId = true;
    520         }
    521 
    522     }
    523 
    524     if(fErrorOccurred) {
    525         fMostRecentAttrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYSIMPLETYPE);
    526     }
    527     fTrailing = false;
    528     fSeenNonWhiteSpace = false;
    529 }
    530 
    531 void SchemaValidator::validateElement(const   XMLElementDecl*  elemDef)
    532 {
    533     ComplexTypeInfo* elemTypeInfo = ((SchemaElementDecl*)elemDef)->getComplexTypeInfo();
    534     fTypeStack->push(elemTypeInfo);
    535     fCurrentDatatypeValidator = (elemTypeInfo)
    536             ? elemTypeInfo->getDatatypeValidator()
    537             : ((SchemaElementDecl*)elemDef)->getDatatypeValidator();
    538 
    539     fErrorOccurred = false;
    540 
    541     if (fXsiType) {
    542         // handle "xsi:type" right here
    543         DatatypeValidator *xsiTypeDV = 0;
    544         unsigned int uri = fXsiType->getURI();
    545         const XMLCh* localPart = fXsiType->getLocalPart();
    546 
    547         if (uri != XMLElementDecl::fgInvalidElemId &&
    548             uri != XMLElementDecl::fgPCDataElemId &&
    549             uri != XMLContentModel::gEpsilonFakeId &&
    550             uri != XMLContentModel::gEOCFakeId) {
    551 
    552             // retrieve Grammar for the uri
    553             const XMLCh* uriStr = getScanner()->getURIText(uri);
    554             SchemaGrammar* sGrammar = (SchemaGrammar*) fGrammarResolver->getGrammar(uriStr);
    555             if (!sGrammar) {
    556 
    557                 // Check built-in simple types
    558                 if (XMLString::equals(uriStr, SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) {
    559 
    560                     xsiTypeDV = fGrammarResolver->getDatatypeValidator(uriStr, localPart);
    561 
    562                     if (!xsiTypeDV) {
    563                         emitError(XMLValid::BadXsiType, fXsiType->getRawName());
    564                         fErrorOccurred = true;
    565                     }
    566                     else {
    567                         if (elemTypeInfo || (fCurrentDatatypeValidator
    568                                 && !fCurrentDatatypeValidator->isSubstitutableBy(xsiTypeDV))) {
    569                             // the type is not derived from ancestor
    570                             emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName());
    571                             fErrorOccurred = true;
    572                         }
    573                         else if(fCurrentDatatypeValidator != xsiTypeDV)
    574                         {
    575                             // the type is derived from ancestor
    576                             if ((((SchemaElementDecl*)elemDef)->getBlockSet() & SchemaSymbols::XSD_RESTRICTION) != 0) {
    577                                 emitError(XMLValid::ElemNoSubforBlock, elemDef->getFullName());
    578                                 fErrorOccurred = true;
    579                             }
    580                             if (elemDef->hasAttDefs()) {
    581                                 // if we have an attribute but xsi:type's type is simple, we have a problem...
    582                                 emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName());
    583                                 fErrorOccurred = true;
    584                             }
    585                         }
    586                         fCurrentDatatypeValidator = xsiTypeDV;
    587                     }
    588                 }
    589                 else {
    590                     // Grammar not found
    591                     emitError(XMLValid::GrammarNotFound, uriStr);
    592                     fErrorOccurred = true;
    593                 }
    594             }
    595             else if (sGrammar->getGrammarType() != Grammar::SchemaGrammarType) {
    596                 emitError(XMLValid::GrammarNotFound, uriStr);
    597                 fErrorOccurred = true;
    598             }
    599             else {
    600                 // retrieve complexType registry and DatatypeValidator registry
    601                 RefHashTableOf<ComplexTypeInfo>* complexTypeRegistry = sGrammar->getComplexTypeRegistry();
    602                 if (!complexTypeRegistry) {
    603                     emitError(XMLValid::BadXsiType, fXsiType->getRawName());
    604                     fErrorOccurred = true;
    605                 }
    606                 else {
    607 
    608                     // retrieve the typeInfo specified in xsi:type
    609                     XMLBuffer aBuffer(1023, fMemoryManager);
    610                     aBuffer.set(uriStr);
    611                     aBuffer.append(chComma);
    612                     aBuffer.append(localPart);
    613                     ComplexTypeInfo* typeInfo = complexTypeRegistry->get(aBuffer.getRawBuffer());
    614 
    615                     if (typeInfo) {
    616                         // typeInfo is found
    617                         if (typeInfo->getAbstract()) {
    618                             emitError(XMLValid::NoAbstractInXsiType, aBuffer.getRawBuffer());
    619                             fErrorOccurred = true;
    620                         }
    621                         else
    622                         {
    623                             if (elemTypeInfo)
    624                             {
    625                                 ComplexTypeInfo* tempType = typeInfo;
    626                                 while (tempType) {
    627                                     if (tempType == elemTypeInfo)
    628                                         break;
    629                                     tempType = tempType->getBaseComplexTypeInfo();
    630                                 }
    631 
    632                                 if (!tempType) {
    633                                     emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName());
    634                                     fErrorOccurred = true;
    635                                 }
    636                                 else if(elemTypeInfo != typeInfo) {
    637                                     // perform the check on the entire inheritance chain
    638                                     ComplexTypeInfo* tempType = typeInfo;
    639                                     while (tempType) {
    640                                         if (tempType == elemTypeInfo)
    641                                             break;
    642                                         int derivationMethod = tempType->getDerivedBy();
    643                                         if ((((SchemaElementDecl*)elemDef)->getBlockSet() & derivationMethod) != 0) {
    644                                             emitError(XMLValid::ElemNoSubforBlock, elemDef->getFullName());
    645                                             fErrorOccurred = true;
    646                                         }
    647                                         if ((elemTypeInfo->getBlockSet() & derivationMethod) != 0) {
    648                                             emitError(XMLValid::TypeNoSubforBlock, elemTypeInfo->getTypeName());
    649                                             fErrorOccurred = true;
    650                                         }
    651                                         tempType = tempType->getBaseComplexTypeInfo();
    652                                     }
    653                                 }
    654                             }
    655                             else
    656                             {
    657                                 // if the original type is a simple type, check derivation ok.
    658                                 if (fCurrentDatatypeValidator && !fCurrentDatatypeValidator->isSubstitutableBy(typeInfo->getDatatypeValidator())) {
    659                                     // the type is not derived from ancestor
    660                                     emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName());
    661                                     fErrorOccurred = true;
    662                                 }
    663                             }
    664 
    665                             if (!fErrorOccurred)
    666                             {
    667                                 fTypeStack->pop();
    668                                 fTypeStack->push(typeInfo);
    669                                 fCurrentDatatypeValidator = typeInfo->getDatatypeValidator();
    670                             }
    671                         }
    672                     }
    673                     else
    674                     {
    675                         // typeInfo not found
    676                         xsiTypeDV = fGrammarResolver->getDatatypeValidator(uriStr, localPart);
    677 
    678                         if (!xsiTypeDV) {
    679                             emitError(XMLValid::BadXsiType, fXsiType->getRawName());
    680                             fErrorOccurred = true;
    681                         }
    682                         else {
    683                             if (fCurrentDatatypeValidator && !fCurrentDatatypeValidator->isSubstitutableBy(xsiTypeDV)) {
    684                                 // the type is not derived from ancestor
    685                                 emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName());
    686                                 fErrorOccurred = true;
    687                             }
    688                             else if(fCurrentDatatypeValidator != xsiTypeDV)
    689                             {
    690                                 DatatypeValidator::ValidatorType derivedType=xsiTypeDV->getType();
    691                                 if((derivedType == DatatypeValidator::List || derivedType == DatatypeValidator::Union) && fCurrentDatatypeValidator==0)
    692                                 {
    693                                     // the substitution is always allowed if the type is list or union and the base type was xs:anySimpleType
    694                                 }
    695                                 else
    696                                 {
    697                                     // the type is derived from ancestor
    698                                     if ((((SchemaElementDecl*)elemDef)->getBlockSet() & SchemaSymbols::XSD_RESTRICTION) != 0) {
    699                                         emitError(XMLValid::ElemNoSubforBlock, elemDef->getFullName());
    700                                         fErrorOccurred = true;
    701                                     }
    702                                     if (elemDef->hasAttDefs()) {
    703                                         // if we have an attribute but xsi:type's type is simple, we have a problem...
    704                                         emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName());
    705                                         fErrorOccurred = true;
    706                                     }
    707                                 }
    708                             }
    709 
    710                             fCurrentDatatypeValidator = xsiTypeDV;
    711                         }
    712                     }
    713                 }
    714             }
    715         }
    716 
    717         delete fXsiType;
    718         fXsiType = 0;
    719     }
    720     else {
    721         //
    722         // xsi:type was not specified...
    723         // If the corresponding type is abstract, detect an error
    724         //
    725         if (elemTypeInfo && elemTypeInfo->getAbstract()) {
    726             emitError(XMLValid::NoUseAbstractType, elemDef->getFullName());
    727             fErrorOccurred = true;
    728         }
    729     }
    730 
    731     //
    732     // Check whether this element is abstract.  If so, an error
    733     //
    734     int miscFlags = ((SchemaElementDecl*)elemDef)->getMiscFlags();
    735     if ((miscFlags & SchemaSymbols::XSD_ABSTRACT) != 0) {
    736         emitError(XMLValid::NoDirectUseAbstractElement, elemDef->getFullName());
    737         fErrorOccurred = true;
    738     }
    739 
    740     //
    741     // Check whether this element allows Nillable
    742     //
    743     if (fNilFound && (miscFlags & SchemaSymbols::XSD_NILLABLE) == 0 ) {
    744         fNil = false;
    745         fNilFound = false;
    746         emitError(XMLValid::NillNotAllowed, elemDef->getFullName());
    747         fErrorOccurred = true;
    748     }
    749 
    750     fDatatypeBuffer.reset();
    751     fTrailing = false;
    752     fSeenNonWhiteSpace = false;
    753     fSeenId = false;
    754 }
    755 
    756 void SchemaValidator::preContentValidation(bool,
    757                                            bool validateDefAttr)
    758 {
    759     //  Lets go through all the grammar in the GrammarResolver
    760     //    and validate those that has not been validated yet
    761     //
    762     //  Lets enumerate all of the elements in the element decl pool
    763     //    and put out an error for any that did not get declared.
    764     //    We also check all of the attributes as well.
    765     //
    766     //  And enumerate all the complextype info in the grammar
    767     //    and do Unique Particle Attribution Checking
    768 
    769     RefHashTableOfEnumerator<Grammar> grammarEnum = fGrammarResolver->getGrammarEnumerator();
    770     while (grammarEnum.hasMoreElements())
    771     {
    772         SchemaGrammar& sGrammar = (SchemaGrammar&) grammarEnum.nextElement();
    773         if (sGrammar.getGrammarType() != Grammar::SchemaGrammarType || sGrammar.getValidated())
    774              continue;
    775 
    776         sGrammar.setValidated(true);
    777 
    778         RefHash3KeysIdPoolEnumerator<SchemaElementDecl> elemEnum = sGrammar.getElemEnumerator();
    779 
    780         while (elemEnum.hasMoreElements())
    781         {
    782             SchemaElementDecl& curElem = elemEnum.nextElement();
    783 
    784             //  First check if declared or not
    785             //
    786             //  See if this element decl was ever marked as declared. If
    787             //  not, then put out an error. In some cases its just
    788             //  a warning, such as being referenced in a content model.
    789             //
    790             const SchemaElementDecl::CreateReasons reason = curElem.getCreateReason();
    791 
    792             if (reason != XMLElementDecl::Declared)
    793             {
    794                 if (reason == XMLElementDecl::AttList)
    795                 {
    796                     getScanner()->emitError
    797                     (
    798                         XMLErrs::UndeclaredElemInAttList
    799                         , curElem.getFullName()
    800                     );
    801                 }
    802                  else if (reason == XMLElementDecl::AsRootElem)
    803                 {
    804                     emitError
    805                     (
    806                         XMLValid::UndeclaredElemInDocType
    807                         , curElem.getFullName()
    808                     );
    809                 }
    810                  else if (reason == XMLElementDecl::InContentModel)
    811                 {
    812                     getScanner()->emitError
    813                     (
    814                         XMLErrs::UndeclaredElemInCM
    815                         , curElem.getFullName()
    816                     );
    817                 }
    818                 else
    819                 {
    820                 }
    821             }
    822 
    823             //
    824             //  Then check all of the attributes of the current element.
    825             //  We check for:
    826             //
    827             //  1) Multiple ID attributes
    828             //  2) That all of the default values of attributes are
    829             //      valid for their type.
    830             //  3) That for any notation types, that their lists
    831             //      of possible values refer to declared notations.
    832             //
    833             if (curElem.hasAttDefs()) {
    834                 XMLAttDefList& attDefList = curElem.getAttDefList();
    835                 bool seenId = false;
    836 
    837                 for(XMLSize_t i=0; i<attDefList.getAttDefCount(); i++)
    838                 {
    839                     const XMLAttDef& curAttDef = attDefList.getAttDef(i);
    840 
    841                     if (curAttDef.getType() == XMLAttDef::ID)
    842                     {
    843                         if (seenId)
    844                         {
    845                             emitError
    846                             (
    847                                 XMLValid::MultipleIdAttrs
    848                                 , curElem.getFullName()
    849                             );
    850                             break;
    851                         }
    852 
    853                         seenId = true;
    854                     }
    855                      else if (curAttDef.getType() == XMLAttDef::Notation && curAttDef.getEnumeration())
    856                     {
    857                         //
    858                         //  We need to verify that all of its possible values
    859                         //  (in the enum list) refer to valid notations.
    860                         //
    861                         XMLCh* list = XMLString::replicate(curAttDef.getEnumeration(), fMemoryManager);
    862                         ArrayJanitor<XMLCh> janList(list, fMemoryManager);
    863 
    864                         //
    865                         //  Search forward for a space or a null. If a null,
    866                         //  we are done. If a space, cap it and look it up.
    867                         //
    868                         bool    breakFlag = false;
    869                         XMLCh*  listPtr = list;
    870                         XMLCh*  lastPtr = listPtr;
    871                         while (true)
    872                         {
    873                             while (*listPtr && (*listPtr != chSpace))
    874                                 listPtr++;
    875 
    876                             //
    877                             //  If at the end, indicate we need to break after
    878                             //  this one. Else, cap it off here.
    879                             //
    880                             if (!*listPtr)
    881                                 breakFlag = true;
    882                             else
    883                                 *listPtr = chNull;
    884 
    885                             if (!sGrammar.getNotationDecl(lastPtr))
    886                             {
    887                                 emitError
    888                                 (
    889                                     XMLValid::UnknownNotRefAttr
    890                                     , curAttDef.getFullName()
    891                                     , lastPtr
    892                                 );
    893                             }
    894 
    895                             // Break out if we hit the end last time
    896                             if (breakFlag)
    897                                 break;
    898 
    899                             // Else move upwards and try again
    900                             listPtr++;
    901                             lastPtr = listPtr;
    902                         }
    903                     }
    904 
    905                     // If it has a default/fixed value, then validate it
    906                     if (validateDefAttr && curAttDef.getValue())
    907                     {
    908                         validateAttrValue
    909                         (
    910                             &curAttDef
    911                             , curAttDef.getValue()
    912                             , true
    913                             , &curElem
    914                         );
    915                     }
    916                 }
    917             }
    918         }
    919 
    920         //  For each complex type info, check the Unique Particle Attribution
    921         if (getScanner()->getValidationSchemaFullChecking()) {
    922             RefHashTableOf<ComplexTypeInfo>* complexTypeRegistry = sGrammar.getComplexTypeRegistry();
    923 
    924             RefHashTableOfEnumerator<ComplexTypeInfo> complexTypeEnum(complexTypeRegistry, false, fMemoryManager);
    925             while (complexTypeEnum.hasMoreElements())
    926             {
    927                 ComplexTypeInfo& curTypeInfo = complexTypeEnum.nextElement();
    928                 curTypeInfo.checkUniqueParticleAttribution(&sGrammar, fGrammarResolver, fGrammarResolver->getStringPool(), this);
    929                 checkParticleDerivation(&sGrammar, &curTypeInfo);
    930                 checkRefElementConsistency(&sGrammar, &curTypeInfo);
    931             }
    932 
    933             RefHashTableOf<XercesGroupInfo>* groupInfoRegistry = sGrammar.getGroupInfoRegistry();
    934             RefHashTableOfEnumerator<XercesGroupInfo> groupEnum(groupInfoRegistry, false, fMemoryManager);
    935 
    936             while (groupEnum.hasMoreElements()) {
    937 
    938                 XercesGroupInfo& curGroup = groupEnum.nextElement();
    939                 XercesGroupInfo* baseGroup = curGroup.getBaseGroup();
    940 
    941                 if (baseGroup) {
    942                     try {
    943                         checkParticleDerivationOk(&sGrammar, curGroup.getContentSpec(), curGroup.getScope(),
    944                                                   baseGroup->getContentSpec(), baseGroup->getScope());
    945                     }
    946                     catch (const XMLException& excep) {
    947                         fSchemaErrorReporter.emitError(excep, curGroup.getLocator());
    948                                         }
    949                 }
    950 
    951                 if (curGroup.getCheckElementConsistency())
    952                     checkRefElementConsistency(&sGrammar, 0, &curGroup);
    953             }
    954         }
    955     }
    956 }
    957 
    958 void SchemaValidator::postParseValidation()
    959 {
    960     //
    961     //  At this time, there is nothing to do here. The scanner itself handles
    962     //  ID/IDREF validation, since that is the same no matter what kind of
    963     //  validator.
    964     //
    965 }
    966 
    967 // ---------------------------------------------------------------------------
    968 //  SchemaValidator: Validator method
    969 // ---------------------------------------------------------------------------
    970 // Do Schema Normalization depends on the WhiteSpace Facet
    971 // preserve : No normalization is done
    972 // replace  : All occurrences of #x9 (tab), #xA (linefeed) and #xD (carriage return)
    973 //            are replaced with #x20 (space).
    974 // collapse : Subsequent to the replacements specified above under replace,
    975 //            contiguous sequences of #x20s are collapsed to a single #x20,
    976 //            and initial and/or final #x20s are deleted.
    977 //
    978 void SchemaValidator::normalizeWhiteSpace(DatatypeValidator* dV, const XMLCh* const value, XMLBuffer& toFill, bool bStandalone /*= false*/)
    979 {
    980     toFill.reset();
    981 
    982     //empty string
    983     if (!*value)
    984         return;
    985 
    986     if(bStandalone)
    987         fTrailing = fSeenNonWhiteSpace = false;
    988 
    989     short wsFacet = dV->getWSFacet();
    990 
    991     //  Loop through the chars of the source value and normalize it
    992     //  according to the whitespace facet
    993     XMLCh nextCh;
    994     const XMLCh* srcPtr = value;
    995     XMLReader* fCurReader = getReaderMgr()->getCurrentReader();
    996 
    997     if (wsFacet == DatatypeValidator::REPLACE)
    998     {
    999         while (*srcPtr)
    1000         {
    1001             nextCh = *srcPtr++;
    1002             if (fCurReader->isWhitespace(nextCh))
    1003                 nextCh = chSpace;
    1004             // Add this char to the target buffer
    1005             toFill.append(nextCh);
    1006         }
    1007     }
    1008     else // COLLAPSE
    1009     {
    1010         enum States
    1011         {
    1012             InWhitespace
    1013             , InContent
    1014         };
    1015 
    1016         States curState = fTrailing ? InWhitespace : InContent;
    1017         while (*srcPtr)
    1018         {
    1019             nextCh = *srcPtr++;
    1020             if (curState == InContent)
    1021             {
    1022                 if (fCurReader->isWhitespace(nextCh))
    1023                 {
    1024                     curState = InWhitespace;
    1025                     continue;
    1026                 }
    1027                 fSeenNonWhiteSpace = true;
    1028             }
    1029             else if (curState == InWhitespace)
    1030             {
    1031                 if (fCurReader->isWhitespace(nextCh))
    1032                     continue;
    1033                 if (fSeenNonWhiteSpace)
    1034                     toFill.append(chSpace);
    1035                 curState = InContent;
    1036                 fSeenNonWhiteSpace = true;
    1037             }
    1038             // Add this char to the target buffer
    1039             toFill.append(nextCh);
    1040         }
    1041 
    1042         if (fCurReader->isWhitespace(*(srcPtr-1)))
    1043           fTrailing = true;
    1044         else
    1045           fTrailing = false;
    1046     }
    1047     if(bStandalone)
    1048         fTrailing = fSeenNonWhiteSpace = false;
    1049 }
    1050 
    1051 
    1052 // ---------------------------------------------------------------------------
    1053 //  SchemaValidator: Particle Derivation Checking
    1054 // ---------------------------------------------------------------------------
    1055 void SchemaValidator::checkRefElementConsistency(SchemaGrammar* const currentGrammar,
    1056                                                  const ComplexTypeInfo* const curTypeInfo,
    1057                                                  const XercesGroupInfo* const curGroup) {
    1058 
    1059     XMLSize_t elemCount = (curTypeInfo) ? curTypeInfo->elementCount() : curGroup->elementCount();
    1060     int elemScope = (curTypeInfo) ? curTypeInfo->getScopeDefined() : curGroup->getScope();
    1061     XSDLocator* typeInfoLocator = (curTypeInfo) ? curTypeInfo->getLocator() : curGroup->getLocator();
    1062 
    1063     for (XMLSize_t i=0; i < elemCount; i++) {
    1064 
    1065         const SchemaElementDecl* elemDecl = (curTypeInfo) ? curTypeInfo->elementAt(i) : curGroup->elementAt(i);
    1066 
    1067         if (elemDecl->isGlobalDecl()) {
    1068 
    1069             unsigned int elemURI = elemDecl->getURI();
    1070             const XMLCh* elemName = elemDecl->getBaseName();
    1071             const SchemaElementDecl* other = (SchemaElementDecl*)
    1072                 currentGrammar->getElemDecl(elemURI, elemName, 0, elemScope);
    1073 
    1074             if (other
    1075                 && (elemDecl->getComplexTypeInfo() != other->getComplexTypeInfo() ||
    1076                     elemDecl->getDatatypeValidator() != other->getDatatypeValidator())) {
    1077                 fSchemaErrorReporter.emitError(XMLErrs::DuplicateElementDeclaration,
    1078                                                XMLUni::fgXMLErrDomain, typeInfoLocator, elemName, 0, 0, 0, fMemoryManager);
    1079                 continue;
    1080             }
    1081 
    1082             RefHash2KeysTableOf<ElemVector>* validSubsGroups = currentGrammar->getValidSubstitutionGroups();
    1083             ValueVectorOf<SchemaElementDecl*>* subsElements = validSubsGroups->get(elemName, elemURI);
    1084 
    1085             if (subsElements) {
    1086 
    1087                 XMLSize_t subsElemSize = subsElements->size();
    1088 
    1089                 for (XMLSize_t j=0; j < subsElemSize; j++) {
    1090 
    1091                     SchemaElementDecl* subsElem = subsElements->elementAt(j);
    1092                     const XMLCh* subsElemName = subsElem->getBaseName();
    1093                     other = (SchemaElementDecl*)
    1094                         currentGrammar->getElemDecl(subsElem->getURI(), subsElemName, 0, elemScope);
    1095 
    1096                     if (other
    1097                         && (subsElem->getComplexTypeInfo() != other->getComplexTypeInfo()
    1098                             || subsElem->getDatatypeValidator() != other->getDatatypeValidator())) {
    1099                         fSchemaErrorReporter.emitError(XMLErrs::DuplicateElementDeclaration,
    1100                                                        XMLUni::fgXMLErrDomain, typeInfoLocator, elemName, 0, 0, 0, fMemoryManager);
    1101                     }
    1102                 }
    1103             }
    1104         }
    1105     }
    1106 }
    1107 
    1108 // ---------------------------------------------------------------------------
    1109 //  SchemaValidator: Particle Derivation Checking
    1110 // ---------------------------------------------------------------------------
    1111 void SchemaValidator::checkParticleDerivation(SchemaGrammar* const currentGrammar,
    1112                                               const ComplexTypeInfo* const curTypeInfo) {
    1113 
    1114     ComplexTypeInfo* baseTypeInfo = 0;
    1115     ContentSpecNode* curSpecNode = 0;
    1116 
    1117     if (curTypeInfo->getDerivedBy() == SchemaSymbols::XSD_RESTRICTION
    1118         && ((baseTypeInfo = curTypeInfo->getBaseComplexTypeInfo()) != 0)
    1119         && ((curSpecNode = curTypeInfo->getContentSpec()) != 0)) {
    1120 
    1121         try {
    1122             checkParticleDerivationOk(currentGrammar, curSpecNode,
    1123                                       curTypeInfo->getScopeDefined(),
    1124                                       baseTypeInfo->getContentSpec(),
    1125                                       baseTypeInfo->getScopeDefined(), baseTypeInfo);
    1126         }
    1127         catch (const XMLException& excep) {
    1128             fSchemaErrorReporter.emitError(excep, curTypeInfo->getLocator());
    1129         }
    1130     }
    1131 }
    1132 
    1133 ContentSpecNode* SchemaValidator::getNonUnaryGroup(ContentSpecNode* const pNode) {
    1134 
    1135     int pNodeType = (pNode->getType() & 0x0f);
    1136     if (pNodeType == ContentSpecNode::Leaf
    1137         || pNodeType == ContentSpecNode::Any
    1138         || pNodeType == ContentSpecNode::Any_Other
    1139         || pNodeType == ContentSpecNode::Any_NS)
    1140         return pNode;
    1141 
    1142     if (pNode->getMinOccurs() == 1 && pNode->getMaxOccurs() == 1
    1143         && pNode->getFirst() && !pNode->getSecond())
    1144         return getNonUnaryGroup(pNode->getFirst());
    1145 
    1146     return pNode;
    1147 }
    1148 
    1149 void SchemaValidator::checkParticleDerivationOk(SchemaGrammar* const aGrammar,
    1150                                                 ContentSpecNode* const curNode,
    1151                                                 const int derivedScope,
    1152                                                 ContentSpecNode* const baseNode,
    1153                                                 const int baseScope,
    1154                                                 const ComplexTypeInfo* const baseInfo,
    1155                                                 const bool toCheckOccurence) {
    1156 
    1157     // Check for pointless occurrences of all, choice, sequence.  The result is
    1158     // the contentspec which is not pointless. If the result is a non-pointless
    1159     // group, Vector is filled  in with the children of interest
    1160     if (curNode && !baseNode)
    1161         ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_EmptyBase, fMemoryManager);
    1162 
    1163     if (!curNode)
    1164         return;
    1165 
    1166     ContentSpecNode* curSpecNode = getNonUnaryGroup(curNode);
    1167     ContentSpecNode* baseSpecNode = getNonUnaryGroup(baseNode);
    1168     ValueVectorOf<ContentSpecNode*> curVector(8, fMemoryManager);
    1169     ValueVectorOf<ContentSpecNode*> baseVector(8, fMemoryManager);
    1170     ContentSpecNode::NodeTypes curNodeType = curSpecNode->getType();
    1171     ContentSpecNode::NodeTypes baseNodeType = baseSpecNode->getType();
    1172 
    1173     if ((curNodeType & 0x0f) == ContentSpecNode::Sequence ||
    1174         (curNodeType & 0x0f) == ContentSpecNode::Choice ||
    1175         curNodeType == ContentSpecNode::All) {
    1176         curSpecNode = checkForPointlessOccurrences(curSpecNode, curNodeType, &curVector);
    1177     }
    1178 
    1179     if ((baseNodeType & 0x0f) == ContentSpecNode::Sequence ||
    1180         (baseNodeType & 0x0f) == ContentSpecNode::Choice ||
    1181         baseNodeType == ContentSpecNode::All) {
    1182         baseSpecNode = checkForPointlessOccurrences(baseSpecNode, baseNodeType, &baseVector);
    1183     }
    1184 
    1185     curNodeType = curSpecNode->getType();
    1186     baseNodeType = baseSpecNode->getType();
    1187 
    1188     switch (curNodeType & 0x0f) {
    1189     case ContentSpecNode::Leaf:
    1190         {
    1191             switch (baseNodeType & 0x0f) {
    1192             case ContentSpecNode::Leaf:
    1193                 {
    1194                     checkNameAndTypeOK(aGrammar, curSpecNode, derivedScope, baseSpecNode, baseScope, baseInfo);
    1195                     return;
    1196                 }
    1197             case ContentSpecNode::Any:
    1198             case ContentSpecNode::Any_Other:
    1199             case ContentSpecNode::Any_NS:
    1200                 {
    1201                     checkNSCompat(curSpecNode, baseSpecNode, toCheckOccurence);
    1202                     return;
    1203                 }
    1204             case ContentSpecNode::Choice:
    1205             case ContentSpecNode::Sequence:
    1206             case ContentSpecNode::All:
    1207                 {
    1208                     checkRecurseAsIfGroup(aGrammar, curSpecNode, derivedScope,
    1209                                           baseSpecNode, baseScope, &baseVector, baseInfo);
    1210                     return;
    1211                 }
    1212             default:
    1213                 {
    1214                     ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_InvalidContentType, fMemoryManager);
    1215                 }
    1216             }
    1217         }
    1218     case ContentSpecNode::Any:
    1219     case ContentSpecNode::Any_Other:
    1220     case ContentSpecNode::Any_NS:
    1221         {
    1222             switch (baseNodeType & 0x0f) {
    1223             case ContentSpecNode::Any:
    1224             case ContentSpecNode::Any_Other:
    1225             case ContentSpecNode::Any_NS:
    1226                 {
    1227                      checkNSSubset(curSpecNode, baseSpecNode);
    1228                      return;
    1229                 }
    1230             case ContentSpecNode::Choice:
    1231             case ContentSpecNode::Sequence:
    1232             case ContentSpecNode::All:
    1233             case ContentSpecNode::Leaf:
    1234                 {
    1235                     if (baseNodeType == ContentSpecNode::Any_NS_Choice) {
    1236                         if (checkNSSubsetChoiceRoot(curSpecNode, baseSpecNode)) {
    1237                             return;
    1238                         }
    1239                     }
    1240 
    1241                     ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_ForbiddenRes1, fMemoryManager);
    1242                 }
    1243             default:
    1244                 {
    1245                     ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_InvalidContentType, fMemoryManager);
    1246                 }
    1247             }
    1248         }
    1249     case ContentSpecNode::All:
    1250         {
    1251             switch (baseNodeType & 0x0f) {
    1252             case ContentSpecNode::Any:
    1253             case ContentSpecNode::Any_Other:
    1254             case ContentSpecNode::Any_NS:
    1255                 {
    1256                     checkNSRecurseCheckCardinality(aGrammar, curSpecNode, &curVector, derivedScope, baseSpecNode, toCheckOccurence);
    1257                     return;
    1258                 }
    1259             case ContentSpecNode::All:
    1260                 {
    1261                     checkRecurse(aGrammar, curSpecNode, derivedScope, &curVector,
    1262                                  baseSpecNode, baseScope, &baseVector, baseInfo);
    1263                     return;
    1264                 }
    1265             case ContentSpecNode::Choice:
    1266             case ContentSpecNode::Sequence:
    1267             case ContentSpecNode::Leaf:
    1268                 {
    1269                     ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_ForbiddenRes2, fMemoryManager);
    1270                 }
    1271             default:
    1272                 {
    1273                     ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_InvalidContentType, fMemoryManager);
    1274                 }
    1275             }
    1276         }
    1277     case ContentSpecNode::Choice:
    1278         {
    1279             switch (baseNodeType & 0x0f) {
    1280             case ContentSpecNode::Any:
    1281             case ContentSpecNode::Any_Other:
    1282             case ContentSpecNode::Any_NS:
    1283                 {
    1284                     checkNSRecurseCheckCardinality(aGrammar, curSpecNode, &curVector, derivedScope, baseSpecNode, toCheckOccurence);
    1285                     return;
    1286                 }
    1287             case ContentSpecNode::Choice:
    1288                 {
    1289                     checkRecurse(aGrammar, curSpecNode, derivedScope, &curVector,
    1290                                  baseSpecNode, baseScope, &baseVector, baseInfo, true);
    1291                     return;
    1292                 }
    1293             case ContentSpecNode::All:
    1294             case ContentSpecNode::Sequence:
    1295             case ContentSpecNode::Leaf:
    1296                 {
    1297                     ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_ForbiddenRes3, fMemoryManager);
    1298                 }
    1299             default:
    1300                 {
    1301                     ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_InvalidContentType, fMemoryManager);
    1302                 }
    1303             }
    1304         }
    1305     case ContentSpecNode::Sequence:
    1306         {
    1307             switch (baseNodeType & 0x0f) {
    1308             case ContentSpecNode::Any:
    1309             case ContentSpecNode::Any_Other:
    1310             case ContentSpecNode::Any_NS:
    1311                 {
    1312                     checkNSRecurseCheckCardinality(aGrammar, curSpecNode, &curVector, derivedScope, baseSpecNode, toCheckOccurence);
    1313                     return;
    1314                 }
    1315             case ContentSpecNode::All:
    1316                 {
    1317                     checkRecurseUnordered(aGrammar, curSpecNode, &curVector, derivedScope,
    1318                                           baseSpecNode, &baseVector, baseScope, baseInfo);
    1319                     return;
    1320                 }
    1321             case ContentSpecNode::Sequence:
    1322                 {
    1323                     checkRecurse(aGrammar, curSpecNode, derivedScope, &curVector,
    1324                                  baseSpecNode, baseScope, &baseVector, baseInfo);
    1325                     return;
    1326                 }
    1327             case ContentSpecNode::Choice:
    1328                 {
    1329                     checkMapAndSum(aGrammar, curSpecNode, &curVector, derivedScope,
    1330                                    baseSpecNode, &baseVector, baseScope, baseInfo);
    1331                     return;
    1332                 }
    1333             case ContentSpecNode::Leaf:
    1334                 {
    1335                     ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_ForbiddenRes4, fMemoryManager);
    1336                 }
    1337             default:
    1338                 {
    1339                     ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_InvalidContentType, fMemoryManager);
    1340                 }
    1341             }
    1342         }
    1343     }
    1344 }
    1345 
    1346 ContentSpecNode*
    1347 SchemaValidator::checkForPointlessOccurrences(ContentSpecNode* const specNode,
    1348                                               const ContentSpecNode::NodeTypes nodeType,
    1349                                               ValueVectorOf<ContentSpecNode*>* const nodes) {
    1350 
    1351     ContentSpecNode* rightNode = specNode->getSecond();
    1352     int min = specNode->getMinOccurs();
    1353     int max = specNode->getMaxOccurs();
    1354 
    1355     if (!rightNode) {
    1356 
    1357          gatherChildren(nodeType, specNode->getFirst(), nodes);
    1358 
    1359          if (nodes->size() == 1 && min == 1 && max == 1) {
    1360             return nodes->elementAt(0);
    1361         }
    1362 
    1363         return specNode;
    1364     }
    1365 
    1366     gatherChildren(nodeType, specNode->getFirst(), nodes);
    1367     gatherChildren(nodeType, rightNode, nodes);
    1368 
    1369     return specNode;
    1370 }
    1371 
    1372 void SchemaValidator::gatherChildren(const ContentSpecNode::NodeTypes parentNodeType,
    1373                                     ContentSpecNode* const specNode,
    1374                                     ValueVectorOf<ContentSpecNode*>* const nodes) {
    1375 
    1376     if (!specNode) {
    1377         return;
    1378     }
    1379 
    1380     int min = specNode->getMinOccurs();
    1381     int max = specNode->getMaxOccurs();
    1382     ContentSpecNode::NodeTypes nodeType = specNode->getType();
    1383     ContentSpecNode* rightNode = specNode->getSecond();
    1384 
    1385     if (nodeType == ContentSpecNode::Leaf ||
    1386         (nodeType & 0x0f) == ContentSpecNode::Any ||
    1387         (nodeType & 0x0f) == ContentSpecNode::Any_NS ||
    1388         (nodeType & 0x0f) == ContentSpecNode::Any_Other) {
    1389         nodes->addElement(specNode);
    1390     }
    1391     else if (min !=1 || max != 1) {
    1392         nodes->addElement(specNode);
    1393     }
    1394     else if (!rightNode) {
    1395         gatherChildren(nodeType, specNode->getFirst(), nodes);
    1396     }
    1397     else if ((parentNodeType & 0x0f) == (nodeType & 0x0f)) {
    1398 
    1399         gatherChildren(nodeType, specNode->getFirst(), nodes);
    1400         gatherChildren(nodeType, rightNode, nodes);
    1401     }
    1402     else {
    1403         nodes->addElement(specNode);
    1404     }
    1405 }
    1406 
    1407 void
    1408 SchemaValidator::checkNSCompat(const ContentSpecNode* const derivedSpecNode,
    1409                                const ContentSpecNode* const baseSpecNode,
    1410                                const bool toCheckOccurence) {
    1411 
    1412     // check Occurrence ranges
    1413     if (toCheckOccurence &&
    1414         !isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(),
    1415                              baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) {
    1416         ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_OccurRangeE,
    1417                   derivedSpecNode->getElement()->getLocalPart(), fMemoryManager);
    1418     }
    1419 
    1420     // check wildcard subset
    1421     if (!wildcardEltAllowsNamespace(baseSpecNode, derivedSpecNode->getElement()->getURI())) {
    1422         ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NSCompat1,
    1423                   derivedSpecNode->getElement()->getLocalPart(), fMemoryManager);
    1424     }
    1425 }
    1426 
    1427 bool
    1428 SchemaValidator::wildcardEltAllowsNamespace(const ContentSpecNode* const baseSpecNode,
    1429                                             const unsigned int derivedURI) {
    1430 
    1431     ContentSpecNode::NodeTypes nodeType = baseSpecNode->getType();
    1432 
    1433     if ((nodeType & 0x0f) == ContentSpecNode::Any) {
    1434         return true;
    1435     }
    1436 
    1437     unsigned int baseURI = baseSpecNode->getElement()->getURI();
    1438 
    1439     if ((nodeType & 0x0f) == ContentSpecNode::Any_NS) {
    1440         if (derivedURI == baseURI) {
    1441            return true;
    1442         }
    1443     }
    1444     else { // must be ANY_OTHER
    1445         if (derivedURI != baseURI && derivedURI != getScanner()->getEmptyNamespaceId()) {
    1446             return true;
    1447         }
    1448     }
    1449 
    1450     return false;
    1451 }
    1452 
    1453 void
    1454 SchemaValidator::checkNameAndTypeOK(SchemaGrammar* const currentGrammar,
    1455                                     const ContentSpecNode* const derivedSpecNode,
    1456                                     const int derivedScope,
    1457                                     const ContentSpecNode* const baseSpecNode,
    1458                                     const int baseScope,
    1459                                     const ComplexTypeInfo* const baseInfo) {
    1460 
    1461     if (derivedSpecNode->getMaxOccurs() == 0)
    1462         return;
    1463 
    1464     unsigned int derivedURI = derivedSpecNode->getElement()->getURI();
    1465 
    1466     // case of mixed complex types with attributes only
    1467     if (derivedURI == XMLElementDecl::fgPCDataElemId) {
    1468         return;
    1469     }
    1470 
    1471     SchemaGrammar* dGrammar = currentGrammar;
    1472 
    1473     if (derivedURI != getScanner()->getEmptyNamespaceId())
    1474     {
    1475         const XMLCh* dURI = fGrammarResolver->getStringPool()->getValueForId(derivedURI);
    1476         dGrammar= (SchemaGrammar*) fGrammarResolver->getGrammar(dURI);
    1477     }
    1478 
    1479     if (!dGrammar) { //something is wrong
    1480         return;
    1481     }
    1482 
    1483     const XMLCh* derivedName = derivedSpecNode->getElement()->getLocalPart();
    1484 
    1485     SchemaElementDecl* derivedElemDecl = findElement(derivedScope, derivedURI, derivedName, dGrammar);
    1486 
    1487     if (!derivedElemDecl) {
    1488         return;
    1489     }
    1490 
    1491     const XMLCh* baseName = baseSpecNode->getElement()->getLocalPart();
    1492     unsigned int baseURI = baseSpecNode->getElement()->getURI();
    1493     bool subsGroup = false;
    1494 
    1495     if (!XMLString::equals(derivedName, baseName) || derivedURI != baseURI) {
    1496         // Check if derived is substitutable for base.
    1497         //
    1498         SchemaElementDecl* e = derivedElemDecl->getSubstitutionGroupElem ();
    1499 
    1500         for (; e != 0; e = e->getSubstitutionGroupElem ()) {
    1501             if (XMLString::equals(e->getBaseName (), baseName) && e->getURI () == baseURI) {
    1502                 break;
    1503             }
    1504         }
    1505 
    1506         if (e == 0) {
    1507             ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_NameTypeOK1, fMemoryManager);
    1508         }
    1509 
    1510         subsGroup = true;
    1511     }
    1512 
    1513     if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(),
    1514                              baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) {
    1515         ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_OccurRangeE, derivedName, fMemoryManager);
    1516     }
    1517 
    1518     // Find the schema grammar for the base element using the base type as
    1519     // a reference if it is available (it is unavailable if we are checking
    1520     // element group restriction which happens in redefine).
    1521     //
    1522     SchemaGrammar* bGrammar = dGrammar;
    1523 
    1524     if (baseInfo)
    1525     {
    1526         const XMLCh* baseTypeURI = baseInfo->getTypeUri ();
    1527 
    1528         if (baseTypeURI != 0 && *baseTypeURI != 0) // Non-empty namespace.
    1529             bGrammar= (SchemaGrammar*) fGrammarResolver->getGrammar(baseTypeURI);
    1530 
    1531         if (!bGrammar) { //something is wrong
    1532             return;
    1533         }
    1534     }
    1535 
    1536     SchemaElementDecl* baseElemDecl =
    1537         findElement(baseScope, baseURI, baseName, bGrammar, baseInfo);
    1538 
    1539     if (!baseElemDecl) {
    1540         return;
    1541     }
    1542 
    1543     int derivedFlags = derivedElemDecl->getMiscFlags();
    1544     int baseFlags = baseElemDecl->getMiscFlags();
    1545 
    1546     if (((baseFlags & SchemaSymbols::XSD_NILLABLE) == 0) &&
    1547                 ((derivedFlags & SchemaSymbols::XSD_NILLABLE) != 0)) {
    1548         ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK2, derivedName, fMemoryManager);
    1549     }
    1550 
    1551     const XMLCh* derivedDefVal = derivedElemDecl->getDefaultValue();
    1552     const XMLCh* baseDefVal = baseElemDecl->getDefaultValue();
    1553 
    1554     if (baseDefVal && (baseFlags & SchemaSymbols::XSD_FIXED) != 0 &&
    1555         ((derivedFlags & SchemaSymbols::XSD_FIXED) == 0 ||
    1556          !XMLString::equals(derivedDefVal, baseDefVal))) {
    1557         ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK3, derivedName, fMemoryManager);
    1558     }
    1559 
    1560     int derivedBlockSet = derivedElemDecl->getBlockSet();
    1561     int baseBlockSet = baseElemDecl->getBlockSet();
    1562 
    1563     if ((derivedBlockSet & baseBlockSet) != baseBlockSet) {
    1564         ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK4, derivedName, fMemoryManager);
    1565     }
    1566 
    1567     // check identity constraints
    1568     checkICRestriction(derivedElemDecl, baseElemDecl, derivedName, baseName);
    1569 
    1570     // check that the derived element's type is derived from the base's.
    1571     if (!subsGroup)
    1572         checkTypesOK(derivedElemDecl, baseElemDecl, derivedName);
    1573 }
    1574 
    1575 SchemaElementDecl*
    1576 SchemaValidator::findElement(const int scope, const unsigned int uriIndex,
    1577                              const XMLCh* const name,
    1578                              SchemaGrammar* const grammar,
    1579                              const ComplexTypeInfo* const typeInfo) {
    1580 
    1581     // check for element at given scope first
    1582     SchemaElementDecl* elemDecl = (SchemaElementDecl*) grammar->getElemDecl(uriIndex, name, 0, scope);
    1583 
    1584     // if not found, check at global scope
    1585     if (!elemDecl) {
    1586 
    1587         elemDecl = (SchemaElementDecl*)
    1588             grammar->getElemDecl(uriIndex, name, 0, Grammar::TOP_LEVEL_SCOPE);
    1589 
    1590         // if still not found, and base is specified, look it up there
    1591         if (!elemDecl && typeInfo) {
    1592 
    1593             const ComplexTypeInfo* baseInfo = typeInfo;
    1594 
    1595             while (baseInfo) {
    1596 
    1597                 elemDecl = (SchemaElementDecl*)
    1598                     grammar->getElemDecl(uriIndex, name, 0, baseInfo->getScopeDefined());
    1599 
    1600                 if (elemDecl) {
    1601                    break;
    1602                 }
    1603 
    1604                 baseInfo = baseInfo->getBaseComplexTypeInfo();
    1605             }
    1606         }
    1607     }
    1608 
    1609     return elemDecl;
    1610 }
    1611 
    1612 void
    1613 SchemaValidator::checkICRestriction(const SchemaElementDecl* const derivedElemDecl,
    1614                                    const SchemaElementDecl* const baseElemDecl,
    1615                                    const XMLCh* const derivedElemName,
    1616                                    const XMLCh* const baseElemName) {
    1617 
    1618     // REVIST - need to get more clarification
    1619     XMLSize_t derivedICCount = derivedElemDecl->getIdentityConstraintCount();
    1620     XMLSize_t baseICCount = baseElemDecl->getIdentityConstraintCount();
    1621 
    1622     if (derivedICCount > baseICCount) {
    1623         ThrowXMLwithMemMgr2(RuntimeException, XMLExcepts::PD_NameTypeOK6, derivedElemName, baseElemName, fMemoryManager);
    1624     }
    1625 
    1626     for (XMLSize_t i=0; i < derivedICCount; i++) {
    1627 
    1628         bool found = false;
    1629         IdentityConstraint* ic= derivedElemDecl->getIdentityConstraintAt(i);
    1630 
    1631         for (XMLSize_t j=0; j < baseICCount; j++) {
    1632             if (*ic == *(baseElemDecl->getIdentityConstraintAt(j))) {
    1633 
    1634                 found = true;
    1635                 break;
    1636             }
    1637         }
    1638 
    1639         if (!found) {
    1640             ThrowXMLwithMemMgr2(RuntimeException, XMLExcepts::PD_NameTypeOK7, derivedElemName, baseElemName, fMemoryManager);
    1641         }
    1642     }
    1643 }
    1644 
    1645 void
    1646 SchemaValidator::checkTypesOK(const SchemaElementDecl* const derivedElemDecl,
    1647                               const SchemaElementDecl* const baseElemDecl,
    1648                               const XMLCh* const derivedElemName) {
    1649 
    1650     SchemaElementDecl::ModelTypes baseType = baseElemDecl->getModelType();
    1651 
    1652     if (baseType == SchemaElementDecl::Any) {
    1653         return;
    1654     }
    1655 
    1656     ComplexTypeInfo* rInfo = derivedElemDecl->getComplexTypeInfo();
    1657     ComplexTypeInfo* bInfo = baseElemDecl->getComplexTypeInfo();
    1658 
    1659     if (derivedElemDecl->getModelType() == SchemaElementDecl::Simple) {
    1660 
    1661         if (baseType != SchemaElementDecl::Simple) {
    1662             ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK5, derivedElemName, fMemoryManager);
    1663         }
    1664 
    1665         if (!rInfo) {
    1666 
    1667             DatatypeValidator* bDV = baseElemDecl->getDatatypeValidator();
    1668 
    1669             if (bInfo || bDV == 0 ||
    1670                                 !bDV->isSubstitutableBy(derivedElemDecl->getDatatypeValidator())) {
    1671                 ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK5, derivedElemName, fMemoryManager);
    1672             }
    1673 
    1674             return;
    1675         }
    1676     }
    1677 
    1678     if (rInfo == bInfo)
    1679         return;
    1680 
    1681     for (; rInfo && rInfo != bInfo; rInfo = rInfo->getBaseComplexTypeInfo()) {
    1682         if (rInfo->getDerivedBy() != SchemaSymbols::XSD_RESTRICTION) {
    1683 
    1684             rInfo = 0;
    1685             break;
    1686         }
    1687     }
    1688 
    1689     if (!rInfo) {
    1690         ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK5, derivedElemName, fMemoryManager);
    1691     }
    1692 }
    1693 
    1694 void
    1695 SchemaValidator::checkRecurseAsIfGroup(SchemaGrammar* const currentGrammar,
    1696                                        ContentSpecNode* const derivedSpecNodeIn,
    1697                                        const int derivedScope,
    1698                                        const ContentSpecNode* const baseSpecNode,
    1699                                        const int baseScope,
    1700                                        ValueVectorOf<ContentSpecNode*>* const baseNodes,
    1701                                        const ComplexTypeInfo* const baseInfo) {
    1702 
    1703     ContentSpecNode::NodeTypes baseType = baseSpecNode->getType();
    1704     bool toLax = false;
    1705 
    1706     //Treat the element as if it were in a group of the same variety as base
    1707     ContentSpecNode derivedGroupNode(baseType, derivedSpecNodeIn, 0, false, true, fMemoryManager);
    1708     const ContentSpecNode* const derivedSpecNode = &derivedGroupNode;
    1709 
    1710     if ((baseSpecNode->getType() & 0x0f) == ContentSpecNode::Choice) {
    1711         toLax = true;
    1712     }
    1713 
    1714     // Instead of calling this routine, inline it
    1715     // checkRecurse(currentGrammar, &derivedGroupNode, derivedScope, &derivedNodes,
    1716     //             baseSpecNode, baseScope, baseNodes, baseInfo, toLax);
    1717 
    1718     if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(),
    1719                              baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) {
    1720         ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_Recurse1, fMemoryManager);
    1721     }
    1722 
    1723     // check for mapping of children
    1724     XMLExcepts::Codes codeToThrow = XMLExcepts::NoError;
    1725     XMLSize_t count2= baseNodes->size();
    1726     XMLSize_t current = 0;
    1727 
    1728     {
    1729         bool matched = false;
    1730 
    1731         for (XMLSize_t j = current; j < count2; j++) {
    1732 
    1733             ContentSpecNode* baseNode = baseNodes->elementAt(j);
    1734             current++;
    1735 
    1736             bool bDoBreak=false;    // workaround for Borland bug with 'break' in 'catch'
    1737             try {
    1738 
    1739                 checkParticleDerivationOk(currentGrammar, derivedSpecNodeIn,
    1740                                           derivedScope, baseNode, baseScope, baseInfo);
    1741                 matched = true;
    1742                 break;
    1743             }
    1744             catch(const XMLException&) {
    1745                 if (!toLax && baseNode->getMinTotalRange()) {
    1746                     bDoBreak=true;
    1747                 }
    1748             }
    1749             if(bDoBreak)
    1750                 break;
    1751         }
    1752 
    1753         // did not find a match
    1754         if (!matched) {
    1755             codeToThrow = XMLExcepts::PD_Recurse2;
    1756         }
    1757     }
    1758 
    1759     // Now, see if there are some elements in the base we didn't match up
    1760     // in case of Sequence or All
    1761     if (!toLax && codeToThrow == XMLExcepts::NoError) {
    1762         for (XMLSize_t j = current; j < count2; j++) {
    1763             if (baseNodes->elementAt(j)->getMinTotalRange() * baseSpecNode->getMinOccurs()) { //!emptiable
    1764                 codeToThrow =  XMLExcepts::PD_Recurse2;
    1765                 break;
    1766             }
    1767         }
    1768     }
    1769 
    1770     if (codeToThrow != XMLExcepts::NoError) {
    1771         ThrowXMLwithMemMgr(RuntimeException, codeToThrow, fMemoryManager);
    1772     }
    1773 }
    1774 
    1775 void
    1776 SchemaValidator::checkRecurse(SchemaGrammar* const currentGrammar,
    1777                               const ContentSpecNode* const derivedSpecNode,
    1778                               const int derivedScope,
    1779                               ValueVectorOf<ContentSpecNode*>* const derivedNodes,
    1780                               const ContentSpecNode* const baseSpecNode,
    1781                               const int baseScope,
    1782                               ValueVectorOf<ContentSpecNode*>* const baseNodes,
    1783                               const ComplexTypeInfo* const baseInfo,
    1784                               const bool toLax) {
    1785 
    1786     if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(),
    1787                              baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) {
    1788         ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_Recurse1, fMemoryManager);
    1789     }
    1790 
    1791     // check for mapping of children
    1792     XMLExcepts::Codes codeToThrow = XMLExcepts::NoError;
    1793     XMLSize_t count1= derivedNodes->size();
    1794     XMLSize_t count2= baseNodes->size();
    1795     XMLSize_t current = 0;
    1796 
    1797     for (XMLSize_t i=0; i<count1; i++) {
    1798 
    1799         bool matched = false;
    1800 
    1801         for (XMLSize_t j = current; j < count2; j++) {
    1802 
    1803             ContentSpecNode* baseNode = baseNodes->elementAt(j);
    1804             current++;
    1805 
    1806             bool bDoBreak=false;    // workaround for Borland bug with 'break' in 'catch'
    1807             try {
    1808 
    1809                 checkParticleDerivationOk(currentGrammar, derivedNodes->elementAt(i),
    1810                                           derivedScope, baseNode, baseScope, baseInfo);
    1811                 matched = true;
    1812                 break;
    1813             }
    1814             catch(const XMLException&) {
    1815                 if (!toLax && baseNode->getMinTotalRange()) {
    1816                     bDoBreak=true;
    1817                 }
    1818             }
    1819             if(bDoBreak)
    1820                 break;
    1821         }
    1822 
    1823         // did not find a match
    1824         if (!matched) {
    1825 
    1826             codeToThrow = XMLExcepts::PD_Recurse2;
    1827             break;
    1828         }
    1829     }
    1830 
    1831     // Now, see if there are some elements in the base we didn't match up
    1832     // in case of Sequence or All
    1833     if (!toLax && codeToThrow == XMLExcepts::NoError) {
    1834         for (XMLSize_t j = current; j < count2; j++) {
    1835             if (baseNodes->elementAt(j)->getMinTotalRange()) { //!emptiable
    1836                 codeToThrow =  XMLExcepts::PD_Recurse2;
    1837                 break;
    1838             }
    1839         }
    1840     }
    1841 
    1842     if (codeToThrow != XMLExcepts::NoError) {
    1843         ThrowXMLwithMemMgr(RuntimeException, codeToThrow, fMemoryManager);
    1844     }
    1845 }
    1846 
    1847 void SchemaValidator::checkNSSubset(const ContentSpecNode* const derivedSpecNode,
    1848                                     const ContentSpecNode* const baseSpecNode) {
    1849 
    1850     // check Occurrence ranges
    1851     if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(),
    1852                              baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) {
    1853         ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_NSSubset1, fMemoryManager);
    1854     }
    1855 
    1856     if (!isWildCardEltSubset(derivedSpecNode, baseSpecNode)) {
    1857         ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_NSSubset2, fMemoryManager);
    1858     }
    1859 }
    1860 
    1861 bool SchemaValidator::checkNSSubsetChoiceRoot(const ContentSpecNode* const derivedSpecNode,
    1862                                     const ContentSpecNode* const baseSpecNode) {
    1863     bool found = false;
    1864 
    1865     if (baseSpecNode->getType() == ContentSpecNode::Any_NS_Choice) {
    1866         const ContentSpecNode* first = baseSpecNode->getFirst();
    1867         const ContentSpecNode* second = baseSpecNode->getSecond();
    1868 
    1869         if (first) {
    1870             found = checkNSSubsetChoiceRoot(derivedSpecNode, first);
    1871             if (found) return true;
    1872         }
    1873         if (second) {
    1874             found = checkNSSubsetChoiceRoot(derivedSpecNode, second);
    1875             if (found) return true;
    1876         }
    1877     }
    1878     else { // should be Any_NS
    1879         found = checkNSSubsetChoice(derivedSpecNode, baseSpecNode);
    1880     }
    1881 
    1882     return found;
    1883 }
    1884 
    1885 bool SchemaValidator::checkNSSubsetChoice(const ContentSpecNode* const derivedSpecNode,
    1886                                     const ContentSpecNode* const baseSpecNode) {
    1887 
    1888     // check Occurrence ranges
    1889     if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(),
    1890                              baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) {
    1891         return false;
    1892     }
    1893 
    1894     if (!isWildCardEltSubset(derivedSpecNode, baseSpecNode)) {
    1895         return false;
    1896     }
    1897     return true;
    1898 }
    1899 
    1900 bool
    1901 SchemaValidator::isWildCardEltSubset(const ContentSpecNode* const derivedSpecNode,
    1902                                      const ContentSpecNode* const baseSpecNode) {
    1903 
    1904     ContentSpecNode::NodeTypes baseType = baseSpecNode->getType();
    1905 
    1906     if ((baseType & 0x0f) == ContentSpecNode::Any) {
    1907         return true;
    1908     }
    1909 
    1910     ContentSpecNode::NodeTypes derivedType = derivedSpecNode->getType();
    1911     unsigned int baseURI = baseSpecNode->getElement()->getURI();
    1912     unsigned int derivedURI = derivedSpecNode->getElement()->getURI();
    1913 
    1914     // Below we assume that empty string has id 1.
    1915     //
    1916     if (((derivedType & 0x0f) == ContentSpecNode::Any_Other) &&
    1917         ((baseType & 0x0f) == ContentSpecNode::Any_Other) &&
    1918         (baseURI == derivedURI || baseURI == 1)) {
    1919         return true;
    1920     }
    1921 
    1922     if ((derivedType & 0x0f) == ContentSpecNode::Any_NS) {
    1923 
    1924         if (((baseType & 0x0f) == ContentSpecNode::Any_NS) &&
    1925             baseURI == derivedURI) {
    1926             return true;
    1927         }
    1928 
    1929         if (((baseType & 0x0f) == ContentSpecNode::Any_Other) &&
    1930             (derivedURI == 1 || baseURI != derivedURI)) {
    1931             return true;
    1932         }
    1933     }
    1934 
    1935     return false;
    1936 }
    1937 
    1938 void
    1939 SchemaValidator::checkNSRecurseCheckCardinality(SchemaGrammar* const currentGrammar,
    1940                                                 const ContentSpecNode* const derivedSpecNode,
    1941                                                 ValueVectorOf<ContentSpecNode*>* const derivedNodes,
    1942                                                 const int derivedScope,
    1943                                                 ContentSpecNode* const baseSpecNode,
    1944                                                 const bool toCheckOccurence) {
    1945 
    1946     // Implement total range check
    1947     int derivedMin = derivedSpecNode->getMinTotalRange();
    1948     int derivedMax = derivedSpecNode->getMaxTotalRange();
    1949 
    1950     // check Occurrence ranges
    1951     if (toCheckOccurence &&
    1952         !isOccurrenceRangeOK(derivedMin, derivedMax, baseSpecNode->getMinOccurs(),
    1953                               baseSpecNode->getMaxOccurs())) {
    1954         ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_NSRecurseCheckCardinality1, fMemoryManager);
    1955     }
    1956 
    1957     // Check that each member of the group is a valid restriction of the wildcard
    1958     XMLSize_t nodesCount = derivedNodes->size();
    1959 
    1960     for (XMLSize_t i = 0; i < nodesCount; i++) {
    1961         checkParticleDerivationOk(currentGrammar, derivedNodes->elementAt(i), derivedScope, baseSpecNode, -1, 0, false);
    1962     }
    1963 }
    1964 
    1965 void
    1966 SchemaValidator::checkRecurseUnordered(SchemaGrammar* const currentGrammar,
    1967                                        const ContentSpecNode* const derivedSpecNode,
    1968                                        ValueVectorOf<ContentSpecNode*>* const derivedNodes,
    1969                                        const int derivedScope,
    1970                                        ContentSpecNode* const baseSpecNode,
    1971                                        ValueVectorOf<ContentSpecNode*>* const baseNodes,
    1972                                        const int baseScope,
    1973                                        const ComplexTypeInfo* const baseInfo) {
    1974 
    1975     // check Occurrence ranges
    1976     if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(),
    1977                              baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) {
    1978         ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_Recurse1, fMemoryManager);
    1979     }
    1980 
    1981     XMLExcepts::Codes  codeToThrow = XMLExcepts::NoError;
    1982     XMLSize_t          derivedCount= derivedNodes->size();
    1983     XMLSize_t          baseCount = baseNodes->size();
    1984     bool*              foundIt = (bool*) fMemoryManager->allocate
    1985     (
    1986         baseCount * sizeof(bool)
    1987     );//new bool[baseCount];
    1988     ArrayJanitor<bool> janFoundIt(foundIt, fMemoryManager);
    1989 
    1990     for (XMLSize_t k=0; k < baseCount; k++) {
    1991         foundIt[k] = false;
    1992     }
    1993 
    1994     // check for mapping of children
    1995     for (XMLSize_t i = 0; i < derivedCount; i++) {
    1996 
    1997         ContentSpecNode* derivedNode = derivedNodes->elementAt(i);
    1998         bool matched = false;
    1999 
    2000         for (XMLSize_t j = 0; j < baseCount; j++) {
    2001 
    2002             try {
    2003 
    2004                 checkParticleDerivationOk(currentGrammar, derivedNode, derivedScope,
    2005                                           baseNodes->elementAt(j), baseScope, baseInfo);
    2006 
    2007                 if (foundIt[j]) {
    2008                     break;
    2009                 }
    2010 
    2011                 foundIt[j] = true;
    2012                 matched = true;
    2013                 break;
    2014             }
    2015             catch (const XMLException&) {
    2016             }
    2017         }
    2018 
    2019         // didn't find a match.
    2020         if (!matched) {
    2021 
    2022                 codeToThrow = XMLExcepts::PD_RecurseUnordered;
    2023             break;
    2024         }
    2025     }
    2026 
    2027     // For all unmapped particles in base, check to see it it's emptiable or not
    2028     if (codeToThrow == XMLExcepts::NoError) {
    2029         for (XMLSize_t j=0; j < baseCount; j++) {
    2030             if (!foundIt[j] && baseNodes->elementAt(j)->getMinTotalRange()) {
    2031 
    2032                     codeToThrow = XMLExcepts::PD_RecurseUnordered;
    2033                 break;
    2034             }
    2035         }
    2036     }
    2037 
    2038     if (codeToThrow != XMLExcepts::NoError) {
    2039         ThrowXMLwithMemMgr(RuntimeException, codeToThrow, fMemoryManager);
    2040     }
    2041 }
    2042 
    2043 void
    2044 SchemaValidator::checkMapAndSum(SchemaGrammar* const currentGrammar,
    2045                                 const ContentSpecNode* const derivedSpecNode,
    2046                                 ValueVectorOf<ContentSpecNode*>* const derivedNodes,
    2047                                 const int derivedScope,
    2048                                 ContentSpecNode* const baseSpecNode,
    2049                                 ValueVectorOf<ContentSpecNode*>* const baseNodes,
    2050                                 const int baseScope,
    2051                                 const ComplexTypeInfo* const baseInfo) {
    2052 
    2053     // check Occurrence ranges
    2054     XMLSize_t derivedCount = derivedNodes->size();
    2055     XMLSize_t baseCount = baseNodes->size();
    2056     int derivedMin = derivedSpecNode->getMinOccurs() * (unsigned int)derivedCount;
    2057     int derivedMax = derivedSpecNode->getMaxOccurs();
    2058 
    2059     if (derivedMax != SchemaSymbols::XSD_UNBOUNDED) {
    2060         derivedMax *= (unsigned int)derivedCount;
    2061     }
    2062 
    2063     if (!isOccurrenceRangeOK(derivedMin, derivedMax, baseSpecNode->getMinOccurs(),
    2064                              baseSpecNode->getMaxOccurs())) {
    2065         ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_Recurse1, fMemoryManager);
    2066     }
    2067 
    2068     // check for mapping of children
    2069     for (XMLSize_t i = 0; i < derivedCount; i++) {
    2070 
    2071         ContentSpecNode* derivedNode = derivedNodes->elementAt(i);
    2072         bool matched = false;
    2073 
    2074         for (XMLSize_t j = 0; j < baseCount && !matched; j++) {
    2075 
    2076             try {
    2077 
    2078                 checkParticleDerivationOk(currentGrammar, derivedNode, derivedScope,
    2079                                           baseNodes->elementAt(j), baseScope, baseInfo);
    2080                 matched = true;
    2081             }
    2082             catch (const XMLException&) {
    2083             }
    2084         }
    2085 
    2086         // didn't find a match.
    2087         if (!matched) {
    2088                 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_MapAndSum, fMemoryManager);
    2089         }
    2090     }
    2091 
    2092 }
    2093 
    2094 XERCES_CPP_NAMESPACE_END
     1#include <icxercesc/validators/schema/SchemaValidator.cpp>
Note: See TracChangeset for help on using the changeset viewer.