source: icXML/icXML-devel/src/icxercesc/validators/schema/SchemaValidator.cpp @ 2740

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

icXML-modified Schema validator files

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