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
9
* http://www.apache.org/licenses/LICENSE-2.0
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.
19
* $Id: ComplexTypeInfo.cpp 707375 2008-10-23 13:53:23Z amassari $
22
// ---------------------------------------------------------------------------
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>
37
XERCES_CPP_NAMESPACE_BEGIN
39
// ---------------------------------------------------------------------------
40
// ComplexTypeInfo: Static member data
41
// ---------------------------------------------------------------------------
42
ComplexTypeInfo* ComplexTypeInfo::fAnyType = 0;
44
void XMLInitializer::initializeComplexTypeInfo()
48
XMLSize_t nsLen = XMLString::stringLen(SchemaSymbols::fgURI_SCHEMAFORSCHEMA);
50
XMLString::copyString(typeName, SchemaSymbols::fgURI_SCHEMAFORSCHEMA);
51
typeName[nsLen] = chComma;
52
XMLString::copyString(typeName + nsLen + 1, SchemaSymbols::fgATTVAL_ANYTYPE);
54
// Create and initialize 'anyType'
55
ComplexTypeInfo::fAnyType = new ComplexTypeInfo();
57
ContentSpecNode* term = new ContentSpecNode
61
XMLUni::fgZeroLenString
62
, XMLUni::fgZeroLenString
67
term->setType(ContentSpecNode::Any_Lax);
68
term->setMinOccurs(0);
69
term->setMaxOccurs(SchemaSymbols::XSD_UNBOUNDED);
71
ContentSpecNode* particle = new ContentSpecNode
73
ContentSpecNode::ModelGroupSequence
78
SchemaAttDef* attWildCard = new SchemaAttDef
80
XMLUni::fgZeroLenString
81
, XMLUni::fgZeroLenString
84
, XMLAttDef::ProcessContents_Lax
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);
95
void XMLInitializer::terminateComplexTypeInfo()
97
delete ComplexTypeInfo::fAnyType;
98
ComplexTypeInfo::fAnyType = 0;
101
ComplexTypeInfo* ComplexTypeInfo::getAnyType(unsigned int emptyNSId)
107
// ---------------------------------------------------------------------------
108
// ComplexTypeInfo: Constructors and Destructor
109
// ---------------------------------------------------------------------------
110
ComplexTypeInfo::ComplexTypeInfo(MemoryManager* const manager)
113
, fAdoptContentSpec(true)
114
, fAttWithTypeId(false)
115
, fPreprocessed(false)
119
, fScopeDefined(Grammar::TOP_LEVEL_SCOPE)
120
, fContentType(SchemaElementDecl::Empty)
121
, fElementId(XMLElementDecl::fgInvalidElemId)
123
, fContentSpecOrgURISize(16)
127
, fBaseDatatypeValidator(0)
128
, fDatatypeValidator(0)
129
, fBaseComplexTypeInfo(0)
137
, fContentSpecOrgURI(0)
139
, fMemoryManager(manager)
141
fAttDefs = new (fMemoryManager) RefHash2KeysTableOf<SchemaAttDef>(29, true, fMemoryManager);
142
fAttList = new (fMemoryManager) SchemaAttDefList(fAttDefs,fMemoryManager);
146
ComplexTypeInfo::~ComplexTypeInfo()
148
fMemoryManager->deallocate(fTypeName); //delete [] fTypeName;
149
fMemoryManager->deallocate(fTypeLocalName); //delete [] fTypeLocalName;
150
fMemoryManager->deallocate(fTypeUri); //delete [] fTypeUri;
152
if (fAdoptContentSpec) {
162
delete fContentModel;
163
fMemoryManager->deallocate(fFormattedModel); //delete [] fFormattedModel;
164
fMemoryManager->deallocate(fContentSpecOrgURI); //delete [] fContentSpecOrgURI;
168
// ---------------------------------------------------------------------------
169
// ComplexTypeInfo: Setter methods
170
// ---------------------------------------------------------------------------
171
void ComplexTypeInfo::addAttDef(SchemaAttDef* const toAdd) {
173
// Tell this guy the element id of its parent (us)
174
toAdd->setElemId(getElementId());
176
fAttDefs->put((void*)(toAdd->getAttName()->getLocalPart()),
177
toAdd->getAttName()->getURI(), toAdd);
178
// update and/or create fAttList
179
fAttList->addAttDef(toAdd);
182
void ComplexTypeInfo::setContentSpec(ContentSpecNode* const toAdopt) {
184
if (fContentSpec && fAdoptContentSpec) {
188
fContentSpec = toAdopt;
191
void ComplexTypeInfo::setLocator(XSDLocator* const aLocator) {
199
// ---------------------------------------------------------------------------
200
// ComplexTypeInfo: Getter methods
201
// ---------------------------------------------------------------------------
202
XMLAttDefList& ComplexTypeInfo::getAttDefList() const
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).
213
ComplexTypeInfo::getFormattedContentModel() const
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.
220
// Since we are faulting this in, within a const getter, we have to
221
// cast off the const-ness.
223
if (!fFormattedModel)
224
((ComplexTypeInfo*)this)->fFormattedModel = formatContentModel();
226
return fFormattedModel;
229
// ---------------------------------------------------------------------------
230
// ComplexTypeInfo: Helper methods
231
// ---------------------------------------------------------------------------
232
void ComplexTypeInfo::checkUniqueParticleAttribution (SchemaGrammar* const pGrammar,
233
GrammarResolver* const pGrammarResolver,
234
XMLStringPool* const pStringPool,
235
XMLValidator* const pValidator)
237
if (fContentSpec && !fContentModel)
239
fContentModel = makeContentModel(true);
241
fContentModel->checkUniqueParticleAttribution(pGrammar, pGrammarResolver, pStringPool, pValidator, fContentSpecOrgURI, fTypeLocalName);
246
// ---------------------------------------------------------------------------
247
// ComplexTypeInfo: Private Helper methods
248
// ---------------------------------------------------------------------------
249
void ComplexTypeInfo::faultInAttDefList() const
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);
256
XMLCh* ComplexTypeInfo::formatContentModel() const
259
if (fContentType == SchemaElementDecl::Any)
261
newValue = XMLString::replicate(XMLUni::fgAnyString, fMemoryManager);
263
else if (fContentType == SchemaElementDecl::Empty ||
264
fContentType == SchemaElementDecl::ElementOnlyEmpty)
266
newValue = XMLString::replicate(XMLUni::fgEmptyString, fMemoryManager);
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.
275
const ContentSpecNode* specNode = fContentSpec;
278
XMLBuffer bufFmt(1023, fMemoryManager);
280
specNode->formatSpec(bufFmt);
281
newValue = XMLString::replicate
283
bufFmt.getRawBuffer()
291
bool ComplexTypeInfo::useRepeatingLeafNodes(ContentSpecNode* particle)
293
int maxOccurs = particle->getMaxOccurs();
294
int minOccurs = particle->getMinOccurs();
295
ContentSpecNode::NodeTypes type = particle->getType();
297
if (((type & 0x0f) == ContentSpecNode::Choice) || ((type & 0x0f) == ContentSpecNode::Sequence))
299
if (minOccurs != 1 || maxOccurs != 1) {
300
if(particle->getFirst()!=0 && particle->getSecond()==0)
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);
311
return (particle->getFirst()==0 && particle->getSecond()==0);
313
if(particle->getFirst()!=0 && !useRepeatingLeafNodes(particle->getFirst()))
315
if(particle->getSecond()!=0 && !useRepeatingLeafNodes(particle->getSecond()))
321
XMLContentModel* ComplexTypeInfo::makeContentModel(bool checkUPA)
323
ContentSpecNode* aSpecNode = new (fMemoryManager) ContentSpecNode(*fContentSpec);
326
fContentSpecOrgURI = (unsigned int*) fMemoryManager->allocate
328
fContentSpecOrgURISize * sizeof(unsigned int)
329
); //new unsigned int[fContentSpecOrgURISize];
332
aSpecNode = convertContentSpecTree(aSpecNode, checkUPA, useRepeatingLeafNodes(aSpecNode));
334
Janitor<ContentSpecNode> janSpecNode(aSpecNode);
336
XMLContentModel* cmRet = 0;
337
if (fContentType == SchemaElementDecl::Simple ||
338
fContentType == SchemaElementDecl::ElementOnlyEmpty) {
339
// just return nothing
341
else if (fContentType == SchemaElementDecl::Mixed_Simple)
344
// Just create a mixel content model object. This type of
345
// content model is optimized for mixed content validation.
347
cmRet = new (fMemoryManager) MixedContentModel(false, aSpecNode, false, fMemoryManager);
349
else if (fContentType == SchemaElementDecl::Mixed_Complex ||
350
fContentType == SchemaElementDecl::Children)
352
bool isMixed = (fContentType == SchemaElementDecl::Mixed_Complex);
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.
362
ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_UnknownCMSpecType, fMemoryManager);
364
ContentSpecNode::NodeTypes specType = aSpecNode->getType();
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.
369
if (aSpecNode->getElement() && aSpecNode->getElement()->getURI() == XMLElementDecl::fgPCDataElemId)
370
ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_NoPCDATAHere, fMemoryManager);
373
// According to the type of node, we will create the correct type of
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
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);
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);
397
// otherwise, let fall through to build a DFAContentModel
399
else if (specType == ContentSpecNode::Leaf)
401
// Create a simple content model
402
cmRet = new (fMemoryManager) SimpleContentModel
405
, aSpecNode->getElement()
407
, ContentSpecNode::Leaf
411
else if (((specType & 0x0f) == ContentSpecNode::Choice)
412
|| ((specType & 0x0f) == ContentSpecNode::Sequence))
415
// Lets see if both of the children are leafs. If so, then it has to
416
// be a simple content model
418
if ((aSpecNode->getFirst()->getType() == ContentSpecNode::Leaf)
419
&& (aSpecNode->getSecond())
420
&& (aSpecNode->getSecond()->getType() == ContentSpecNode::Leaf))
422
cmRet = new (fMemoryManager) SimpleContentModel
425
, aSpecNode->getFirst()->getElement()
426
, aSpecNode->getSecond()->getElement()
432
else if ((specType == ContentSpecNode::OneOrMore)
433
|| (specType == ContentSpecNode::ZeroOrMore)
434
|| (specType == ContentSpecNode::ZeroOrOne))
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
441
if (aSpecNode->getFirst()->getType() == ContentSpecNode::Leaf)
443
cmRet = new (fMemoryManager) SimpleContentModel
446
, aSpecNode->getFirst()->getElement()
452
else if (aSpecNode->getFirst()->getType() == ContentSpecNode::All)
453
cmRet = new (fMemoryManager) AllContentModel(aSpecNode->getFirst(), false, fMemoryManager);
456
else if (specType == ContentSpecNode::All)
457
cmRet = new (fMemoryManager) AllContentModel(aSpecNode, false, fMemoryManager);
460
ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_UnknownCMSpecType, fMemoryManager);
463
// Its not any simple type of content, so create a DFA based content model
465
cmRet = new (fMemoryManager) DFAContentModel(false, aSpecNode, isMixed, fMemoryManager);
469
ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_MustBeMixedOrChildren, fMemoryManager);
475
// ---------------------------------------------------------------------------
476
// SchemaElementDecl: Private helper methods
477
// ---------------------------------------------------------------------------
480
ComplexTypeInfo::convertContentSpecTree(ContentSpecNode* const curNode,
482
bool bAllowCompactSyntax) {
487
const ContentSpecNode::NodeTypes curType = curNode->getType();
489
// When checking Unique Particle Attribution, rename leaf elements
491
if (curNode->getElement()) {
492
if (fUniqueURI == fContentSpecOrgURISize) {
493
resizeContentSpecOrgURI();
496
fContentSpecOrgURI[fUniqueURI] = curNode->getElement()->getURI();
497
curNode->getElement()->setURI(fUniqueURI);
502
// Get the spec type of the passed node
503
int minOccurs = curNode->getMinOccurs();
504
int maxOccurs = curNode->getMaxOccurs();
505
ContentSpecNode* retNode = curNode;
507
if ((curType & 0x0f) == ContentSpecNode::Any
508
|| (curType & 0x0f) == ContentSpecNode::Any_Other
509
|| (curType & 0x0f) == ContentSpecNode::Any_NS
510
|| curType == ContentSpecNode::Leaf)
512
retNode = expandContentModel(curNode, minOccurs, maxOccurs, bAllowCompactSyntax);
514
else if (((curType & 0x0f) == ContentSpecNode::Choice)
515
|| (curType == ContentSpecNode::All)
516
|| ((curType & 0x0f) == ContentSpecNode::Sequence))
518
ContentSpecNode* childNode = curNode->getFirst();
519
ContentSpecNode* leftNode = convertContentSpecTree(childNode, checkUPA, bAllowCompactSyntax);
520
ContentSpecNode* rightNode = curNode->getSecond();
524
retNode = expandContentModel(leftNode, minOccurs, maxOccurs, bAllowCompactSyntax);
525
curNode->setAdoptFirst(false);
530
if (leftNode != childNode) {
532
curNode->setAdoptFirst(false);
533
curNode->setFirst(leftNode);
534
curNode->setAdoptFirst(true);
537
childNode = rightNode;
538
rightNode = convertContentSpecTree(childNode, checkUPA, bAllowCompactSyntax);
540
if (rightNode != childNode) {
542
curNode->setAdoptSecond(false);
543
curNode->setSecond(rightNode);
544
curNode->setAdoptSecond(true);
547
retNode = expandContentModel(curNode, minOccurs, maxOccurs, bAllowCompactSyntax);
553
ContentSpecNode* ComplexTypeInfo::expandContentModel(ContentSpecNode* const specNode,
556
bool bAllowCompactSyntax)
562
ContentSpecNode* saveNode = specNode;
563
ContentSpecNode* retNode = specNode;
565
if (minOccurs == 1 && maxOccurs == 1) {
567
else if (minOccurs == 0 && maxOccurs == 1) {
569
retNode = new (fMemoryManager) ContentSpecNode
571
ContentSpecNode::ZeroOrOne
579
else if (minOccurs == 0 && maxOccurs == -1) {
580
retNode = new (fMemoryManager) ContentSpecNode
582
ContentSpecNode::ZeroOrMore
590
else if (minOccurs == 1 && maxOccurs == -1) {
591
retNode = new (fMemoryManager) ContentSpecNode
593
ContentSpecNode::OneOrMore
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))
608
retNode = new (fMemoryManager) ContentSpecNode
610
ContentSpecNode::Loop
617
retNode->setMinOccurs(minOccurs);
618
retNode->setMaxOccurs(maxOccurs);
621
retNode = new (fMemoryManager) ContentSpecNode
623
ContentSpecNode::ZeroOrMore
631
retNode = new (fMemoryManager) ContentSpecNode
633
ContentSpecNode::OneOrMore
642
else if (maxOccurs == -1) {
644
retNode = new (fMemoryManager) ContentSpecNode
646
ContentSpecNode::OneOrMore
654
for (int i=0; i < (minOccurs-1); i++) {
655
retNode = new (fMemoryManager) ContentSpecNode
657
ContentSpecNode::Sequence
668
if (minOccurs == 0) {
670
ContentSpecNode* optional = new (fMemoryManager) ContentSpecNode
672
ContentSpecNode::ZeroOrOne
682
for (int i=0; i < (maxOccurs-1); i++) {
683
retNode = new (fMemoryManager) ContentSpecNode
685
ContentSpecNode::Sequence
698
retNode = new (fMemoryManager) ContentSpecNode
700
ContentSpecNode::Sequence
708
for (int i=1; i < (minOccurs-1); i++) {
709
retNode = new (fMemoryManager) ContentSpecNode
711
ContentSpecNode::Sequence
721
int counter = maxOccurs-minOccurs;
725
ContentSpecNode* optional = new (fMemoryManager) ContentSpecNode
727
ContentSpecNode::ZeroOrOne
735
retNode = new (fMemoryManager) ContentSpecNode
737
ContentSpecNode::Sequence
745
for (int j=1; j < counter; j++) {
747
retNode = new (fMemoryManager) ContentSpecNode
749
ContentSpecNode::Sequence
764
void ComplexTypeInfo::resizeContentSpecOrgURI() {
766
unsigned int newSize = fContentSpecOrgURISize * 2;
767
unsigned int* newContentSpecOrgURI = (unsigned int*) fMemoryManager->allocate
769
newSize * sizeof(unsigned int)
770
); //new unsigned int[newSize];
772
// Copy the existing values
773
unsigned int index = 0;
774
for (; index < fContentSpecOrgURISize; index++)
775
newContentSpecOrgURI[index] = fContentSpecOrgURI[index];
777
for (; index < newSize; index++)
778
newContentSpecOrgURI[index] = 0;
780
// Delete the old array and udpate our members
781
fMemoryManager->deallocate(fContentSpecOrgURI); //delete [] fContentSpecOrgURI;
782
fContentSpecOrgURI = newContentSpecOrgURI;
783
fContentSpecOrgURISize = newSize;
787
* Support for Serialization/De-serialization
790
IMPL_XSERIALIZABLE_TOCREATE(ComplexTypeInfo)
792
void ComplexTypeInfo::serialize(XSerializeEngine& serEng)
795
if (serEng.isStoring())
799
serEng<<fAdoptContentSpec;
800
serEng<<fAttWithTypeId;
801
serEng<<fPreprocessed;
805
serEng<<fScopeDefined;
806
serEng<<fContentType;
810
serEng.writeString(fTypeName);
811
serEng.writeString(fTypeLocalName);
812
serEng.writeString(fTypeUri);
814
DatatypeValidator::storeDV(serEng, fBaseDatatypeValidator);
815
DatatypeValidator::storeDV(serEng, fDatatypeValidator);
817
serEng<<fBaseComplexTypeInfo;
818
serEng<<fContentSpec;
819
serEng<<fAttWildCard;
824
* Serialize RefVectorOf<SchemaElementDecl>* fElements;
825
* Serialize RefHash2KeysTableOf<SchemaAttDef>* fAttDefs;
827
XTemplateSerializer::storeObject(fElements, serEng);
828
XTemplateSerializer::storeObject(fAttDefs, serEng);
837
* fContentSpecOrgURI: start of the array
838
* fContentSpecOrgURISize: size of the array
839
* fUniqueURI: the current last element in the array
846
serEng>>fAdoptContentSpec;
847
serEng>>fAttWithTypeId;
848
serEng>>fPreprocessed;
852
serEng>>fScopeDefined;
853
serEng>>fContentType;
857
serEng.readString(fTypeName);
858
serEng.readString(fTypeLocalName);
859
serEng.readString(fTypeUri);
861
fBaseDatatypeValidator = DatatypeValidator::loadDV(serEng);
862
fDatatypeValidator = DatatypeValidator::loadDV(serEng);
864
serEng>>fBaseComplexTypeInfo;
865
serEng>>fContentSpec;
866
serEng>>fAttWildCard;
867
delete fAttList; // will recreate it next...
872
* Deserialize RefVectorOf<SchemaElementDecl>* fElements;
873
* Deserialize RefHash2KeysTableOf<SchemaAttDef>* fAttDefs;
875
XTemplateSerializer::loadObject(&fElements, 8, false, serEng);
876
delete fAttDefs; // will recreate it next...
877
XTemplateSerializer::loadObject(&fAttDefs, 29, true, serEng);
885
* fContentSpecOrgURI: start of the array
886
* fContentSpecOrgURISize: size of the array
887
* fUniqueURI: the current last element in the array
892
fContentSpecOrgURI = 0;
893
fContentSpecOrgURISize = 0;
896
// Create the content model by calling getContentModel(). This
897
// will ensure the grammar can be used concurrently by multiple
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);
907
XERCES_CPP_NAMESPACE_END
910
* End of file ComplexTypeInfo.cpp