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$
20  */
21 
22 // ---------------------------------------------------------------------------
23 //  Includes
24 // ---------------------------------------------------------------------------
25 #include <xercesc/framework/XMLBuffer.hpp>
26 #include <xercesc/validators/schema/ComplexTypeInfo.hpp>
27 #include <xercesc/validators/schema/SchemaAttDefList.hpp>
28 #include <xercesc/validators/common/AllContentModel.hpp>
29 #include <xercesc/validators/common/ContentSpecNode.hpp>
30 #include <xercesc/validators/common/DFAContentModel.hpp>
31 #include <xercesc/validators/common/MixedContentModel.hpp>
32 #include <xercesc/validators/common/SimpleContentModel.hpp>
33 #include <xercesc/validators/schema/XSDLocator.hpp>
34 #include <xercesc/internal/XTemplateSerializer.hpp>
35 #include <xercesc/util/XMLInitializer.hpp>
36 
37 XERCES_CPP_NAMESPACE_BEGIN
38 
39 // ---------------------------------------------------------------------------
40 //  ComplexTypeInfo: Static member data
41 // ---------------------------------------------------------------------------
42 ComplexTypeInfo* ComplexTypeInfo::fAnyType = 0;
43 
initializeComplexTypeInfo()44 void XMLInitializer::initializeComplexTypeInfo()
45 {
46   // create type name
47   XMLCh typeName[128];
48   XMLSize_t nsLen = XMLString::stringLen(SchemaSymbols::fgURI_SCHEMAFORSCHEMA);
49 
50   XMLString::copyString(typeName, SchemaSymbols::fgURI_SCHEMAFORSCHEMA);
51   typeName[nsLen] = chComma;
52   XMLString::copyString(typeName + nsLen + 1, SchemaSymbols::fgATTVAL_ANYTYPE);
53 
54   // Create and initialize 'anyType'
55   ComplexTypeInfo::fAnyType = new ComplexTypeInfo();
56 
57   ContentSpecNode* term = new ContentSpecNode
58     (
59       new QName
60       (
61         XMLUni::fgZeroLenString
62         , XMLUni::fgZeroLenString
63         , 1
64       )
65       , false
66     );
67   term->setType(ContentSpecNode::Any_Lax);
68   term->setMinOccurs(0);
69   term->setMaxOccurs(SchemaSymbols::XSD_UNBOUNDED);
70 
71   ContentSpecNode* particle = new ContentSpecNode
72     (
73       ContentSpecNode::ModelGroupSequence
74       , term
75       , 0
76     );
77 
78   SchemaAttDef* attWildCard = new SchemaAttDef
79     (
80       XMLUni::fgZeroLenString
81       , XMLUni::fgZeroLenString
82       , 1
83       , XMLAttDef::Any_Any
84       , XMLAttDef::ProcessContents_Lax
85     );
86 
87   ComplexTypeInfo::fAnyType->setTypeName(typeName);
88   ComplexTypeInfo::fAnyType->setBaseComplexTypeInfo(ComplexTypeInfo::fAnyType);
89   ComplexTypeInfo::fAnyType->setDerivedBy(SchemaSymbols::XSD_RESTRICTION);
90   ComplexTypeInfo::fAnyType->setContentType(SchemaElementDecl::Mixed_Complex);
91   ComplexTypeInfo::fAnyType->setContentSpec(particle);
92   ComplexTypeInfo::fAnyType->setAttWildCard(attWildCard);
93 }
94 
terminateComplexTypeInfo()95 void XMLInitializer::terminateComplexTypeInfo()
96 {
97   delete ComplexTypeInfo::fAnyType;
98   ComplexTypeInfo::fAnyType = 0;
99 }
100 
getAnyType(unsigned int)101 ComplexTypeInfo* ComplexTypeInfo::getAnyType(unsigned int /*emptyNSId*/)
102 {
103     return fAnyType;
104 }
105 
106 
107 // ---------------------------------------------------------------------------
108 //  ComplexTypeInfo: Constructors and Destructor
109 // ---------------------------------------------------------------------------
ComplexTypeInfo(MemoryManager * const manager)110 ComplexTypeInfo::ComplexTypeInfo(MemoryManager* const manager)
111     : fAnonymous(false)
112     , fAbstract(false)
113     , fAdoptContentSpec(true)
114     , fAttWithTypeId(false)
115     , fPreprocessed(false)
116     , fDerivedBy(0)
117     , fBlockSet(0)
118     , fFinalSet(0)
119     , fScopeDefined(Grammar::TOP_LEVEL_SCOPE)
120     , fContentType(SchemaElementDecl::Empty)
121     , fElementId(XMLElementDecl::fgInvalidElemId)
122     , fUniqueURI(0)
123     , fContentSpecOrgURISize(16)
124     , fTypeName(0)
125     , fTypeLocalName(0)
126     , fTypeUri(0)
127     , fBaseDatatypeValidator(0)
128     , fDatatypeValidator(0)
129     , fBaseComplexTypeInfo(0)
130     , fContentSpec(0)
131     , fAttWildCard(0)
132     , fAttList(0)
133     , fElements(0)
134     , fAttDefs(0)
135     , fContentModel(0)
136     , fFormattedModel(0)
137     , fContentSpecOrgURI(0)
138     , fLocator(0)
139     , fMemoryManager(manager)
140 {
141     fAttDefs = new (fMemoryManager) RefHash2KeysTableOf<SchemaAttDef>(29, true, fMemoryManager);
142     fAttList = new (fMemoryManager) SchemaAttDefList(fAttDefs,fMemoryManager);
143 }
144 
145 
~ComplexTypeInfo()146 ComplexTypeInfo::~ComplexTypeInfo()
147 {
148     fMemoryManager->deallocate(fTypeName); //delete [] fTypeName;
149     fMemoryManager->deallocate(fTypeLocalName); //delete [] fTypeLocalName;
150     fMemoryManager->deallocate(fTypeUri); //delete [] fTypeUri;
151 
152     if (fAdoptContentSpec) {
153         delete fContentSpec;
154     }
155 
156     delete fAttWildCard;
157     delete fAttDefs;
158     delete fAttList;
159     delete fElements;
160     delete fLocator;
161 
162     delete fContentModel;
163     fMemoryManager->deallocate(fFormattedModel); //delete [] fFormattedModel;
164     fMemoryManager->deallocate(fContentSpecOrgURI); //delete [] fContentSpecOrgURI;
165 
166 }
167 
168 // ---------------------------------------------------------------------------
169 //  ComplexTypeInfo: Setter methods
170 // ---------------------------------------------------------------------------
addAttDef(SchemaAttDef * const toAdd)171 void ComplexTypeInfo::addAttDef(SchemaAttDef* const toAdd) {
172 
173     // Tell this guy the element id of its parent (us)
174     toAdd->setElemId(getElementId());
175 
176     fAttDefs->put((void*)(toAdd->getAttName()->getLocalPart()),
177                           toAdd->getAttName()->getURI(), toAdd);
178     // update and/or create fAttList
179     fAttList->addAttDef(toAdd);
180 }
181 
setContentSpec(ContentSpecNode * const toAdopt)182 void ComplexTypeInfo::setContentSpec(ContentSpecNode* const toAdopt) {
183 
184     if (fContentSpec && fAdoptContentSpec) {
185         delete fContentSpec;
186     }
187 
188     fContentSpec = toAdopt;
189 }
190 
setLocator(XSDLocator * const aLocator)191 void ComplexTypeInfo::setLocator(XSDLocator* const aLocator) {
192 
193     if (fLocator)
194         delete fLocator;
195 
196     fLocator = aLocator;
197 }
198 
199 // ---------------------------------------------------------------------------
200 //  ComplexTypeInfo: Getter methods
201 // ---------------------------------------------------------------------------
getAttDefList() const202 XMLAttDefList& ComplexTypeInfo::getAttDefList() const
203 {
204     // NOTE: if users plan on using nextElement() to access attributes
205     //       they need to call Reset() explicitly (i.e attList.Reset()).
206     //       It's better to get the attribute count and use an index to
207     //       access attributes (especially if same grammar is used in
208     //       multiple threads).
209     return *fAttList;
210 }
211 
212 const XMLCh*
getFormattedContentModel() const213 ComplexTypeInfo::getFormattedContentModel() const
214 {
215     //
216     //  If its not already built, then call the protected virtual method
217     //  to allow the derived class to build it (since only it knows.)
218     //  Otherwise, just return the previously formatted methods.
219     //
220     //  Since we are faulting this in, within a const getter, we have to
221     //  cast off the const-ness.
222     //
223     if (!fFormattedModel)
224         ((ComplexTypeInfo*)this)->fFormattedModel = formatContentModel();
225 
226     return fFormattedModel;
227 }
228 
229 // ---------------------------------------------------------------------------
230 //  ComplexTypeInfo: Helper methods
231 // ---------------------------------------------------------------------------
checkUniqueParticleAttribution(SchemaGrammar * const pGrammar,GrammarResolver * const pGrammarResolver,XMLStringPool * const pStringPool,XMLValidator * const pValidator)232 void ComplexTypeInfo::checkUniqueParticleAttribution (SchemaGrammar*    const pGrammar,
233                                                       GrammarResolver*  const pGrammarResolver,
234                                                       XMLStringPool*    const pStringPool,
235                                                       XMLValidator*     const pValidator)
236 {
237     if (fContentSpec && !fContentModel)
238     {
239         fContentModel = makeContentModel(true);
240         if (fContentModel) {
241             fContentModel->checkUniqueParticleAttribution(pGrammar, pGrammarResolver, pStringPool, pValidator, fContentSpecOrgURI, fTypeLocalName);
242         }
243     }
244 }
245 
246 // ---------------------------------------------------------------------------
247 //  ComplexTypeInfo: Private Helper methods
248 // ---------------------------------------------------------------------------
faultInAttDefList() const249 void ComplexTypeInfo::faultInAttDefList() const
250 {
251     // Use a hash modulus of 29 and tell it owns its elements
252     ((ComplexTypeInfo*)this)->fAttDefs =
253         new (fMemoryManager) RefHash2KeysTableOf<SchemaAttDef>(29, true, fMemoryManager);
254 }
255 
formatContentModel() const256 XMLCh* ComplexTypeInfo::formatContentModel() const
257 {
258     XMLCh* newValue = 0;
259     if (fContentType == SchemaElementDecl::Any)
260     {
261         newValue = XMLString::replicate(XMLUni::fgAnyString, fMemoryManager);
262     }
263     else if (fContentType == SchemaElementDecl::Empty ||
264              fContentType == SchemaElementDecl::ElementOnlyEmpty)
265     {
266         newValue = XMLString::replicate(XMLUni::fgEmptyString, fMemoryManager);
267     }
268     else
269     {
270         //
271         //  Use a temp XML buffer to format into. Content models could be
272         //  pretty long, but very few will be longer than one K. The buffer
273         //  will expand to handle the more pathological ones.
274         //
275         const ContentSpecNode* specNode = fContentSpec;
276 
277         if (specNode) {
278             XMLBuffer bufFmt(1023, fMemoryManager);
279 
280             specNode->formatSpec(bufFmt);
281             newValue = XMLString::replicate
282             (
283                 bufFmt.getRawBuffer()
284                 , fMemoryManager
285             );
286         }
287     }
288     return newValue;
289 }
290 
useRepeatingLeafNodes(ContentSpecNode * particle)291 bool ComplexTypeInfo::useRepeatingLeafNodes(ContentSpecNode* particle)
292 {
293     int maxOccurs = particle->getMaxOccurs();
294     int minOccurs = particle->getMinOccurs();
295     ContentSpecNode::NodeTypes type = particle->getType();
296 
297     if (((type & 0x0f) == ContentSpecNode::Choice) ||  ((type & 0x0f) == ContentSpecNode::Sequence))
298     {
299         if (minOccurs != 1 || maxOccurs != 1) {
300             if(particle->getFirst()!=0 && particle->getSecond()==0)
301             {
302                 ContentSpecNode* particle2 = particle->getFirst();
303                 ContentSpecNode::NodeTypes type2 = particle2->getType();
304                 return (((type2 == ContentSpecNode::Leaf) ||
305                         ((type2 & 0x0f) == ContentSpecNode::Any) ||
306                         ((type2 & 0x0f) == ContentSpecNode::Any_Other) ||
307                         ((type2 & 0x0f) == ContentSpecNode::Any_NS)) &&
308                         particle2->getMinOccurs() == 1 &&
309                         particle2->getMaxOccurs() == 1);
310             }
311             return (particle->getFirst()==0 && particle->getSecond()==0);
312         }
313         if(particle->getFirst()!=0 && !useRepeatingLeafNodes(particle->getFirst()))
314             return false;
315         if(particle->getSecond()!=0 && !useRepeatingLeafNodes(particle->getSecond()))
316             return false;
317     }
318     return true;
319 }
320 
makeContentModel(bool checkUPA)321 XMLContentModel* ComplexTypeInfo::makeContentModel(bool checkUPA)
322 {
323     ContentSpecNode* aSpecNode = new (fMemoryManager) ContentSpecNode(*fContentSpec);
324 
325     if (checkUPA) {
326         fContentSpecOrgURI = (unsigned int*) fMemoryManager->allocate
327         (
328             fContentSpecOrgURISize * sizeof(unsigned int)
329         ); //new unsigned int[fContentSpecOrgURISize];
330     }
331 
332     aSpecNode = convertContentSpecTree(aSpecNode, checkUPA, useRepeatingLeafNodes(aSpecNode));
333 
334     Janitor<ContentSpecNode> janSpecNode(aSpecNode);
335 
336     XMLContentModel* cmRet = 0;
337     if (fContentType == SchemaElementDecl::Simple ||
338         fContentType == SchemaElementDecl::ElementOnlyEmpty) {
339        // just return nothing
340     }
341     else if (fContentType == SchemaElementDecl::Mixed_Simple)
342     {
343         //
344         //  Just create a mixel content model object. This type of
345         //  content model is optimized for mixed content validation.
346         //
347         cmRet = new (fMemoryManager) MixedContentModel(false, aSpecNode, false, fMemoryManager);
348     }
349     else if (fContentType == SchemaElementDecl::Mixed_Complex ||
350              fContentType == SchemaElementDecl::Children)
351     {
352         bool isMixed = (fContentType == SchemaElementDecl::Mixed_Complex);
353 
354         //
355         //  This method will create an optimal model for the complexity
356         //  of the element's defined model. If its simple, it will create
357         //  a SimpleContentModel object. If its a simple list, it will
358         //  create a SimpleListContentModel object. If its complex, it
359         //  will create a DFAContentModel object.
360         //
361         if(!aSpecNode)
362             ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_UnknownCMSpecType, fMemoryManager);
363 
364         ContentSpecNode::NodeTypes specType = aSpecNode->getType();
365         //
366         //  Do a sanity check that the node is does not have a PCDATA id. Since,
367         //  if it was, it should have already gotten taken by the Mixed model.
368         //
369         if (aSpecNode->getElement() && aSpecNode->getElement()->getURI() == XMLElementDecl::fgPCDataElemId)
370             ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_NoPCDATAHere, fMemoryManager);
371 
372         //
373         //  According to the type of node, we will create the correct type of
374         //  content model.
375         //
376         if (((specType & 0x0f) == ContentSpecNode::Any) ||
377            ((specType & 0x0f) == ContentSpecNode::Any_Other) ||
378            ((specType & 0x0f) == ContentSpecNode::Any_NS) ||
379            specType == ContentSpecNode::Loop) {
380            // let fall through to build a DFAContentModel
381         }
382         else if (isMixed)
383         {
384             if (specType == ContentSpecNode::All) {
385                 // All the nodes under an ALL must be additional ALL nodes and
386                 // ELEMENTs (or ELEMENTs under ZERO_OR_ONE nodes.)
387                 // We collapse the ELEMENTs into a single vector.
388                 cmRet = new (fMemoryManager) AllContentModel(aSpecNode, true, fMemoryManager);
389             }
390             else if (specType == ContentSpecNode::ZeroOrOne) {
391                 // An ALL node can appear under a ZERO_OR_ONE node.
392                 if (aSpecNode->getFirst()->getType() == ContentSpecNode::All) {
393                     cmRet = new (fMemoryManager) AllContentModel(aSpecNode->getFirst(), true, fMemoryManager);
394                 }
395             }
396 
397             // otherwise, let fall through to build a DFAContentModel
398         }
399          else if (specType == ContentSpecNode::Leaf)
400         {
401             // Create a simple content model
402             cmRet = new (fMemoryManager) SimpleContentModel
403             (
404                 false
405                 , aSpecNode->getElement()
406                 , 0
407                 , ContentSpecNode::Leaf
408                 , fMemoryManager
409             );
410         }
411          else if (((specType & 0x0f) == ContentSpecNode::Choice)
412               ||  ((specType & 0x0f) == ContentSpecNode::Sequence))
413         {
414             //
415             //  Lets see if both of the children are leafs. If so, then it has to
416             //  be a simple content model
417             //
418             if ((aSpecNode->getFirst()->getType() == ContentSpecNode::Leaf)
419             &&  (aSpecNode->getSecond())
420             &&  (aSpecNode->getSecond()->getType() == ContentSpecNode::Leaf))
421             {
422                 cmRet = new (fMemoryManager) SimpleContentModel
423                 (
424                     false
425                     , aSpecNode->getFirst()->getElement()
426                     , aSpecNode->getSecond()->getElement()
427                     , specType
428                     , fMemoryManager
429                 );
430             }
431         }
432          else if ((specType == ContentSpecNode::OneOrMore)
433               ||  (specType == ContentSpecNode::ZeroOrMore)
434               ||  (specType == ContentSpecNode::ZeroOrOne))
435         {
436             //
437             //  Its a repetition, so see if its one child is a leaf. If so its a
438             //  repetition of a single element, so we can do a simple content
439             //  model for that.
440             //
441             if (aSpecNode->getFirst()->getType() == ContentSpecNode::Leaf)
442             {
443                 cmRet = new (fMemoryManager) SimpleContentModel
444                 (
445                     false
446                     , aSpecNode->getFirst()->getElement()
447                     , 0
448                     , specType
449                     , fMemoryManager
450                 );
451             }
452             else if (aSpecNode->getFirst()->getType() == ContentSpecNode::All)
453                 cmRet = new (fMemoryManager) AllContentModel(aSpecNode->getFirst(), false, fMemoryManager);
454 
455         }
456         else if (specType == ContentSpecNode::All)
457             cmRet = new (fMemoryManager) AllContentModel(aSpecNode, false, fMemoryManager);
458         else
459         {
460             ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_UnknownCMSpecType, fMemoryManager);
461         }
462 
463         // Its not any simple type of content, so create a DFA based content model
464         if(cmRet==0)
465             cmRet = new (fMemoryManager) DFAContentModel(false, aSpecNode, isMixed, fMemoryManager);
466     }
467      else
468     {
469         ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_MustBeMixedOrChildren, fMemoryManager);
470     }
471 
472     return cmRet;
473 }
474 
475 // ---------------------------------------------------------------------------
476 //  SchemaElementDecl: Private helper methods
477 // ---------------------------------------------------------------------------
478 
479 ContentSpecNode*
convertContentSpecTree(ContentSpecNode * const curNode,bool checkUPA,bool bAllowCompactSyntax)480 ComplexTypeInfo::convertContentSpecTree(ContentSpecNode* const curNode,
481                                         bool checkUPA,
482                                         bool bAllowCompactSyntax) {
483 
484     if (!curNode)
485         return 0;
486 
487     const ContentSpecNode::NodeTypes curType = curNode->getType();
488 
489     // When checking Unique Particle Attribution, rename leaf elements
490     if (checkUPA) {
491         if (curNode->getElement()) {
492             if (fUniqueURI == fContentSpecOrgURISize) {
493                 resizeContentSpecOrgURI();
494             }
495 
496             fContentSpecOrgURI[fUniqueURI] = curNode->getElement()->getURI();
497             curNode->getElement()->setURI(fUniqueURI);
498             fUniqueURI++;
499         }
500     }
501 
502     // Get the spec type of the passed node
503     int minOccurs = curNode->getMinOccurs();
504     int maxOccurs = curNode->getMaxOccurs();
505     ContentSpecNode* retNode = curNode;
506 
507     if ((curType & 0x0f) == ContentSpecNode::Any
508         || (curType & 0x0f) == ContentSpecNode::Any_Other
509         || (curType & 0x0f) == ContentSpecNode::Any_NS
510         || curType == ContentSpecNode::Leaf)
511     {
512         retNode =  expandContentModel(curNode, minOccurs, maxOccurs, bAllowCompactSyntax);
513     }
514     else if (((curType & 0x0f) == ContentSpecNode::Choice)
515         ||   (curType == ContentSpecNode::All)
516         ||   ((curType & 0x0f) == ContentSpecNode::Sequence))
517     {
518         ContentSpecNode* childNode = curNode->getFirst();
519         ContentSpecNode* leftNode = convertContentSpecTree(childNode, checkUPA, bAllowCompactSyntax);
520         ContentSpecNode* rightNode = curNode->getSecond();
521 
522         if (!rightNode) {
523 
524             retNode = expandContentModel(leftNode, minOccurs, maxOccurs, bAllowCompactSyntax);
525             curNode->setAdoptFirst(false);
526             delete curNode;
527             return retNode;
528         }
529 
530         if (leftNode != childNode) {
531 
532             curNode->setAdoptFirst(false);
533             curNode->setFirst(leftNode);
534             curNode->setAdoptFirst(true);
535         }
536 
537         childNode = rightNode;
538         rightNode =  convertContentSpecTree(childNode, checkUPA, bAllowCompactSyntax);
539 
540         if (rightNode != childNode) {
541 
542             curNode->setAdoptSecond(false);
543             curNode->setSecond(rightNode);
544             curNode->setAdoptSecond(true);
545         }
546 
547         retNode =  expandContentModel(curNode, minOccurs, maxOccurs, bAllowCompactSyntax);
548     }
549 
550     return retNode;
551 }
552 
expandContentModel(ContentSpecNode * const specNode,int minOccurs,int maxOccurs,bool bAllowCompactSyntax)553 ContentSpecNode* ComplexTypeInfo::expandContentModel(ContentSpecNode* const specNode,
554                                                      int minOccurs,
555                                                      int maxOccurs,
556                                                      bool bAllowCompactSyntax)
557 {
558     if (!specNode) {
559         return 0;
560     }
561 
562     ContentSpecNode* saveNode = specNode;
563     ContentSpecNode* retNode = specNode;
564 
565     if (minOccurs == 1 && maxOccurs == 1) {
566     }
567     else if (minOccurs == 0 && maxOccurs == 1) {
568 
569         retNode = new (fMemoryManager) ContentSpecNode
570         (
571             ContentSpecNode::ZeroOrOne
572             , retNode
573             , 0
574             , true
575             , true
576             , fMemoryManager
577         );
578     }
579     else if (minOccurs == 0 && maxOccurs == -1) {
580         retNode = new (fMemoryManager) ContentSpecNode
581         (
582             ContentSpecNode::ZeroOrMore
583             , retNode
584             , 0
585             , true
586             , true
587             , fMemoryManager
588         );
589     }
590     else if (minOccurs == 1 && maxOccurs == -1) {
591         retNode = new (fMemoryManager) ContentSpecNode
592         (
593             ContentSpecNode::OneOrMore
594             , retNode
595             , 0
596             , true
597             , true
598             , fMemoryManager
599         );
600     }
601     // if what is being repeated is a leaf avoid expanding the tree
602     else if(bAllowCompactSyntax &&
603         (saveNode->getType()==ContentSpecNode::Leaf ||
604         (saveNode->getType() & 0x0f)==ContentSpecNode::Any ||
605         (saveNode->getType() & 0x0f)==ContentSpecNode::Any_Other ||
606         (saveNode->getType() & 0x0f)==ContentSpecNode::Any_NS))
607     {
608         retNode = new (fMemoryManager) ContentSpecNode
609         (
610             ContentSpecNode::Loop
611             , retNode
612             , 0
613             , true
614             , true
615             , fMemoryManager
616         );
617         retNode->setMinOccurs(minOccurs);
618         retNode->setMaxOccurs(maxOccurs);
619 
620         if(minOccurs==0)
621             retNode = new (fMemoryManager) ContentSpecNode
622             (
623                 ContentSpecNode::ZeroOrMore
624                 , retNode
625                 , 0
626                 , true
627                 , true
628                 , fMemoryManager
629             );
630         else
631             retNode = new (fMemoryManager) ContentSpecNode
632             (
633                 ContentSpecNode::OneOrMore
634                 , retNode
635                 , 0
636                 , true
637                 , true
638                 , fMemoryManager
639             );
640 
641     }
642     else if (maxOccurs == -1) {
643 
644         retNode = new (fMemoryManager) ContentSpecNode
645         (
646             ContentSpecNode::OneOrMore
647             , retNode
648             , 0
649             , true
650             , true
651             , fMemoryManager
652         );
653 
654         for (int i=0; i < (minOccurs-1); i++) {
655             retNode = new (fMemoryManager) ContentSpecNode
656             (
657                 ContentSpecNode::Sequence
658                 , saveNode
659                 , retNode
660                 , false
661                 , true
662                 , fMemoryManager
663             );
664         }
665     }
666     else {
667 
668         if (minOccurs == 0) {
669 
670             ContentSpecNode* optional = new (fMemoryManager) ContentSpecNode
671             (
672                 ContentSpecNode::ZeroOrOne
673                 , saveNode
674                 , 0
675                 , true
676                 , true
677                 , fMemoryManager
678             );
679 
680             retNode = optional;
681 
682             for (int i=0; i < (maxOccurs-1); i++) {
683                 retNode = new (fMemoryManager) ContentSpecNode
684                 (
685                     ContentSpecNode::Sequence
686                     , retNode
687                     , optional
688                     , true
689                     , false
690                     , fMemoryManager
691                 );
692             }
693         }
694         else {
695 
696             if (minOccurs > 1) {
697 
698                 retNode = new (fMemoryManager) ContentSpecNode
699                 (
700                     ContentSpecNode::Sequence
701                     , retNode
702                     , saveNode
703                     , true
704                     , false
705                     , fMemoryManager
706                 );
707 
708                 for (int i=1; i < (minOccurs-1); i++) {
709                     retNode = new (fMemoryManager) ContentSpecNode
710                     (
711                         ContentSpecNode::Sequence
712                         , retNode
713                         , saveNode
714                         , true
715                         , false
716                         , fMemoryManager
717                     );
718                 }
719             }
720 
721             int counter = maxOccurs-minOccurs;
722 
723             if (counter > 0) {
724 
725                 ContentSpecNode* optional = new (fMemoryManager) ContentSpecNode
726                 (
727                     ContentSpecNode::ZeroOrOne
728                     , saveNode
729                     , 0
730                     , false
731                     , true
732                     , fMemoryManager
733                 );
734 
735                 retNode = new (fMemoryManager) ContentSpecNode
736                 (
737                     ContentSpecNode::Sequence
738                     , retNode
739                     , optional
740                     , true
741                     , true
742                     , fMemoryManager
743                 );
744 
745                 for (int j=1; j < counter; j++) {
746 
747                     retNode = new (fMemoryManager) ContentSpecNode
748                     (
749                         ContentSpecNode::Sequence
750                         , retNode
751                         , optional
752                         , true
753                         , false
754                         , fMemoryManager
755                     );
756                 }
757             }
758         }
759     }
760 
761     return retNode;
762 }
763 
resizeContentSpecOrgURI()764 void ComplexTypeInfo::resizeContentSpecOrgURI() {
765 
766     unsigned int newSize = fContentSpecOrgURISize * 2;
767     unsigned int* newContentSpecOrgURI = (unsigned int*) fMemoryManager->allocate
768     (
769         newSize * sizeof(unsigned int)
770     ); //new unsigned int[newSize];
771 
772     // Copy the existing values
773     unsigned int index = 0;
774     for (; index < fContentSpecOrgURISize; index++)
775         newContentSpecOrgURI[index] = fContentSpecOrgURI[index];
776 
777     for (; index < newSize; index++)
778         newContentSpecOrgURI[index] = 0;
779 
780     // Delete the old array and udpate our members
781     fMemoryManager->deallocate(fContentSpecOrgURI); //delete [] fContentSpecOrgURI;
782     fContentSpecOrgURI = newContentSpecOrgURI;
783     fContentSpecOrgURISize = newSize;
784 }
785 
786 /***
787  * Support for Serialization/De-serialization
788  ***/
789 
IMPL_XSERIALIZABLE_TOCREATE(ComplexTypeInfo)790 IMPL_XSERIALIZABLE_TOCREATE(ComplexTypeInfo)
791 
792 void ComplexTypeInfo::serialize(XSerializeEngine& serEng)
793 {
794 
795     if (serEng.isStoring())
796     {
797         serEng<<fAnonymous;
798         serEng<<fAbstract;
799         serEng<<fAdoptContentSpec;
800         serEng<<fAttWithTypeId;
801         serEng<<fPreprocessed;
802         serEng<<fDerivedBy;
803         serEng<<fBlockSet;
804         serEng<<fFinalSet;
805         serEng<<fScopeDefined;
806         serEng<<fContentType;
807 
808         serEng<<fElementId;
809 
810         serEng.writeString(fTypeName);
811         serEng.writeString(fTypeLocalName);
812         serEng.writeString(fTypeUri);
813 
814         DatatypeValidator::storeDV(serEng, fBaseDatatypeValidator);
815         DatatypeValidator::storeDV(serEng, fDatatypeValidator);
816 
817         serEng<<fBaseComplexTypeInfo;
818         serEng<<fContentSpec;
819         serEng<<fAttWildCard;
820         serEng<<fAttList;
821 
822         /***
823          *
824          * Serialize RefVectorOf<SchemaElementDecl>*    fElements;
825          * Serialize RefHash2KeysTableOf<SchemaAttDef>* fAttDefs;
826          ***/
827         XTemplateSerializer::storeObject(fElements, serEng);
828         XTemplateSerializer::storeObject(fAttDefs, serEng);
829 
830          /***
831           *   Don't serialize
832           *
833           *   fContentModel;
834           *   fFormattedModel;
835           *   fLocator;
836           *
837           *   fContentSpecOrgURI:     start of the array
838           *   fContentSpecOrgURISize: size of the array
839           *   fUniqueURI:             the current last element in the array
840           ***/
841     }
842     else
843     {
844         serEng>>fAnonymous;
845         serEng>>fAbstract;
846         serEng>>fAdoptContentSpec;
847         serEng>>fAttWithTypeId;
848         serEng>>fPreprocessed;
849         serEng>>fDerivedBy;
850         serEng>>fBlockSet;
851         serEng>>fFinalSet;
852         serEng>>fScopeDefined;
853         serEng>>fContentType;
854 
855         serEng>>fElementId;
856 
857         serEng.readString(fTypeName);
858         serEng.readString(fTypeLocalName);
859         serEng.readString(fTypeUri);
860 
861         fBaseDatatypeValidator = DatatypeValidator::loadDV(serEng);
862         fDatatypeValidator     = DatatypeValidator::loadDV(serEng);
863 
864         serEng>>fBaseComplexTypeInfo;
865         serEng>>fContentSpec;
866         serEng>>fAttWildCard;
867         delete fAttList; // will recreate it next...
868         serEng>>fAttList;
869 
870         /***
871          *
872          * Deserialize RefVectorOf<SchemaElementDecl>*    fElements;
873          * Deserialize RefHash2KeysTableOf<SchemaAttDef>* fAttDefs;
874          ***/
875         XTemplateSerializer::loadObject(&fElements, 8, false, serEng);
876         delete fAttDefs; // will recreate it next...
877         XTemplateSerializer::loadObject(&fAttDefs, 29, true, serEng);
878 
879          /***
880           *   Don't deserialize
881           *
882           *   fFormattedModel;
883           *   fLocator;
884           *
885           *   fContentSpecOrgURI:     start of the array
886           *   fContentSpecOrgURISize: size of the array
887           *   fUniqueURI:             the current last element in the array
888           ***/
889 
890          fFormattedModel = 0;
891          fLocator = 0;
892          fContentSpecOrgURI = 0;
893          fContentSpecOrgURISize = 0;
894          fUniqueURI = 0;
895 
896          // Create the content model by calling getContentModel().  This
897          // will ensure the grammar can be used concurrently by multiple
898          // parsers.
899          // Don't bother to do check unique particle attribution, since
900          // this will already have been done when the grammar was first
901          // created (if full schema checking was enabled).
902          getContentModel(false);
903     }
904 }
905 
906 
907 XERCES_CPP_NAMESPACE_END
908 
909 /**
910   * End of file ComplexTypeInfo.cpp
911   */
912