source: icXML/icXML-devel/src/xercesc/validators/datatype/ListDatatypeValidator.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.9 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: ListDatatypeValidator.cpp 695949 2008-09-16 15:57:44Z borisk $
20 */
21
22// ---------------------------------------------------------------------------
23//  Includes
24// ---------------------------------------------------------------------------
25#include <xercesc/validators/datatype/ListDatatypeValidator.hpp>
26#include <xercesc/validators/datatype/InvalidDatatypeFacetException.hpp>
27#include <xercesc/validators/datatype/InvalidDatatypeValueException.hpp>
28#include <xercesc/util/OutOfMemoryException.hpp>
29
30XERCES_CPP_NAMESPACE_BEGIN
31
32static const int BUF_LEN = 64;
33
34// ---------------------------------------------------------------------------
35//  Constructors and Destructor
36// ---------------------------------------------------------------------------
37ListDatatypeValidator::ListDatatypeValidator(MemoryManager* const manager)
38:AbstractStringValidator(0, 0, 0, DatatypeValidator::List, manager)
39,fContent(0)
40{}
41
42ListDatatypeValidator::ListDatatypeValidator(
43                          DatatypeValidator*            const baseValidator
44                        , RefHashTableOf<KVStringPair>* const facets
45                        , RefArrayVectorOf<XMLCh>*           const enums
46                        , const int                           finalSet
47                        , MemoryManager* const manager)
48:AbstractStringValidator(baseValidator, facets, finalSet, DatatypeValidator::List, manager)
49,fContent(0)
50{
51    //
52    // baseValidator shall either
53    // an atomic DTV which servers as itemType, or
54    // another ListDTV from which, this ListDTV is derived by restriction.
55    //
56    // In either case, it shall be not null
57    //
58    if (!baseValidator)
59        ThrowXMLwithMemMgr(InvalidDatatypeFacetException, XMLExcepts::FACET_List_Null_baseValidator, manager);
60
61    init(enums, manager);
62}
63
64ListDatatypeValidator::~ListDatatypeValidator()
65{}
66
67DatatypeValidator* ListDatatypeValidator::newInstance
68(
69      RefHashTableOf<KVStringPair>* const facets
70    , RefArrayVectorOf<XMLCh>* const      enums
71    , const int                           finalSet
72    , MemoryManager* const                manager
73)
74{
75    return (DatatypeValidator*) new (manager) ListDatatypeValidator(this, facets, enums, finalSet, manager);
76}
77
78
79int ListDatatypeValidator::compare(const XMLCh*     const lValue
80                                 , const XMLCh*     const rValue
81                                 , MemoryManager*   const manager)
82{
83    DatatypeValidator* theItemTypeDTV = getItemTypeDTV();
84    BaseRefVectorOf<XMLCh>* lVector = XMLString::tokenizeString(lValue, manager);
85    Janitor<BaseRefVectorOf<XMLCh> > janl(lVector);
86    BaseRefVectorOf<XMLCh>* rVector = XMLString::tokenizeString(rValue, manager);
87    Janitor<BaseRefVectorOf<XMLCh> > janr(rVector);
88
89    XMLSize_t lNumberOfTokens = lVector->size();
90    XMLSize_t rNumberOfTokens = rVector->size();
91
92    if (lNumberOfTokens < rNumberOfTokens)
93        return -1;
94    else if (lNumberOfTokens > rNumberOfTokens)
95        return 1;
96    else
97    { //compare each token
98        for ( XMLSize_t i = 0; i < lNumberOfTokens; i++)
99        {
100            int returnValue = theItemTypeDTV->compare(lVector->elementAt(i), rVector->elementAt(i), manager);
101            if (returnValue != 0)
102                return returnValue; //REVISIT: does it make sense to return -1 or +1..?
103        }
104        return 0;
105    }
106
107}
108
109void ListDatatypeValidator::validate( const XMLCh*             const content
110                                    ,       ValidationContext* const context
111                                    ,       MemoryManager*     const manager)
112{
113    setContent(content);
114    BaseRefVectorOf<XMLCh>* tokenVector = XMLString::tokenizeString(content, manager);
115    Janitor<BaseRefVectorOf<XMLCh> > janName(tokenVector);
116    checkContent(tokenVector, content, context, false, manager);
117}
118
119void ListDatatypeValidator::checkContent( const XMLCh*             const content
120                                         ,      ValidationContext* const context
121                                         ,      bool                     asBase
122                                         ,      MemoryManager*     const manager)
123{
124    setContent(content);
125    BaseRefVectorOf<XMLCh>* tokenVector = XMLString::tokenizeString(content, manager);
126    Janitor<BaseRefVectorOf<XMLCh> > janName(tokenVector);
127    checkContent(tokenVector, content, context, asBase, manager);
128}
129
130//
131// here content is a list of items
132//
133void ListDatatypeValidator::checkContent(       BaseRefVectorOf<XMLCh>*       tokenVector
134                                        , const XMLCh*                  const content
135                                        ,       ValidationContext*      const context
136                                        ,       bool                          asBase
137                                        ,       MemoryManager*          const manager)
138{
139    DatatypeValidator* bv = getBaseValidator();
140
141    if (bv->getType() == DatatypeValidator::List)
142        ((ListDatatypeValidator*)bv)->checkContent(tokenVector, content, context, true, manager);
143    else
144    {   // the ultimate itemType DTV
145        for (unsigned int i = 0; i < tokenVector->size(); i++)
146            bv->validate(tokenVector->elementAt(i), context, manager);
147    }
148
149    int thisFacetsDefined = getFacetsDefined();
150
151    // we check pattern first
152    if ( (thisFacetsDefined & DatatypeValidator::FACET_PATTERN ) != 0 )
153    {
154        //check every item in the list as a whole
155        if (getRegex()->matches(content, manager) == false)
156        {
157            ThrowXMLwithMemMgr2(InvalidDatatypeValueException
158                    , XMLExcepts::VALUE_NotMatch_Pattern
159                    , content
160                    , getPattern()
161                    , manager);
162        }
163
164    }
165
166    // if this is a base validator, we only need to check pattern facet
167    // all other facet were inherited by the derived type
168    if (asBase)
169        return;
170
171    XMLSize_t tokenNumber = tokenVector->size();
172
173    if (((thisFacetsDefined & DatatypeValidator::FACET_MAXLENGTH) != 0) &&
174        (tokenNumber > getMaxLength()))
175    {
176        XMLCh value1[BUF_LEN+1];
177        XMLCh value2[BUF_LEN+1];
178        XMLString::sizeToText(tokenNumber, value1, BUF_LEN, 10, manager);
179        XMLString::sizeToText(getMaxLength(), value2, BUF_LEN, 10, manager);
180
181        ThrowXMLwithMemMgr3(InvalidDatatypeValueException
182                , XMLExcepts::VALUE_GT_maxLen
183                , getContent()
184                , value1
185                , value2
186                , manager);
187    }
188
189    if (((thisFacetsDefined & DatatypeValidator::FACET_MINLENGTH) != 0) &&
190        (tokenNumber < getMinLength()))
191    {
192        XMLCh value1[BUF_LEN+1];
193        XMLCh value2[BUF_LEN+1];
194        XMLString::sizeToText(tokenNumber, value1, BUF_LEN, 10, manager);
195        XMLString::sizeToText(getMinLength(), value2, BUF_LEN, 10, manager);
196
197        ThrowXMLwithMemMgr3(InvalidDatatypeValueException
198                , XMLExcepts::VALUE_LT_minLen
199                , getContent()
200                , value1
201                , value2
202                , manager);
203    }
204
205    if (((thisFacetsDefined & DatatypeValidator::FACET_LENGTH) != 0) &&
206        (tokenNumber != AbstractStringValidator::getLength()))
207    {
208        XMLCh value1[BUF_LEN+1];
209        XMLCh value2[BUF_LEN+1];
210        XMLString::sizeToText(tokenNumber, value1, BUF_LEN, 10, manager);
211        XMLString::sizeToText(AbstractStringValidator::getLength(), value2, BUF_LEN, 10, manager);
212
213        ThrowXMLwithMemMgr3(InvalidDatatypeValueException
214                , XMLExcepts::VALUE_NE_Len
215                , getContent()
216                , value1
217                , value2
218                , manager);
219    }
220
221    if ((thisFacetsDefined & DatatypeValidator::FACET_ENUMERATION) != 0 &&
222        (getEnumeration() != 0))
223    {
224        XMLSize_t i;
225        XMLSize_t enumLength = getEnumeration()->size();
226
227        for ( i = 0; i < enumLength; i++)
228        {
229            //optimization: we do a lexical comparision first
230            // this may be faster for string and its derived
231            if (XMLString::equals(getEnumeration()->elementAt(i), getContent()))
232                break; // a match found
233
234            // do a value space check
235            // this is needed for decimal (and probably other types
236            // such as datetime related)
237            // eg.
238            // tokenVector = "1 2 3.0 4" vs enumeration = "1 2 3 4.0"
239            //
240            if (valueSpaceCheck(tokenVector, getEnumeration()->elementAt(i), manager))
241                break;
242        }
243
244        if (i == enumLength)
245            ThrowXMLwithMemMgr1(InvalidDatatypeValueException, XMLExcepts::VALUE_NotIn_Enumeration, getContent(), manager);
246
247    } // enumeration
248
249}
250
251bool ListDatatypeValidator::valueSpaceCheck(BaseRefVectorOf<XMLCh>* tokenVector
252                                          , const XMLCh*    const  enumStr
253                                          , MemoryManager*  const  manager) const
254{
255    DatatypeValidator* theItemTypeDTV = getItemTypeDTV();
256    BaseRefVectorOf<XMLCh>* enumVector = XMLString::tokenizeString(enumStr, manager);
257    Janitor<BaseRefVectorOf<XMLCh> > janName(enumVector);
258
259    if (tokenVector->size() != enumVector->size())
260        return false;
261
262    for ( unsigned int j = 0; j < tokenVector->size(); j++ )
263    {
264        if (theItemTypeDTV->compare(tokenVector->elementAt(j), enumVector->elementAt(j), manager) != 0)
265            return false;
266    }
267
268    return true;
269}
270
271DatatypeValidator* ListDatatypeValidator::getItemTypeDTV() const
272{
273    DatatypeValidator* bdv = this->getBaseValidator();
274
275    while (bdv->getType() == DatatypeValidator::List)
276        bdv = bdv->getBaseValidator();
277
278    return bdv;
279}
280
281// ---------------------------------------------------------------------------
282//  Utilities
283// ---------------------------------------------------------------------------
284
285void ListDatatypeValidator::checkValueSpace(const XMLCh* const
286                                            , MemoryManager* const)
287{}
288
289XMLSize_t ListDatatypeValidator::getLength(const XMLCh* const content
290                                     , MemoryManager* const manager) const
291{
292    BaseRefVectorOf<XMLCh>* tokenVector = XMLString::tokenizeString(content, manager);
293    Janitor<BaseRefVectorOf<XMLCh> > janName(tokenVector);
294
295    return tokenVector->size();
296}
297
298void ListDatatypeValidator::inspectFacetBase(MemoryManager* const manager)
299{
300
301    //
302    // we are pretty sure baseValidator is not null
303    //
304
305    if (getBaseValidator()->getType() == DatatypeValidator::List)
306    {
307        AbstractStringValidator::inspectFacetBase(manager);
308    }
309    else
310    {
311        // the first level ListDTV
312        // check 4.3.5.c0 must: enumeration values from the value space of base
313        if ( ((getFacetsDefined() & DatatypeValidator::FACET_ENUMERATION) != 0) &&
314             (getEnumeration() !=0)                                              )
315        {
316            XMLSize_t i;
317            XMLSize_t enumLength = getEnumeration()->size();
318            try
319            {
320                for ( i = 0; i < enumLength; i++)
321                {
322                    // ask the itemType for a complete check
323                    BaseRefVectorOf<XMLCh>* tempList = XMLString::tokenizeString(getEnumeration()->elementAt(i), manager);
324                    Janitor<BaseRefVectorOf<XMLCh> >    jan(tempList);
325                    XMLSize_t tokenNumber = tempList->size();
326
327                    try
328                    {
329                        for ( XMLSize_t j = 0; j < tokenNumber; j++)
330                            getBaseValidator()->validate(tempList->elementAt(j), (ValidationContext*)0, manager);
331                    }
332                    catch(const OutOfMemoryException&)
333                    {
334                        jan.release();
335
336                        throw;
337                    }
338#if 0
339// spec says that only base has to checkContent                   
340                    // enum shall pass this->checkContent() as well.
341                    checkContent(getEnumeration()->elementAt(i), (ValidationContext*)0, false, manager);
342#endif
343                }
344            }
345
346            catch ( XMLException& )
347            {
348                ThrowXMLwithMemMgr1(InvalidDatatypeFacetException
349                        , XMLExcepts::FACET_enum_base
350                        , getEnumeration()->elementAt(i)
351                        , manager);
352            }
353
354        }
355
356    }
357
358}// End of inspectFacetBase()
359
360void ListDatatypeValidator::inheritFacet()
361{
362
363    //iff the base validator is List, then we inherit
364    //
365    if (getBaseValidator()->getType() == DatatypeValidator::List)
366    {
367        AbstractStringValidator::inheritFacet();
368    }
369
370}
371
372/***
373 * 2.5.1.2 List datatypes   
374 *   
375 * The canonical-lexical-representation for the list datatype is defined as
376 * the lexical form in which each item in the list has the canonical
377 * lexical representation of its itemType.
378 ***/
379const XMLCh* ListDatatypeValidator::getCanonicalRepresentation(const XMLCh*         const rawData
380                                                             ,       MemoryManager* const memMgr
381                                                             ,       bool                 toValidate) const
382{
383    MemoryManager* toUse = memMgr? memMgr : getMemoryManager();
384    ListDatatypeValidator* temp = (ListDatatypeValidator*) this;
385    temp->setContent(rawData);
386    BaseRefVectorOf<XMLCh>* tokenVector = XMLString::tokenizeString(rawData, toUse);
387    Janitor<BaseRefVectorOf<XMLCh> > janName(tokenVector);   
388
389    if (toValidate)
390    {
391        try
392        {
393            temp->checkContent(tokenVector, rawData, 0, false, toUse);
394        }
395        catch (...)
396        {
397            return 0;
398        }
399    }
400   
401    XMLSize_t retBufSize = 2 * XMLString::stringLen(rawData);
402    XMLCh* retBuf = (XMLCh*) toUse->allocate(retBufSize * sizeof(XMLCh));
403    retBuf[0] = 0;
404    XMLCh* retBufPtr = retBuf;
405    DatatypeValidator* itemDv = this->getItemTypeDTV();
406
407    try
408    {
409        for (unsigned int i = 0; i < tokenVector->size(); i++)
410        {
411            XMLCh* itemCanRep = (XMLCh*) itemDv->getCanonicalRepresentation(tokenVector->elementAt(i), toUse, false);
412            XMLSize_t itemLen = XMLString::stringLen(itemCanRep); 
413
414            if(retBufPtr+itemLen+2 >= retBuf+retBufSize)
415            {
416                // need to resize
417                XMLCh * oldBuf = retBuf;
418                retBuf = (XMLCh*) toUse->allocate(retBufSize * sizeof(XMLCh) * 4);
419                memcpy(retBuf, oldBuf, retBufSize * sizeof(XMLCh ));
420                retBufPtr = (retBufPtr - oldBuf) + retBuf;
421                toUse->deallocate(oldBuf);
422                retBufSize <<= 2;
423            }
424
425            XMLString::catString(retBufPtr, itemCanRep);
426            retBufPtr = retBufPtr + itemLen;
427            *(retBufPtr++) = chSpace;
428            *(retBufPtr) = chNull;
429            toUse->deallocate(itemCanRep);
430        }
431
432        return retBuf;
433
434    }
435    catch (...)
436    {
437        return 0;
438    }
439}
440
441/***
442 * Support for Serialization/De-serialization
443 ***/
444
445IMPL_XSERIALIZABLE_TOCREATE(ListDatatypeValidator)
446
447void ListDatatypeValidator::serialize(XSerializeEngine& serEng)
448{
449    AbstractStringValidator::serialize(serEng);
450
451    //don't serialize fContent, since it is NOT owned and
452    //will be reset each time validate()/checkContent() invoked.
453}
454
455XERCES_CPP_NAMESPACE_END
456
457/**
458  * End of file ListDatatypeValidator.cpp
459  */
Note: See TracBrowser for help on using the repository browser.