source: icXML/icXML-devel/src/icxercesc/validators/DTD/DTDElementDecl.cpp @ 2720

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

Initial check-in of icXML 0.8 source files

File size: 11.2 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: DTDElementDecl.cpp 471747 2006-11-06 14:31:56Z amassari $
20 */
21
22
23// ---------------------------------------------------------------------------
24//  Includes
25// ---------------------------------------------------------------------------
26#include <xercesc/util/XMLString.hpp>
27#include <xercesc/util/XMLUniDefs.hpp>
28#include <xercesc/util/XMLUni.hpp>
29#include <xercesc/framework/XMLBuffer.hpp>
30#include <xercesc/validators/common/DFAContentModel.hpp>
31#include <xercesc/validators/common/ContentSpecNode.hpp>
32#include <xercesc/validators/common/MixedContentModel.hpp>
33#include <xercesc/validators/common/SimpleContentModel.hpp>
34#include <xercesc/validators/DTD/DTDAttDefList.hpp>
35#include <xercesc/validators/DTD/DTDElementDecl.hpp>
36
37#include <xercesc/internal/XTemplateSerializer.hpp>
38
39XERCES_CPP_NAMESPACE_BEGIN
40
41// ---------------------------------------------------------------------------
42//  DTDElementDecl: Constructors and Destructor
43// ---------------------------------------------------------------------------
44DTDElementDecl::DTDElementDecl(MemoryManager* const manager) :
45
46        XMLElementDecl(manager)
47        , fModelType(Any)
48        , fAttDefs(0)
49        , fAttList(0)
50        , fContentSpec(0)
51        , fContentModel(0)
52        , fFormattedModel(0)
53{
54}
55
56DTDElementDecl::DTDElementDecl( const XMLCh* const               elemRawName
57                                                          , const unsigned int               uriId
58                                                          , const DTDElementDecl::ModelTypes type
59                                                          , MemoryManager* const             manager) :
60        XMLElementDecl(manager)
61        , fModelType(type)
62        , fAttDefs(0)
63        , fAttList(0)
64        , fContentSpec(0)
65        , fContentModel(0)
66        , fFormattedModel(0)
67{
68        setElementName(elemRawName, uriId);
69}
70
71DTDElementDecl::DTDElementDecl( const QName* const               elementName
72                                                          , const DTDElementDecl::ModelTypes type
73                                                          , MemoryManager* const             manager) :
74        XMLElementDecl(manager)
75        , fModelType(type)
76        , fAttDefs(0)
77        , fAttList(0)
78        , fContentSpec(0)
79        , fContentModel(0)
80        , fFormattedModel(0)
81{
82        setElementName(elementName);
83}
84
85DTDElementDecl::~DTDElementDecl()
86{
87        delete fAttDefs;
88        delete fAttList;
89        delete fContentSpec;
90        delete fContentModel;
91        getMemoryManager()->deallocate(fFormattedModel);
92}
93
94
95
96// ---------------------------------------------------------------------------
97//  The virtual element decl interface
98// ---------------------------------------------------------------------------
99XMLAttDefList& DTDElementDecl::getAttDefList() const
100{
101        if (!fAttList)
102        {
103                // If the att def list is not made yet, then fault it in too
104                if (!fAttDefs)
105                        faultInAttDefList();
106
107                ((DTDElementDecl*)this)->fAttList =
108                        new (getMemoryManager()) DTDAttDefList(fAttDefs,getMemoryManager());
109        }
110
111        return *fAttList;
112}
113
114
115XMLElementDecl::CharDataOpts DTDElementDecl::getCharDataOpts() const
116{
117        XMLElementDecl::CharDataOpts retVal;
118        switch(fModelType)
119        {
120                case Children :
121                        retVal = XMLElementDecl::SpacesOk;
122                        break;
123
124                case Empty :
125                        retVal = XMLElementDecl::NoCharData;
126                        break;
127
128                default :
129                        retVal = XMLElementDecl::AllCharData;
130                        break;
131        }
132        return retVal;
133}
134
135
136bool DTDElementDecl::hasAttDefs() const
137{
138        // If the collection hasn't been faulted in, then no att defs
139        if (!fAttDefs)
140                return false;
141
142        return !fAttDefs->isEmpty();
143}
144
145void
146DTDElementDecl::setContentSpec(ContentSpecNode* toAdopt)
147{
148        delete fContentSpec;
149        fContentSpec = toAdopt;
150
151        //reset Content Model
152        setContentModel(0);
153
154}
155
156const XMLCh*
157DTDElementDecl::getFormattedContentModel() const
158{
159        //
160        //  If its not already built, then call the protected virtual method
161        //  to allow the derived class to build it (since only it knows.)
162        //  Otherwise, just return the previously formatted methods.
163        //
164        //  Since we are faulting this in, within a const getter, we have to
165        //  cast off the const-ness.
166        //
167        if (!fFormattedModel)
168                ((DTDElementDecl*)this)->fFormattedModel = formatContentModel();
169
170        return fFormattedModel;
171}
172
173
174// ---------------------------------------------------------------------------
175//  DTDElementDecl: Getter methods
176// ---------------------------------------------------------------------------
177const DTDAttDef* DTDElementDecl::getAttDef(const XMLCh* const attName) const
178{
179        // If no list, then return a null
180        if (!fAttDefs)
181                return 0;
182
183        return fAttDefs->get(attName);
184}
185
186
187DTDAttDef* DTDElementDecl::getAttDef(const XMLCh* const attName)
188{
189        // If no list, then return a null
190        if (!fAttDefs)
191                return 0;
192
193        return fAttDefs->get(attName);
194}
195
196
197// ---------------------------------------------------------------------------
198//  DTDElementDecl: Implementation of the protected virtual interface
199// ---------------------------------------------------------------------------
200void DTDElementDecl::addAttDef(DTDAttDef* const toAdd)
201{
202        // Fault in the att list if required
203        if (!fAttDefs)
204                        faultInAttDefList();
205
206        // Tell this guy the element id of its parent (us)
207        toAdd->setElemId(getId());
208
209        fAttDefs->put((void*)(toAdd->getFullName()), toAdd);
210        // update and/or create fAttList
211        if(!fAttList)
212                ((DTDElementDecl*)this)->fAttList = new (getMemoryManager()) DTDAttDefList(fAttDefs,getMemoryManager());
213        fAttList->addAttDef(toAdd);
214}
215
216
217// ---------------------------------------------------------------------------
218//  DTDElementDecl: Private helper methods
219// ---------------------------------------------------------------------------
220XMLCh* DTDElementDecl::formatContentModel() const
221{
222        XMLCh* newValue = 0;
223        if (fModelType == Any)
224        {
225                newValue = XMLString::replicate(XMLUni::fgAnyString, getMemoryManager());
226        }
227         else if (fModelType == Empty)
228        {
229                newValue = XMLString::replicate(XMLUni::fgEmptyString, getMemoryManager());
230        }
231         else
232        {
233                //
234                //  Use a temp XML buffer to format into. Content models could be
235                //  pretty long, but very few will be longer than one K. The buffer
236                //  will expand to handle the more pathological ones.
237                //
238                XMLBuffer bufFmt(1023, getMemoryManager());
239                getContentSpec()->formatSpec(bufFmt);
240                newValue = XMLString::replicate(bufFmt.getRawBuffer(), getMemoryManager());
241        }
242        return newValue;
243}
244
245XMLContentModel* DTDElementDecl::makeContentModel()
246{
247        XMLContentModel* cmRet = 0;
248        if (fModelType == Mixed_Simple)
249        {
250                //
251                //  Just create a mixel content model object. This type of
252                //  content model is optimized for mixed content validation.
253                //
254                cmRet = new (getMemoryManager()) MixedContentModel(true, this->getContentSpec(), false, getMemoryManager());
255        }
256         else if (fModelType == Children)
257        {
258                //
259                //  This method will create an optimal model for the complexity
260                //  of the element's defined model. If its simple, it will create
261                //  a SimpleContentModel object. If its a simple list, it will
262                //  create a SimpleListContentModel object. If its complex, it
263                //  will create a DFAContentModel object.
264                //
265                cmRet = createChildModel();
266        }
267         else
268        {
269                ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_MustBeMixedOrChildren, getMemoryManager());
270        }
271        return cmRet;
272}
273
274
275XMLContentModel* DTDElementDecl::createChildModel()
276{
277        // Get the content spec node of the element
278        ContentSpecNode* specNode = getContentSpec();
279
280        if(!specNode)
281                ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_UnknownCMSpecType, getMemoryManager());
282
283        //
284        //  Do a sanity check that the node does not have a PCDATA id. Since,
285        //  if it was, it should have already gotten taken by the Mixed model.
286        //
287        if (specNode->getElement()) {
288                if (specNode->getElement()->getURI() == XMLElementDecl::fgPCDataElemId)
289                        ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_NoPCDATAHere, getMemoryManager());
290        }
291
292        //
293        //  According to the type of node, we will create the correct type of
294        //  content model.
295        //
296        if (specNode->getType() == ContentSpecNode::Leaf)
297        {
298                // Create a simple content model
299                return new (getMemoryManager()) SimpleContentModel
300                (
301                        true
302                        , specNode->getElement()
303                        , 0
304                        , ContentSpecNode::Leaf
305                        , getMemoryManager()
306                );
307        }
308         else if ((specNode->getType() == ContentSpecNode::Choice)
309                  ||  (specNode->getType() == ContentSpecNode::Sequence))
310        {
311                //
312                //  Lets see if both of the children are leafs. If so, then it has to
313                //  be a simple content model
314                //
315                if ((specNode->getFirst()->getType() == ContentSpecNode::Leaf)
316                &&  (specNode->getSecond()->getType() == ContentSpecNode::Leaf))
317                {
318                        return new (getMemoryManager()) SimpleContentModel
319                        (
320                                true
321                                , specNode->getFirst()->getElement()
322                                , specNode->getSecond()->getElement()
323                                , specNode->getType()
324                                , getMemoryManager()
325                        );
326                }
327        }
328         else if ((specNode->getType() == ContentSpecNode::OneOrMore)
329                  ||  (specNode->getType() == ContentSpecNode::ZeroOrMore)
330                  ||  (specNode->getType() == ContentSpecNode::ZeroOrOne))
331        {
332                //
333                //  Its a repetition, so see if its one child is a leaf. If so its a
334                //  repetition of a single element, so we can do a simple content
335                //  model for that.
336                //
337                if (specNode->getFirst()->getType() == ContentSpecNode::Leaf)
338                {
339                        return new (getMemoryManager()) SimpleContentModel
340                        (
341                                true
342                                , specNode->getFirst()->getElement()
343                                , 0
344                                , specNode->getType()
345                                , getMemoryManager()
346                        );
347                }
348        }
349         else
350        {
351                ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_UnknownCMSpecType, getMemoryManager());
352        }
353
354        // Its not any simple type of content, so create a DFA based content model
355        return new (getMemoryManager()) DFAContentModel
356        (
357                true
358                , this->getContentSpec()
359                , getMemoryManager()
360        );
361}
362
363
364void DTDElementDecl::faultInAttDefList() const
365{
366        // Use a hash modulus of 29 and tell it owns its elements
367        ((DTDElementDecl*)this)->fAttDefs = new (getMemoryManager()) RefHashTableOf<DTDAttDef>(29, true, getMemoryManager());
368}
369
370/***
371 * Support for Serialization/De-serialization
372 ***/
373
374IMPL_XSERIALIZABLE_TOCREATE(DTDElementDecl)
375
376void DTDElementDecl::serialize(XSerializeEngine& serEng)
377{
378
379        XMLElementDecl::serialize(serEng);
380
381        if (serEng.isStoring())
382        {
383                serEng<<(int) fModelType;
384
385                /***
386                 *
387                 * Serialize RefHashTableOf<DTDAttDef>
388                 *
389                 ***/
390                XTemplateSerializer::storeObject(fAttDefs, serEng);
391
392                serEng<<fAttList;
393                serEng<<fContentSpec;
394
395                /***
396                 *   don't serialize
397                 *
398                 *   XMLContentModel*            fContentModel;
399                 *   XMLCh*                      fFormattedModel;
400                 *
401                 ***/
402
403        }
404        else
405        {
406                int i;
407                serEng>>i;
408                fModelType=(ModelTypes)i;
409
410                /***
411                 *
412                 * Deserialize RefHashTableOf<DTDAttDef>
413                 *
414                 ***/
415                XTemplateSerializer::loadObject(&fAttDefs, 29, true, serEng);
416
417                serEng>>fAttList;
418                serEng>>fContentSpec;
419
420                /***
421                 *   don't deserialize
422                 *
423                 *   XMLContentModel*            fContentModel;
424                 *   XMLCh*                      fFormattedModel;
425                 *
426                 ***/
427                fContentModel   = 0;
428                fFormattedModel = 0;
429        }
430
431}
432
433XMLElementDecl::objectType  DTDElementDecl::getObjectType() const
434{
435        return DTD;
436}
437
438XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.