source: icXML/icXML-devel/src/xercesc/validators/schema/SchemaValidator.cpp @ 2734

Last change on this file since 2734 was 2734, checked in by cameron, 6 years ago

More paths and missing files.

File size: 81.5 KB
Line 
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
45XERCES_CPP_NAMESPACE_BEGIN
46
47// ---------------------------------------------------------------------------
48//  SchemaValidator: Constructors and Destructor
49// ---------------------------------------------------------------------------
50SchemaValidator::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
74SchemaValidator::~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// ---------------------------------------------------------------------------
86bool 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
317void 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
337void 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
352bool SchemaValidator::requiresNamespaces() const
353{
354    return true;
355}
356
357void 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
531void 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
756void 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
958void 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//
978void 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// ---------------------------------------------------------------------------
1055void 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// ---------------------------------------------------------------------------
1111void 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
1133ContentSpecNode* 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
1149void 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
1346ContentSpecNode*
1347SchemaValidator::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
1372void 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
1407void
1408SchemaValidator::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
1427bool
1428SchemaValidator::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
1453void
1454SchemaValidator::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
1575SchemaElementDecl*
1576SchemaValidator::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
1612void
1613SchemaValidator::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
1645void
1646SchemaValidator::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
1694void
1695SchemaValidator::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
1775void
1776SchemaValidator::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
1847void 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
1861bool 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
1885bool 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
1900bool
1901SchemaValidator::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
1938void
1939SchemaValidator::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
1965void
1966SchemaValidator::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
2043void
2044SchemaValidator::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
2094XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.