source: icXML/icXML-devel/src/icxercesc/validators/common/SimpleContentModel.cpp

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

Changes to icxercesc files

File size: 13.1 KB
Line 
1/*
2 * Unless required by applicable law or agreed to in writing, software
3 * distributed under the License is distributed on an "AS IS" BASIS,
4 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
5 * See the License for the specific language governing permissions and
6 * limitations under the License.
7 */
8
9/*
10 * $Id: SimpleContentModel.cpp 799211 2009-07-30 09:06:43Z amassari $
11 */
12
13
14// ---------------------------------------------------------------------------
15//  Includes
16// ---------------------------------------------------------------------------
17#include <xercesc/util/RuntimeException.hpp>
18#include <icxercesc/framework/XMLValidator.hpp>
19#include <icxercesc/validators/common/SimpleContentModel.hpp>
20#include <icxercesc/validators/schema/SubstitutionGroupComparator.hpp>
21#include <xercesc/validators/schema/XercesElementWildcard.hpp>
22
23XERCES_CPP_NAMESPACE_BEGIN
24
25// ---------------------------------------------------------------------------
26//  SimpleContentModel: Implementation of the ContentModel virtual interface
27// ---------------------------------------------------------------------------
28//
29//  This method is called to validate our content. For this one, its just a
30//  pretty simple 'bull your way through it' test according to what kind of
31//  operation it is for.
32//
33
34bool
35SimpleContentModel::validateContent
36(
37        XMLElementDecl ** const         children
38        , XMLSize_t                                     childCount
39        , XMLSize_t*                            indexOfFailingChild
40        , MemoryManager*    const       manager
41) const
42{
43        DEBUG_MESSAGE("SimpleContentModel::validateContent");
44
45        //
46        //  According to the type of operation, we do the correct type of
47        //  content check.
48        //
49        XMLSize_t index;
50        switch (fOp & 0x0f)
51        {
52                case ContentSpecNode::Leaf :
53
54                        //
55                        //  There can only be one child and it has to be of the
56                        //  element type we stored.
57                        //
58
59            if (childCount == 0)
60            {
61                *indexOfFailingChild = 0;
62                return false;
63            }
64
65            // intentionally fall through ...
66
67                case ContentSpecNode::ZeroOrOne :
68                        //
69                        //  If the child count is greater than one, then obviously
70                        //  bad. Otherwise, if its one, then the one child must be
71                        //  of the type we stored.
72                        //
73            if (unlikely((childCount == 1 && !equals(fDTD, children[0], fFirstChild)) || childCount > 1))
74                        {
75                *indexOfFailingChild = 1;
76                                return false;
77                        }
78                        break;
79
80
81        case ContentSpecNode::OneOrMore :
82            //
83            //  If the child count is zero, that's an error. If its more
84            //  than zero, then make sure that all children are of the
85            //  element type that we stored.
86            //
87            if (childCount == 0)
88            {
89                *indexOfFailingChild = 0;
90                return false;
91            }
92
93            // intentionally fall through ...
94
95                case ContentSpecNode::ZeroOrMore :
96                        //
97                        //  If the child count is zero, that's fine. If its more than
98                        //  zero, then make sure that all children are of the element
99                        //  type that we stored.
100                        //
101                        if (childCount > 0)
102                        {
103                                if (fDTD)
104                                {
105                                        for (index = 0; index < childCount; index++)
106                                        {
107                        if (!equals(true, children[index], fFirstChild))
108                                                {
109                                                        *indexOfFailingChild=index;
110                                                        return false;
111                                                }
112                                        }
113                                }
114                                else
115                                {
116                                        for (index = 0; index < childCount; index++)
117                                        {
118                        if (!equals(false, children[index], fFirstChild))
119                        {
120                                                        *indexOfFailingChild=index;
121                                                        return false;
122                                                }
123                                        }
124                                }
125                        }
126                        break;
127
128                case ContentSpecNode::Choice :
129                        //
130                        //  There can only be one child, and it must be one of the
131                        //  two types we stored.
132                        //
133            if (childCount == 0)
134                        {
135                *indexOfFailingChild = 0;
136                                return false;
137                        }
138
139            // test first child
140            if (unlikely(!equals(fDTD, children[0], fFirstChild) && equals(fDTD, children[0], fSecondChild)))
141            {
142                *indexOfFailingChild=0;
143                return false;
144            }
145
146            if (unlikely(childCount > 1))
147                        {
148                                *indexOfFailingChild=1;
149                                return false;
150                        }
151                        break;
152
153                case ContentSpecNode::Sequence :
154                        //
155                        //  There must be two children and they must be the two values
156                        //  we stored, in the stored order. So first check the obvious
157                        //  problem of an empty content, which would never be valid
158                        //  in this content mode.
159                        //
160            if (childCount == 0)
161                        {
162                                *indexOfFailingChild=0;
163                                return false;
164                        }
165
166                        // test first child
167            if (unlikely(!equals(fDTD, children[0], fFirstChild)))
168            {
169                *indexOfFailingChild=0;
170                return false;
171            }
172
173                        // test second child, if present
174            if (unlikely(childCount == 1))
175                        {
176                                // missing second child
177                                *indexOfFailingChild=1;
178                                return false;
179                        }
180                        else
181                        {
182                // test first child
183                if (unlikely(!equals(fDTD, children[1], fSecondChild)))
184                {
185                    *indexOfFailingChild = 1;
186                    return false;
187                }
188
189                if (unlikely(childCount > 2))
190                                {
191                    *indexOfFailingChild = 2;
192                                        return false;
193                                }
194                        }
195                        break;
196
197                default :
198                        ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_UnknownCMSpecType, fMemoryManager);
199                        break;
200        }
201        return true;
202}
203
204bool SimpleContentModel::validateContentSpecial
205(
206        XMLElementDecl ** const                 children
207        , XMLSize_t                                             childCount
208        , GrammarResolver*  const               pGrammarResolver
209        , XMLNamespaceResolver* const   pUriResolver
210        , XMLSize_t*                                    indexOfFailingChild
211        , MemoryManager*    const               manager
212) const
213{
214        SubstitutionGroupComparator comparator(pGrammarResolver, pUriResolver);
215
216        //
217        //  According to the type of operation, we do the correct type of
218        //  content check.
219        //
220        unsigned int index;
221        switch(fOp & 0x0f)
222        {
223                case ContentSpecNode::Leaf :
224
225                        //
226                        //  There can only be one child and it has to be of the
227                        //  element type we stored.
228                        //
229                        if (!childCount)
230                        {
231                                *indexOfFailingChild=0;
232                                return false;
233                        }
234
235                        if ((children[0]->getURI() != fFirstChild->getURI()) ||
236                                !XMLString::equals(children[0]->getLocalPart(), fFirstChild->getLocalPart()))
237                        {
238                                if (!comparator.isEquivalentTo(children[0], fFirstChild))
239                                {
240                                        *indexOfFailingChild=0;
241                                        return false;
242                                }
243                        }
244
245                        if (childCount > 1)
246                        {
247                                *indexOfFailingChild=1;
248                                return false;
249                        }
250                        break;
251
252                case ContentSpecNode::ZeroOrOne :
253                        //
254                        //  If the child count is greater than one, then obviously
255                        //  bad. Otherwise, if its one, then the one child must be
256                        //  of the type we stored.
257                        //
258                        if ((childCount == 1) &&
259                           ((children[0]->getURI() != fFirstChild->getURI()) ||
260                                !XMLString::equals(children[0]->getLocalPart(), fFirstChild->getLocalPart())))
261                        {
262                                if(!comparator.isEquivalentTo(children[0], fFirstChild))
263                                {
264                                        *indexOfFailingChild=0;
265                                        return false;
266                                }
267                        }
268
269                        if (childCount > 1)
270                        {
271                                *indexOfFailingChild=1;
272                                return false;
273                        }
274                        break;
275
276                case ContentSpecNode::ZeroOrMore :
277                        //
278                        //  If the child count is zero, that's fine. If its more than
279                        //  zero, then make sure that all children are of the element
280                        //  type that we stored.
281                        //
282                        if (childCount > 0)
283                        {
284                                for (index = 0; index < childCount; index++)
285                                {
286                                        if ((children[index]->getURI() != fFirstChild->getURI()) ||
287                                                !XMLString::equals(children[index]->getLocalPart(), fFirstChild->getLocalPart()))
288                                        {
289                                                if (!comparator.isEquivalentTo(children[index], fFirstChild))
290                                                {
291                                                        *indexOfFailingChild=index;
292                                                        return false;
293                                                }
294                                        }
295                                }
296                        }
297                        break;
298
299                case ContentSpecNode::OneOrMore :
300                        //
301                        //  If the child count is zero, that's an error. If its more
302                        //  than zero, then make sure that all children are of the
303                        //  element type that we stored.
304                        //
305                        if (childCount == 0)
306                        {
307                                *indexOfFailingChild=0;
308                                return false;
309                        }
310
311                        for (index = 0; index < childCount; index++)
312                        {
313                                if ((children[index]->getURI() != fFirstChild->getURI()) ||
314                                        !XMLString::equals(children[index]->getLocalPart(), fFirstChild->getLocalPart()))
315                                {
316                                        if (!comparator.isEquivalentTo(children[index], fFirstChild))
317                                        {
318                                                *indexOfFailingChild=index;
319                                                return false;
320                                        }
321                                }
322                        }
323                        break;
324
325                case ContentSpecNode::Choice :
326                        //
327                        //  There can only be one child, and it must be one of the
328                        //  two types we stored.
329                        //
330                        if (!childCount)
331                        {
332                                *indexOfFailingChild=0;
333                                return false;
334                        }
335
336                        if (((children[0]->getURI() != fFirstChild->getURI()) ||
337                                 !XMLString::equals(children[0]->getLocalPart(), fFirstChild->getLocalPart())) &&
338                                ((children[0]->getURI() != fSecondChild->getURI()) ||
339                                 !XMLString::equals(children[0]->getLocalPart(), fSecondChild->getLocalPart())))
340                        {
341
342                                 if (!comparator.isEquivalentTo(children[0], fFirstChild) &&
343                                         !comparator.isEquivalentTo(children[0], fSecondChild) )
344                                 {
345                                         *indexOfFailingChild=0;
346                                         return false;
347                                 }
348                        }
349
350                        if (childCount > 1)
351                        {
352                                *indexOfFailingChild=1;
353                                return false;
354                        }
355                        break;
356
357                case ContentSpecNode::Sequence :
358                        //
359                        //  There must be two children and they must be the two values
360                        //  we stored, in the stored order. So first check the obvious
361                        //  problem of an empty content, which would never be valid
362                        //  in this content mode.
363                        //
364                        if (!childCount)
365                        {
366                                *indexOfFailingChild=0;
367                                return false;
368                        }
369
370            DEBUG_GRAMMAR_MESSAGE("children[0]=" << children[0]->getURI() << "," << children[0]->getLocalPart());
371            DEBUG_GRAMMAR_MESSAGE("fFirstChild=" << fFirstChild->getURI() << "," << fFirstChild->getLocalPart());
372
373                        // test first child
374            if ((children[0]->getURI() != fFirstChild->getURI()) || !XMLString::equals(children[0]->getLocalPart(), fFirstChild->getLocalPart()))
375                        {
376                if (!comparator.isEquivalentTo(children[0], fFirstChild))
377                                {
378                                        *indexOfFailingChild=0;
379                                        return false;
380                                }
381                        }
382                        // test second child, if present
383                        if( childCount == 1)
384                        {
385                                // missing second child
386                                *indexOfFailingChild=1;
387                                return false;
388                        }
389                        else
390                        {
391                DEBUG_GRAMMAR_MESSAGE("children[1]=" << children[1]->getURI() << "," << children[1]->getLocalPart());
392                DEBUG_GRAMMAR_MESSAGE("fSecondChild=" << fFirstChild->getURI() << "," << fSecondChild->getLocalPart());
393
394                if ((children[1]->getURI() != fSecondChild->getURI()) || !XMLString::equals(children[1]->getLocalPart(), fSecondChild->getLocalPart()))
395                                {
396                                        if (!comparator.isEquivalentTo(children[1], fSecondChild))
397                                        {
398                                                *indexOfFailingChild=1;
399                                                return false;
400                                        }
401                                }
402
403                if (childCount > 2)
404                {
405                                        *indexOfFailingChild=2;
406                                        return false;
407                                }
408                        }
409                        break;
410
411                default :
412                        ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_UnknownCMSpecType, fMemoryManager);
413                        break;
414        }
415        return true;
416}
417
418ContentLeafNameTypeVector* SimpleContentModel::getContentLeafNameTypeVector() const
419{
420        return 0;
421}
422
423static inline bool checkUriForRenaming(const QName * child)
424{
425    if (child)
426    {
427        unsigned int orgURIIndex = child->getURI();
428        if (likely(orgURIIndex < XMLContentModel::gEOCFakeId))
429        {
430            return true;
431        }
432        else if (unlikely(orgURIIndex == XMLContentModel::gEOCFakeId || orgURIIndex == XMLElementDecl::fgInvalidElemId || orgURIIndex == XMLElementDecl::fgPCDataElemId))
433        {
434            return false;
435        }
436        return true;
437    }
438    return false;
439}
440
441void SimpleContentModel::checkUniqueParticleAttribution
442(
443        SchemaGrammar*    const                 pGrammar
444        , GrammarResolver*  const               pGrammarResolver
445        , XMLNamespaceResolver* const   pUriResolver
446        , XMLValidator*     const               pValidator
447        , unsigned int*     const               pContentSpecOrgURI
448        , const XMLCh*                                  pComplexTypeName /*= 0*/
449)
450{
451        // rename back
452    if (checkUriForRenaming(fFirstChild))
453    {
454        fFirstChild->setURI(pContentSpecOrgURI[fFirstChild->getURI()]);
455    }
456    if (checkUriForRenaming(fSecondChild))
457    {
458        fSecondChild->setURI(pContentSpecOrgURI[fSecondChild->getURI()]);
459    }
460
461        // only possible violation is when it's a choice
462        if ((fOp & 0x0f) == ContentSpecNode::Choice)
463        {
464
465                SubstitutionGroupComparator comparator(pGrammarResolver, pUriResolver);
466
467                if (XercesElementWildcard::conflict(pGrammar,
468                                                                                        ContentSpecNode::Leaf,
469                                                                                        fFirstChild,
470                                                                                        ContentSpecNode::Leaf,
471                                                                                        fSecondChild,
472                                                                                        &comparator))
473
474                        pValidator->emitError(XMLValid::UniqueParticleAttributionFail,
475                                                                  pComplexTypeName,
476                                                                  fFirstChild->getRawName(),
477                                                                  fSecondChild->getRawName());
478        }
479}
480
481bool SimpleContentModel::validateContent
482(
483        QName** const
484  , XMLSize_t
485  , unsigned int
486  , XMLSize_t*
487  , MemoryManager*  const
488)
489const
490{
491        DEPRECATED_FEATURE_IN_ICXML;
492}
493
494bool SimpleContentModel::validateContentSpecial
495(
496        QName** const
497  , XMLSize_t
498  , unsigned int
499  , GrammarResolver*  const
500  , XMLStringPool*    const
501  , XMLSize_t*
502  , MemoryManager*    const
503)
504const
505{
506        DEPRECATED_FEATURE_IN_ICXML;
507}
508
509void SimpleContentModel::checkUniqueParticleAttribution
510(
511        SchemaGrammar*    const
512  , GrammarResolver*  const
513  , XMLStringPool*    const
514  , XMLValidator*     const
515  , unsigned int*     const
516  , const XMLCh*
517)
518{
519        DEPRECATED_FEATURE_IN_ICXML;
520}
521
522XERCES_CPP_NAMESPACE_END
523
Note: See TracBrowser for help on using the repository browser.