source: icXML/icXML-devel/src/xercesc/validators/common/ContentSpecNode.cpp @ 2722

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

Original Xerces files with import mods for icxercesc

File size: 10.1 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: ContentSpecNode.cpp 933155 2010-04-12 09:07:02Z amassari $
20 */
21
22
23// ---------------------------------------------------------------------------
24//  Includes
25// ---------------------------------------------------------------------------
26#include <icxercesc/framework/XMLBuffer.hpp>
27#include <xercesc/validators/common/ContentSpecNode.hpp>
28#include <xercesc/validators/schema/SchemaSymbols.hpp>
29
30XERCES_CPP_NAMESPACE_BEGIN
31
32// ---------------------------------------------------------------------------
33//  ContentSpecNode: Copy Constructor
34//
35//  Note: this copy constructor has dependency on various get*() methods
36//        and shall be placed after those method's declaration.
37//        aka inline function compilation error on AIX 4.2, xlC 3 r ev.1
38// ---------------------------------------------------------------------------
39
40ContentSpecNode::ContentSpecNode(const ContentSpecNode& toCopy) :
41    XSerializable(toCopy)
42    , XMemory(toCopy)
43    , fMemoryManager(toCopy.fMemoryManager)
44    , fElement(0)
45    , fElementDecl(toCopy.fElementDecl)
46    , fFirst(0)
47    , fSecond(0)
48    , fType(toCopy.fType)
49    , fAdoptFirst(true)
50    , fAdoptSecond(true)
51    , fMinOccurs(toCopy.fMinOccurs)
52    , fMaxOccurs(toCopy.fMaxOccurs)
53{
54    const QName* tempElement = toCopy.getElement();
55    if (tempElement)
56        fElement = new (fMemoryManager) QName(*tempElement);
57
58    const ContentSpecNode *tmp = toCopy.getFirst();
59    if (tmp)
60        fFirst = new (fMemoryManager) ContentSpecNode(*tmp);
61
62    tmp = toCopy.getSecond();
63    if (tmp)
64        fSecond = new (fMemoryManager) ContentSpecNode(*tmp);
65}
66
67// ---------------------------------------------------------------------------
68//  Local methods
69// ---------------------------------------------------------------------------
70static void formatNode( const   ContentSpecNode* const      curNode
71                        , const ContentSpecNode::NodeTypes  parentType
72                        ,       XMLBuffer&                  bufToFill)
73{
74    if (!curNode)
75        return;
76
77    const ContentSpecNode* first = curNode->getFirst();
78    const ContentSpecNode* second = curNode->getSecond();
79    const ContentSpecNode::NodeTypes curType = curNode->getType();
80
81    // Get the type of the first node
82    const ContentSpecNode::NodeTypes firstType = first ?
83                                                 first->getType() :
84                                                 ContentSpecNode::Leaf;
85
86    // Calculate the parens flag for the rep nodes
87    bool doRepParens = false;
88    if (((firstType != ContentSpecNode::Leaf)
89            && (parentType != ContentSpecNode::UnknownType))
90    ||  ((firstType == ContentSpecNode::Leaf)
91            && (parentType == ContentSpecNode::UnknownType)))
92    {
93        doRepParens = true;
94    }
95
96    // Now handle our type
97    switch(curType & 0x0f)
98    {
99        case ContentSpecNode::Leaf :
100            if (curNode->getElement()->getURI() == XMLElementDecl::fgPCDataElemId)
101                bufToFill.append(XMLElementDecl::fgPCDataElemName);
102            else
103            {
104                bufToFill.append(curNode->getElement()->getRawName());
105                // show the + and * modifiers also when we have a non-infinite number of repetitions
106                if(curNode->getMinOccurs()==0 && (curNode->getMaxOccurs()==-1 || curNode->getMaxOccurs()>1))
107                    bufToFill.append(chAsterisk);
108                else if(curNode->getMinOccurs()==0 && curNode->getMaxOccurs()==1)
109                    bufToFill.append(chQuestion);
110                else if(curNode->getMinOccurs()==1 && (curNode->getMaxOccurs()==-1 || curNode->getMaxOccurs()>1))
111                    bufToFill.append(chPlus);
112            }
113            break;
114
115        case ContentSpecNode::ZeroOrOne :
116            if (doRepParens)
117                bufToFill.append(chOpenParen);
118            formatNode(first, curType, bufToFill);
119            if (doRepParens)
120                bufToFill.append(chCloseParen);
121            bufToFill.append(chQuestion);
122            break;
123
124        case ContentSpecNode::ZeroOrMore :
125            if (doRepParens)
126                bufToFill.append(chOpenParen);
127            formatNode(first, curType, bufToFill);
128            if (doRepParens)
129                bufToFill.append(chCloseParen);
130            bufToFill.append(chAsterisk);
131            break;
132
133        case ContentSpecNode::OneOrMore :
134            if (doRepParens)
135                bufToFill.append(chOpenParen);
136            formatNode(first, curType, bufToFill);
137            if (doRepParens)
138                bufToFill.append(chCloseParen);
139            bufToFill.append(chPlus);
140            break;
141
142        case ContentSpecNode::Choice :
143            if ((parentType & 0x0f) != (curType & 0x0f))
144                bufToFill.append(chOpenParen);
145            formatNode(first, curType, bufToFill);
146            if(second!=NULL)
147            {
148                bufToFill.append(chPipe);
149                formatNode(second, curType, bufToFill);
150            }
151            if ((parentType & 0x0f) != (curType & 0x0f))
152                bufToFill.append(chCloseParen);
153            break;
154
155        case ContentSpecNode::Sequence :
156            if ((parentType & 0x0f) != (curType & 0x0f))
157                bufToFill.append(chOpenParen);
158            formatNode(first, curType, bufToFill);
159            if(second!=NULL)
160            {
161                bufToFill.append(chComma);
162                formatNode(second, curType, bufToFill);
163            }
164            if ((parentType & 0x0f) != (curType & 0x0f))
165                bufToFill.append(chCloseParen);
166            break;
167
168        case ContentSpecNode::All :
169            if ((parentType & 0x0f) != (curType & 0x0f))
170                        {
171                bufToFill.append(chLatin_A);
172                bufToFill.append(chLatin_l);
173                bufToFill.append(chLatin_l);
174                bufToFill.append(chOpenParen);
175                        }
176            formatNode(first, curType, bufToFill);
177            bufToFill.append(chComma);
178            formatNode(second, curType, bufToFill);
179            if ((parentType & 0x0f) != (curType & 0x0f))
180                bufToFill.append(chCloseParen);
181            break;
182    }
183}
184
185
186// ---------------------------------------------------------------------------
187//  ContentSpecNode: Miscellaneous
188// ---------------------------------------------------------------------------
189void ContentSpecNode::formatSpec(XMLBuffer&      bufToFill) const
190{
191    // Clean out the buffer first
192    bufToFill.reset();
193
194    if (fType == ContentSpecNode::Leaf)
195        bufToFill.append(chOpenParen);
196    formatNode
197    (
198        this
199        , UnknownType
200        , bufToFill
201    );
202    if (fType == ContentSpecNode::Leaf)
203        bufToFill.append(chCloseParen);
204}
205
206int ContentSpecNode::getMinTotalRange() const {
207
208    int min = fMinOccurs;
209
210    if ((fType & 0x0f) == ContentSpecNode::Sequence
211        || fType == ContentSpecNode::All
212        || (fType & 0x0f) == ContentSpecNode::Choice) {
213
214        int minFirst = fFirst->getMinTotalRange();
215
216        if (fSecond) {
217
218            int minSecond = fSecond->getMinTotalRange();
219
220            if ((fType & 0x0f) == ContentSpecNode::Choice) {
221                min = min * ((minFirst < minSecond)? minFirst : minSecond);
222            }
223            else {
224                min = min * (minFirst + minSecond);
225            }
226        }
227        else
228            min = min * minFirst;
229    }
230
231    return min;
232}
233
234int ContentSpecNode::getMaxTotalRange() const {
235
236    int max = fMaxOccurs;
237
238    if (max == SchemaSymbols::XSD_UNBOUNDED) {
239         return SchemaSymbols::XSD_UNBOUNDED;
240    }
241
242    if ((fType & 0x0f) == ContentSpecNode::Sequence
243        || fType == ContentSpecNode::All
244        || (fType & 0x0f) == ContentSpecNode::Choice) {
245
246        int maxFirst = fFirst->getMaxTotalRange();
247
248        if (maxFirst == SchemaSymbols::XSD_UNBOUNDED) {
249             return SchemaSymbols::XSD_UNBOUNDED;
250        }
251
252        if (fSecond) {
253
254            int maxSecond = fSecond->getMaxTotalRange();
255
256            if (maxSecond == SchemaSymbols::XSD_UNBOUNDED) {
257                return SchemaSymbols::XSD_UNBOUNDED;
258            }
259            else {
260
261                if ((fType & 0x0f) == ContentSpecNode::Choice) {
262                    max = max * (maxFirst > maxSecond) ? maxFirst : maxSecond;
263                }
264                else {
265                    max = max * (maxFirst + maxSecond);
266                }
267            }
268        }
269        else {
270            max = max * maxFirst;
271        }
272    }
273
274    return max;
275}
276
277/***
278 * Support for Serialization/De-serialization
279 ***/
280
281IMPL_XSERIALIZABLE_TOCREATE(ContentSpecNode)
282
283void ContentSpecNode::serialize(XSerializeEngine& serEng)
284{
285    /***
286     *  Since fElement, fFirst, fSecond are NOT created by the default
287     *  constructor, we need to create them dynamically.
288     ***/
289
290    if (serEng.isStoring())
291    {
292        serEng<<fElement;
293        XMLElementDecl::storeElementDecl(serEng, fElementDecl);
294        serEng<<fFirst;
295        serEng<<fSecond;
296
297        serEng<<(int)fType;
298        serEng<<fAdoptFirst;
299        serEng<<fAdoptSecond;
300        serEng<<fMinOccurs;
301        serEng<<fMaxOccurs;
302    }
303    else
304    {
305        serEng>>fElement;
306        fElementDecl = XMLElementDecl::loadElementDecl(serEng);
307        serEng>>fFirst;
308        serEng>>fSecond;
309
310        int type;
311        serEng>>type;
312        fType = (NodeTypes)type;
313
314        serEng>>fAdoptFirst;
315        serEng>>fAdoptSecond;
316        serEng>>fMinOccurs;
317        serEng>>fMaxOccurs;
318    }
319
320}
321
322XERCES_CPP_NAMESPACE_END
323
Note: See TracBrowser for help on using the repository browser.