source: icXML/icXML-devel/src/xercesc/validators/datatype/UnionDatatypeValidator.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: 15.5 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: UnionDatatypeValidator.cpp 677559 2008-07-17 11:35:27Z amassari $
20 */
21
22// ---------------------------------------------------------------------------
23//  Includes
24// ---------------------------------------------------------------------------
25#include <xercesc/validators/datatype/UnionDatatypeValidator.hpp>
26#include <xercesc/validators/datatype/InvalidDatatypeFacetException.hpp>
27#include <xercesc/validators/datatype/InvalidDatatypeValueException.hpp>
28#include <xercesc/util/OutOfMemoryException.hpp>
29
30#include <xercesc/internal/XTemplateSerializer.hpp>
31
32XERCES_CPP_NAMESPACE_BEGIN
33
34static const unsigned int BUF_LEN = 64;
35
36// ---------------------------------------------------------------------------
37//  Constructors and Destructor
38// ---------------------------------------------------------------------------
39UnionDatatypeValidator::UnionDatatypeValidator(MemoryManager* const manager)
40:DatatypeValidator(0, 0, 0, DatatypeValidator::Union, manager)
41,fEnumerationInherited(false)
42,fMemberTypesInherited(false)
43,fEnumeration(0)
44,fMemberTypeValidators(0)
45
46{}
47
48UnionDatatypeValidator::~UnionDatatypeValidator()
49{
50    cleanUp();
51}
52
53UnionDatatypeValidator::UnionDatatypeValidator(
54                        RefVectorOf<DatatypeValidator>* const memberTypeValidators
55                      , const int                             finalSet
56                      , MemoryManager* const                  manager)
57:DatatypeValidator(0, 0, finalSet, DatatypeValidator::Union, manager)
58,fEnumerationInherited(false)
59,fMemberTypesInherited(false)
60,fEnumeration(0)
61,fMemberTypeValidators(0)
62{
63    if ( !memberTypeValidators )
64    {
65        ThrowXMLwithMemMgr(InvalidDatatypeFacetException
66               , XMLExcepts::FACET_Union_Null_memberTypeValidators, manager);
67    }
68
69    // no pattern, no enumeration
70    fMemberTypeValidators = memberTypeValidators;
71}
72
73typedef JanitorMemFunCall<UnionDatatypeValidator>   CleanupType;
74
75UnionDatatypeValidator::UnionDatatypeValidator(
76                          DatatypeValidator*            const baseValidator
77                        , RefHashTableOf<KVStringPair>* const facets
78                        , RefArrayVectorOf<XMLCh>*      const enums
79                        , const int                           finalSet
80                        , MemoryManager* const                manager
81                        , RefVectorOf<DatatypeValidator>* const memberTypeValidators
82                        , const bool memberTypesInherited
83                        )
84:DatatypeValidator(baseValidator, facets, finalSet, DatatypeValidator::Union, manager)
85,fEnumerationInherited(false)
86,fMemberTypesInherited(memberTypesInherited)
87,fEnumeration(0)
88,fMemberTypeValidators(memberTypeValidators)
89{
90    //
91    // baseValidator another UnionDTV from which,
92    // this UnionDTV is derived by restriction.
93    // it shall be not null
94    //
95    if (!baseValidator)
96    {
97        ThrowXMLwithMemMgr(InvalidDatatypeFacetException
98               , XMLExcepts::FACET_Union_Null_baseValidator, manager);
99    }
100
101    if (baseValidator->getType() != DatatypeValidator::Union)
102    {
103        XMLCh value1[BUF_LEN+1];
104        XMLString::binToText(baseValidator->getType(), value1, BUF_LEN, 10, manager);
105        ThrowXMLwithMemMgr1(InvalidDatatypeFacetException
106                , XMLExcepts::FACET_Union_invalid_baseValidatorType
107                , value1
108                , manager);
109    }
110
111    CleanupType cleanup(this, &UnionDatatypeValidator::cleanUp);
112
113    try
114    {
115        init(baseValidator, facets, enums, manager);
116    }
117    catch(const OutOfMemoryException&)
118    {
119        // Don't cleanup when out of memory, since executing the
120        // code can cause problems.
121        cleanup.release();
122
123        throw;
124    }
125
126    cleanup.release();
127}
128
129void UnionDatatypeValidator::init(DatatypeValidator*            const baseValidator
130                                , RefHashTableOf<KVStringPair>* const facets
131                                , RefArrayVectorOf<XMLCh>*      const enums
132                                , MemoryManager*                const manager)
133{
134    if (enums)
135        setEnumeration(enums, false);
136
137    // Set Facets if any defined
138    if (facets)
139    {
140        XMLCh* key;
141        XMLCh* value;
142        RefHashTableOfEnumerator<KVStringPair> e(facets, false, manager);
143
144        while (e.hasMoreElements())
145        {
146            KVStringPair pair = e.nextElement();
147            key = pair.getKey();
148            value = pair.getValue();
149
150            if (XMLString::equals(key, SchemaSymbols::fgELT_PATTERN))
151            {
152                setPattern(value);
153                if (getPattern())
154                    setFacetsDefined(DatatypeValidator::FACET_PATTERN);
155                // do not construct regex until needed
156            }
157            else
158            {
159                 ThrowXMLwithMemMgr1(InvalidDatatypeFacetException
160                         , XMLExcepts::FACET_Invalid_Tag
161                         , key
162                         , manager);
163            }
164        }//while
165
166        /***
167           Schema constraint: Part I -- self checking
168        ***/
169        // Nil
170
171        /***
172           Schema constraint: Part II base vs derived checking
173        ***/
174        // check 4.3.5.c0 must: enumeration values from the value space of base
175        if ( ((getFacetsDefined() & DatatypeValidator::FACET_ENUMERATION) != 0) &&
176            (getEnumeration() !=0))
177        {
178            XMLSize_t i = 0;
179            XMLSize_t enumLength = getEnumeration()->size();
180            try
181            {
182                for ( ; i < enumLength; i++)
183                {
184                    // ask parent do a complete check
185                    //
186                    // enum need NOT be passed this->checkContent()
187                    // since there are no other facets for Union, parent
188                    // checking is good enough.
189                    //
190                    baseValidator->validate(getEnumeration()->elementAt(i), (ValidationContext*)0, manager);
191
192                }
193            }
194
195            catch ( XMLException& )
196            {
197                ThrowXMLwithMemMgr1(InvalidDatatypeFacetException
198                            , XMLExcepts::FACET_enum_base
199                            , getEnumeration()->elementAt(i)
200                            , manager);
201            }
202        }
203
204    }// End of Facet setting
205
206    /***
207        Inherit facets from base.facets
208
209        The reason of this inheriting (or copying values) is to ease
210        schema constraint checking, so that we need NOT trace back to our
211        very first base validator in the hierachy. Instead, we are pretty
212        sure checking against immediate base validator is enough.
213    ***/
214
215    UnionDatatypeValidator *pBaseValidator = (UnionDatatypeValidator*) baseValidator;
216
217    // inherit enumeration
218    if (((pBaseValidator->getFacetsDefined() & DatatypeValidator::FACET_ENUMERATION) !=0) &&
219        ((getFacetsDefined() & DatatypeValidator::FACET_ENUMERATION) == 0))
220    {
221        setEnumeration(pBaseValidator->getEnumeration(), true);
222    }
223
224}
225
226//
227// 1) the bottom level UnionDTV would check against
228//        pattern and enumeration as well
229// 2) each UnionDTV(s) above the bottom level UnionDTV and
230//        below the native UnionDTV (the top level DTV)
231//        would check against pattern only.
232// 3) the natvie Union DTV (the top level DTV) would invoke
233//        memberTypeValidator to validate
234//
235void UnionDatatypeValidator::checkContent(const XMLCh*             const content
236                                        ,       ValidationContext* const context
237                                        ,       bool                     asBase
238                                        ,       MemoryManager*     const manager)
239{
240
241    DatatypeValidator* bv = getBaseValidator();
242    if (bv)
243        ((UnionDatatypeValidator*)bv)->checkContent(content, context, true, manager);
244    else
245    {   // 3) native union type
246        // check content against each member type validator in Union
247        // report an error only in case content is not valid against all member datatypes.
248        //
249        bool memTypeValid = false;
250        for ( unsigned int i = 0; i < fMemberTypeValidators->size(); ++i )
251        {
252            if ( memTypeValid )
253                break;
254
255            try
256            {
257                fMemberTypeValidators->elementAt(i)->validate(content, context, manager);
258                memTypeValid = true;
259               
260                //set the validator of the type actually used to validate the content
261                DatatypeValidator *dtv = fMemberTypeValidators->elementAt(i);               
262                // context will be null during schema construction
263                if(context)
264                    context->setValidatingMemberType(dtv);
265            }
266            catch (XMLException&)
267            {
268                //absorbed
269            }
270        } // for
271
272        if ( !memTypeValid )
273        {
274            ThrowXMLwithMemMgr1(InvalidDatatypeValueException
275                    , XMLExcepts::VALUE_no_match_memberType
276                    , content
277                    , manager);
278            //( "Content '"+content+"' does not match any union types" );
279        }
280    }
281
282    // 1) and 2). we check pattern first
283    if ( (getFacetsDefined() & DatatypeValidator::FACET_PATTERN ) != 0 )
284    {
285        if (getRegex()->matches(content, manager) == false)
286        {
287            ThrowXMLwithMemMgr2(InvalidDatatypeValueException
288                    , XMLExcepts::VALUE_NotMatch_Pattern
289                    , content
290                    , getPattern()
291                    , manager);
292        }
293    }
294
295    // if this is a base validator, we only need to check pattern facet
296    // all other facet were inherited by the derived type
297    if (asBase)
298        return;
299
300    if ((getFacetsDefined() & DatatypeValidator::FACET_ENUMERATION) != 0 &&
301        (getEnumeration() != 0))
302    {
303
304        // If the content match (compare equal) any enumeration with
305        // any of the member types, it is considerd valid.
306        //
307        RefVectorOf<DatatypeValidator>* memberDTV = getMemberTypeValidators();
308        RefArrayVectorOf<XMLCh>* tmpEnum = getEnumeration();
309        XMLSize_t memberTypeNumber = memberDTV->size();
310        XMLSize_t enumLength = tmpEnum->size();
311
312        for ( XMLSize_t memberIndex = 0; memberIndex < memberTypeNumber; ++memberIndex)
313        {
314            for ( XMLSize_t enumIndex = 0; enumIndex < enumLength; ++enumIndex)
315            {
316                try
317                {
318                    if (memberDTV->elementAt(memberIndex)->compare(content, tmpEnum->elementAt(enumIndex), manager) == 0)
319                        return;
320                }
321                catch (XMLException&)
322                {
323                    //absorbed
324                }
325            } // for enumIndex
326        } // for memberIndex
327
328        ThrowXMLwithMemMgr1(InvalidDatatypeValueException, XMLExcepts::VALUE_NotIn_Enumeration, content, manager);
329
330    } // enumeration
331
332}
333
334//
335//
336//
337int UnionDatatypeValidator::compare(const XMLCh* const lValue
338                                  , const XMLCh* const rValue
339                                  , MemoryManager* const manager)
340{
341    RefVectorOf<DatatypeValidator>* memberDTV = getMemberTypeValidators();
342    XMLSize_t memberTypeNumber = memberDTV->size();
343
344    for ( XMLSize_t memberIndex = 0; memberIndex < memberTypeNumber; ++memberIndex)
345    {
346        // 'compare' can throw exceptions when the datatype is not valid, or just
347        // return -1; so attempt to validate both values to get the right validator
348        try
349        {
350            memberDTV->elementAt(memberIndex)->validate(lValue, 0, manager);                       
351            memberDTV->elementAt(memberIndex)->validate(rValue, 0, manager);                       
352            if (memberDTV->elementAt(memberIndex)->compare(lValue, rValue, manager) ==0)
353                return  0;
354        }
355        catch (XMLException&)
356        {
357            //absorbed
358        }
359    }
360
361    //REVISIT: what does it mean for UNION1 to be <less than> or <greater than> UNION2 ?
362    // As long as -1 or +1 indicates an unequality, return either of them is ok.
363    return -1;
364}
365
366const RefArrayVectorOf<XMLCh>* UnionDatatypeValidator::getEnumString() const
367{
368        return getEnumeration();
369}
370
371/***
372 * 2.5.1.3 Union datatypes
373 *
374 * The canonical-lexical-representation for a union datatype is defined as the lexical form
375 * in which the values have the canonical lexical representation of the appropriate memberTypes.       
376 ***/
377const XMLCh* UnionDatatypeValidator::getCanonicalRepresentation(const XMLCh*         const rawData
378                                                              ,       MemoryManager* const memMgr
379                                                              ,       bool                 toValidate) const
380{
381    MemoryManager* toUse = memMgr? memMgr : getMemoryManager();
382    UnionDatatypeValidator* temp = (UnionDatatypeValidator*) this;
383
384    if (toValidate)
385    {
386        try
387        {
388            temp->checkContent(rawData, 0, false, toUse);
389        }
390        catch (...)
391        {
392            return 0;
393        }
394    }   
395
396    //get the native unionDv
397    UnionDatatypeValidator* bdv = (UnionDatatypeValidator*) temp->getBaseValidator();
398    while (bdv)
399    {
400        temp = bdv;
401        bdv = (UnionDatatypeValidator*) temp->getBaseValidator();
402    }
403
404    //let the member dv which recognize the rawData, to return
405    //us the canonical form
406    for ( unsigned int i = 0; i < temp->fMemberTypeValidators->size(); ++i )
407    {
408        try
409        {
410            temp->fMemberTypeValidators->elementAt(i)->validate(rawData, 0, toUse);                       
411            return temp->fMemberTypeValidators->elementAt(i)->getCanonicalRepresentation(rawData, toUse, false);
412        }
413        catch (XMLException&)
414        {
415            //absorbed
416        }
417    }
418
419    //if no member dv recognize it
420    return 0;
421}
422
423
424/***
425 * Support for Serialization/De-serialization
426 ***/
427
428IMPL_XSERIALIZABLE_TOCREATE(UnionDatatypeValidator)
429
430void UnionDatatypeValidator::serialize(XSerializeEngine& serEng)
431{
432
433    DatatypeValidator::serialize(serEng);
434
435    if (serEng.isStoring())
436    {
437        serEng<<fEnumerationInherited;
438        serEng<<fMemberTypesInherited;
439
440        /***
441         * Serialize RefArrayVectorOf<XMLCh>
442         * Serialize RefVectorOf<DatatypeValidator>
443         ***/
444        XTemplateSerializer::storeObject(fEnumeration, serEng);
445        XTemplateSerializer::storeObject(fMemberTypeValidators, serEng);
446    }
447    else
448    {
449        serEng>>fEnumerationInherited;
450        serEng>>fMemberTypesInherited;
451
452        /***
453         * Deserialize RefArrayVectorOf<XMLCh>
454         * Deserialize RefVectorOf<DatatypeValidator>
455         ***/
456        XTemplateSerializer::loadObject(&fEnumeration, 8, true, serEng);
457        XTemplateSerializer::loadObject(&fMemberTypeValidators, 4, false, serEng);
458    }
459}
460
461XERCES_CPP_NAMESPACE_END
462
463/**
464  * End of file UnionDatatypeValidator.cpp
465  */
Note: See TracBrowser for help on using the repository browser.