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

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

Various fixes

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