source: icXML/icXML-devel/src/xercesc/validators/datatype/DecimalDatatypeValidator.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: 22.0 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: DecimalDatatypeValidator.cpp 932887 2010-04-11 13:04:59Z borisk $
20 */
21
22// ---------------------------------------------------------------------------
23//  Includes
24// ---------------------------------------------------------------------------
25#include <xercesc/validators/datatype/DecimalDatatypeValidator.hpp>
26#include <xercesc/validators/datatype/XMLCanRepGroup.hpp>
27#include <xercesc/validators/schema/SchemaSymbols.hpp>
28#include <xercesc/validators/datatype/InvalidDatatypeFacetException.hpp>
29#include <xercesc/validators/datatype/InvalidDatatypeValueException.hpp>
30
31#include <icxercesc/validators/datatype/DatatypeValidatorFactory.hpp>
32#include <xercesc/util/NumberFormatException.hpp>
33#include <xercesc/util/XMLBigDecimal.hpp>
34#include <xercesc/util/XMLBigInteger.hpp>
35
36XERCES_CPP_NAMESPACE_BEGIN
37
38static const int BUF_LEN = 64;
39
40// ---------------------------------------------------------------------------
41//  Constructors and Destructor
42// ---------------------------------------------------------------------------
43DecimalDatatypeValidator::DecimalDatatypeValidator(MemoryManager* const manager)
44:AbstractNumericValidator(0, 0, 0, DatatypeValidator::Decimal, manager)
45, fTotalDigits(0)
46, fFractionDigits(0)
47{
48    setOrdered(XSSimpleTypeDefinition::ORDERED_TOTAL);
49    setNumeric(true);
50}
51
52DecimalDatatypeValidator::DecimalDatatypeValidator(
53                          DatatypeValidator*            const baseValidator
54                        , RefHashTableOf<KVStringPair>* const facets
55                        , RefArrayVectorOf<XMLCh>*      const enums
56                        , const int                           finalSet
57                        , MemoryManager*                const manager)
58:AbstractNumericValidator(baseValidator, facets, finalSet, DatatypeValidator::Decimal, manager)
59, fTotalDigits(0)
60, fFractionDigits(0)
61{
62    init(enums, manager);
63}
64
65DecimalDatatypeValidator::~DecimalDatatypeValidator()
66{
67}
68
69// -----------------------------------------------------------------------
70// Compare methods
71// -----------------------------------------------------------------------
72int DecimalDatatypeValidator::compare(const XMLCh* const lValue
73                                    , const XMLCh* const rValue
74                                    , MemoryManager* const manager)
75{
76    XMLBigDecimal lObj(lValue, manager);
77    XMLBigDecimal rObj(rValue, manager);
78
79    return compareValues(&lObj, &rObj);
80}
81
82DatatypeValidator* DecimalDatatypeValidator::newInstance
83(
84      RefHashTableOf<KVStringPair>* const facets
85    , RefArrayVectorOf<XMLCh>* const      enums
86    , const int                           finalSet
87    , MemoryManager* const                manager
88)
89{
90    return (DatatypeValidator*) new (manager) DecimalDatatypeValidator(this, facets, enums, finalSet, manager);
91}
92
93// -----------------------------------------------------------------------
94// ctor provided to be used by derived classes
95// -----------------------------------------------------------------------
96DecimalDatatypeValidator::DecimalDatatypeValidator(DatatypeValidator*            const baseValidator
97                                                 , RefHashTableOf<KVStringPair>* const facets
98                                                 , const int                           finalSet
99                                                 , const ValidatorType                 type
100                                                 , MemoryManager* const                manager)
101:AbstractNumericValidator(baseValidator, facets, finalSet, type, manager)
102, fTotalDigits(0)
103, fFractionDigits(0)
104{
105    //do not invoke init here !!!
106}
107
108void DecimalDatatypeValidator::assignAdditionalFacet(const XMLCh* const key
109                                                   , const XMLCh* const value
110                                                   , MemoryManager* const manager)
111{
112    if (XMLString::equals(key, SchemaSymbols::fgELT_TOTALDIGITS))
113    {
114        int val;
115        try
116        {
117            val = XMLString::parseInt(value, manager);
118        }
119        catch (NumberFormatException&)
120        {
121            ThrowXMLwithMemMgr1(InvalidDatatypeFacetException, XMLExcepts::FACET_Invalid_TotalDigit, value, manager);
122        }
123
124        // check 4.3.11.c0 must: totalDigits > 0
125        if ( val <= 0 )
126            ThrowXMLwithMemMgr1(InvalidDatatypeFacetException, XMLExcepts::FACET_PosInt_TotalDigit, value, manager);
127
128        setTotalDigits(val);
129        setFacetsDefined(DatatypeValidator::FACET_TOTALDIGITS);
130    }
131    else if (XMLString::equals(key, SchemaSymbols::fgELT_FRACTIONDIGITS))
132    {
133        int val;
134        try
135        {
136            val = XMLString::parseInt(value, manager);
137        }
138        catch (NumberFormatException&)
139        {
140            ThrowXMLwithMemMgr1(InvalidDatatypeFacetException, XMLExcepts::FACET_Invalid_FractDigit, value, manager);
141        }
142
143        // check 4.3.12.c0 must: fractionDigits > 0
144        if ( val < 0 )
145            ThrowXMLwithMemMgr1(InvalidDatatypeFacetException, XMLExcepts::FACET_NonNeg_FractDigit, value, manager);
146
147        setFractionDigits(val);
148        setFacetsDefined(DatatypeValidator::FACET_FRACTIONDIGITS);
149    }
150    else
151    {
152        ThrowXMLwithMemMgr1(InvalidDatatypeFacetException
153                , XMLExcepts::FACET_Invalid_Tag
154                , key
155                , manager);
156    }
157}
158
159void DecimalDatatypeValidator::inheritAdditionalFacet()
160{
161
162    DecimalDatatypeValidator *numBase = (DecimalDatatypeValidator*) getBaseValidator();
163
164    if (!numBase)
165        return;
166
167    int thisFacetsDefined = getFacetsDefined();
168    int baseFacetsDefined = numBase->getFacetsDefined();
169
170    // inherit totalDigits
171    if ((( baseFacetsDefined & DatatypeValidator::FACET_TOTALDIGITS) != 0) &&
172        (( thisFacetsDefined & DatatypeValidator::FACET_TOTALDIGITS) == 0) )
173    {
174        setTotalDigits(numBase->fTotalDigits);
175        setFacetsDefined(DatatypeValidator::FACET_TOTALDIGITS);
176    }
177
178    // inherit fractionDigits
179    if ((( baseFacetsDefined & DatatypeValidator::FACET_FRACTIONDIGITS) != 0) &&
180        (( thisFacetsDefined & DatatypeValidator::FACET_FRACTIONDIGITS) == 0) )
181    {
182        setFractionDigits(numBase->fFractionDigits);
183        setFacetsDefined(DatatypeValidator::FACET_FRACTIONDIGITS);
184    }
185}
186
187void DecimalDatatypeValidator::checkAdditionalFacetConstraints(MemoryManager* const manager) const
188{
189    int thisFacetsDefined = getFacetsDefined();
190
191    // check 4.3.12.c1 must: fractionDigits <= totalDigits
192    if ( ((thisFacetsDefined & DatatypeValidator::FACET_FRACTIONDIGITS) != 0) &&
193         ((thisFacetsDefined & DatatypeValidator::FACET_TOTALDIGITS) != 0) )
194    {
195        if ( fFractionDigits > fTotalDigits )
196        {
197            XMLCh value1[BUF_LEN+1];
198            XMLCh value2[BUF_LEN+1];
199            XMLString::binToText(getFractionDigits(), value1, BUF_LEN, 10, manager);
200            XMLString::binToText(getTotalDigits(), value2, BUF_LEN, 10, manager);
201            ThrowXMLwithMemMgr2(InvalidDatatypeFacetException
202                                 , XMLExcepts::FACET_TotDigit_FractDigit
203                                 , value2
204                                 , value1
205                                 , manager);
206        }
207    }
208
209}
210
211void DecimalDatatypeValidator::checkAdditionalFacetConstraintsBase(MemoryManager* const manager) const
212{
213
214    DecimalDatatypeValidator *numBase = (DecimalDatatypeValidator*) getBaseValidator();
215
216    if (!numBase)
217        return;
218
219    int thisFacetsDefined = getFacetsDefined();
220    int baseFacetsDefined = numBase->getFacetsDefined();
221
222    // check 4.3.11.c1 error: totalDigits > base.totalDigits
223    // totalDigits != base.totalDigits if (base.fixed)
224    if (( thisFacetsDefined & DatatypeValidator::FACET_TOTALDIGITS) != 0)
225    {
226        if ( (( baseFacetsDefined & DatatypeValidator::FACET_TOTALDIGITS) != 0) &&
227            ( fTotalDigits > numBase->fTotalDigits ))
228        {
229            XMLCh value1[BUF_LEN+1];
230            XMLCh value2[BUF_LEN+1];
231            XMLString::binToText(fTotalDigits, value1, BUF_LEN, 10, manager);
232            XMLString::binToText(numBase->fTotalDigits, value2, BUF_LEN, 10, manager);
233            ThrowXMLwithMemMgr2(InvalidDatatypeFacetException
234                                 , XMLExcepts::FACET_totalDigit_base_totalDigit
235                                 , value1
236                                 , value2
237                                 , manager);
238        }
239
240        if ( (( baseFacetsDefined & DatatypeValidator::FACET_TOTALDIGITS) != 0) &&
241            (( numBase->getFixed() & DatatypeValidator::FACET_TOTALDIGITS) != 0) &&
242            ( fTotalDigits != numBase->fTotalDigits ))
243        {
244            XMLCh value1[BUF_LEN+1];
245            XMLCh value2[BUF_LEN+1];
246            XMLString::binToText(fTotalDigits, value1, BUF_LEN, 10, manager);
247            XMLString::binToText(numBase->fTotalDigits, value2, BUF_LEN, 10, manager);
248            ThrowXMLwithMemMgr2(InvalidDatatypeFacetException
249                                 , XMLExcepts::FACET_totalDigit_base_fixed
250                                 , value1
251                                 , value2
252                                 , manager);
253        }
254    }
255
256    if (( thisFacetsDefined & DatatypeValidator::FACET_FRACTIONDIGITS) != 0)
257    {
258        // check question error: fractionDigits > base.fractionDigits ???
259        if ( (( baseFacetsDefined & DatatypeValidator::FACET_FRACTIONDIGITS) != 0) &&
260            ( fFractionDigits > numBase->fFractionDigits ))
261        {
262            XMLCh value1[BUF_LEN+1];
263            XMLCh value2[BUF_LEN+1];
264            XMLString::binToText(fFractionDigits, value1, BUF_LEN, 10, manager);
265            XMLString::binToText(numBase->fFractionDigits, value2, BUF_LEN, 10, manager);
266            ThrowXMLwithMemMgr2(InvalidDatatypeFacetException
267                                 , XMLExcepts::FACET_fractDigit_base_fractDigit
268                                 , value1
269                                 , value2
270                                 , manager);
271                        }
272
273        // check question error: fractionDigits > base.totalDigits ???
274        if ( (( baseFacetsDefined & DatatypeValidator::FACET_TOTALDIGITS) != 0) &&
275            ( fFractionDigits > numBase->fTotalDigits ))
276        {
277            XMLCh value1[BUF_LEN+1];
278            XMLCh value2[BUF_LEN+1];
279            XMLString::binToText(fFractionDigits, value1, BUF_LEN, 10, manager);
280            XMLString::binToText(numBase->fTotalDigits, value2, BUF_LEN, 10, manager);
281            ThrowXMLwithMemMgr2(InvalidDatatypeFacetException
282                                 , XMLExcepts::FACET_fractDigit_base_totalDigit
283                                 , value1
284                                 , value2
285                                 , manager);
286        }
287
288        // fractionDigits != base.fractionDigits if (base.fixed)
289        if ( (( baseFacetsDefined & DatatypeValidator::FACET_FRACTIONDIGITS) != 0) &&
290            (( numBase->getFixed() & DatatypeValidator::FACET_FRACTIONDIGITS) != 0) &&
291            ( fFractionDigits != numBase->fFractionDigits ))
292        {
293            XMLCh value1[BUF_LEN+1];
294            XMLCh value2[BUF_LEN+1];
295            XMLString::binToText(fFractionDigits, value1, BUF_LEN, 10, manager);
296            XMLString::binToText(numBase->fFractionDigits, value2, BUF_LEN, 10, manager);
297            ThrowXMLwithMemMgr2(InvalidDatatypeFacetException
298                                 , XMLExcepts::FACET_fractDigit_base_fixed
299                                 , value1
300                                 , value2
301                                 , manager);
302        }
303    }
304
305}
306
307int  DecimalDatatypeValidator::compareValues(const XMLNumber* const lValue
308                                           , const XMLNumber* const rValue)
309{
310    return XMLBigDecimal::compareValues((XMLBigDecimal*) lValue, (XMLBigDecimal*) rValue,
311                                        ((XMLBigDecimal*)lValue)->getMemoryManager());
312}
313
314void  DecimalDatatypeValidator::setMaxInclusive(const XMLCh* const value)
315{
316    fMaxInclusive = new (fMemoryManager) XMLBigDecimal(value, fMemoryManager);
317}
318
319void  DecimalDatatypeValidator::setMaxExclusive(const XMLCh* const value)
320{
321    fMaxExclusive = new (fMemoryManager) XMLBigDecimal(value, fMemoryManager);
322}
323
324void  DecimalDatatypeValidator::setMinInclusive(const XMLCh* const value)
325{
326    fMinInclusive = new (fMemoryManager) XMLBigDecimal(value, fMemoryManager);
327}
328
329void  DecimalDatatypeValidator::setMinExclusive(const XMLCh* const value)
330{
331    fMinExclusive = new (fMemoryManager) XMLBigDecimal(value, fMemoryManager);
332}
333
334void DecimalDatatypeValidator::setEnumeration(MemoryManager* const manager)
335{
336    // check 4.3.5.c0 must: enumeration values from the value space of base
337    //
338    // 1. shall be from base value space
339    // 2. shall be from current value space as well ( shall go through boundsCheck() )
340    //
341    if (!fStrEnumeration)
342        return;
343
344    XMLSize_t i = 0;
345    XMLSize_t enumLength = fStrEnumeration->size();
346
347    DecimalDatatypeValidator *numBase = (DecimalDatatypeValidator*) getBaseValidator();
348    if (numBase)
349    {
350        try
351        {
352            for ( i = 0; i < enumLength; i++)
353            {
354                numBase->checkContent(fStrEnumeration->elementAt(i), (ValidationContext*)0, false, manager);
355            }
356        }
357        catch (XMLException&)
358        {
359            ThrowXMLwithMemMgr1(InvalidDatatypeFacetException
360                    , XMLExcepts::FACET_enum_base
361                    , fStrEnumeration->elementAt(i)
362                    , manager);
363        }
364    }
365#if 0
366// spec says that only base has to checkContent
367    // We put the this->checkContent in a separate loop
368    // to not block original message with in that method.
369    //
370    for ( i = 0; i < enumLength; i++)
371    {
372        checkContent(fStrEnumeration->elementAt(i), (ValidationContext*)0, false, manager);
373    }
374#endif
375    fEnumeration = new (manager) RefVectorOf<XMLNumber>(enumLength, true, manager);
376    fEnumerationInherited = false;
377
378    for ( i = 0; i < enumLength; i++)
379    {
380        fEnumeration->insertElementAt(new (manager) XMLBigDecimal(fStrEnumeration->elementAt(i), manager), i);
381    }
382
383}
384
385// -----------------------------------------------------------------------
386// Abstract interface from AbstractNumericValidator
387// -----------------------------------------------------------------------
388void DecimalDatatypeValidator::checkContent(const XMLCh*             const content
389                                           ,      ValidationContext* const context
390                                           ,      bool                     asBase
391                                           ,      MemoryManager*     const manager)
392{
393    //validate against base validator if any
394    DecimalDatatypeValidator *pBase = (DecimalDatatypeValidator*) this->getBaseValidator();
395    if (pBase)
396        pBase->checkContent(content, context, true, manager);
397
398    int thisFacetsDefined = getFacetsDefined();
399
400    // we check pattern first
401    if ( (thisFacetsDefined & DatatypeValidator::FACET_PATTERN ) != 0 )
402    {
403        if (getRegex()->matches(content, manager) ==false)
404        {
405            ThrowXMLwithMemMgr2(InvalidDatatypeValueException
406                    , XMLExcepts::VALUE_NotMatch_Pattern
407                    , content
408                    , getPattern()
409                    , manager);
410        }
411    }
412
413    // if this is a base validator, we only need to check pattern facet
414    // all other facet were inherited by the derived type
415    if (asBase)
416        return;
417
418    XMLBigDecimal  compareDataValue(content, manager);
419    XMLBigDecimal* compareData = &compareDataValue;
420
421    if (getEnumeration())
422    {
423        XMLSize_t i=0;
424        XMLSize_t enumLength = getEnumeration()->size();
425        for ( ; i < enumLength; i++)
426        {
427            if (compareValues(compareData, (XMLBigDecimal*) getEnumeration()->elementAt(i)) ==0 )
428                break;
429        }
430
431        if (i == enumLength)
432            ThrowXMLwithMemMgr1(InvalidDatatypeValueException, XMLExcepts::VALUE_NotIn_Enumeration, content, manager);
433    }
434
435    boundsCheck(compareData, manager);
436
437    if ( (thisFacetsDefined & DatatypeValidator::FACET_FRACTIONDIGITS) != 0 )
438    {
439        if ( compareData->getScale() > fFractionDigits )
440        {
441            XMLCh value1[BUF_LEN+1];
442            XMLCh value2[BUF_LEN+1];
443            XMLString::binToText(compareData->getScale(), value1, BUF_LEN, 10, manager);
444            XMLString::binToText(fFractionDigits, value2, BUF_LEN, 10, manager);
445            ThrowXMLwithMemMgr3(InvalidDatatypeFacetException
446                              , XMLExcepts::VALUE_exceed_fractDigit
447                              , compareData->getRawData()
448                              , value1
449                              , value2
450                              , manager);
451        }
452    }
453
454    if ( (thisFacetsDefined & DatatypeValidator::FACET_TOTALDIGITS) != 0 )
455    {
456        if ( compareData->getTotalDigit() > fTotalDigits )
457        {
458            XMLCh value1[BUF_LEN+1];
459            XMLCh value2[BUF_LEN+1];
460            XMLString::binToText(compareData->getTotalDigit(), value1, BUF_LEN, 10, manager);
461            XMLString::binToText(fTotalDigits, value2, BUF_LEN, 10, manager);
462            ThrowXMLwithMemMgr3(InvalidDatatypeFacetException
463                              , XMLExcepts::VALUE_exceed_totalDigit
464                              , compareData->getRawData()
465                              , value1
466                              , value2
467                              , manager);
468        }
469
470        /***
471         E2-44 totalDigits
472         ... by restricting it to numbers that are expressible as i x 10^-n
473         where i and n are integers such that |i| < 10^totalDigits and 0 <= n <= totalDigits.
474         ***/
475
476        if ( compareData->getScale() > fTotalDigits )
477        {
478            XMLCh value1[BUF_LEN+1];
479            XMLCh value2[BUF_LEN+1];
480            XMLString::binToText(compareData->getScale(), value1, BUF_LEN, 10, manager);
481            XMLString::binToText(fTotalDigits, value2, BUF_LEN, 10, manager);
482            ThrowXMLwithMemMgr3(InvalidDatatypeFacetException
483                              , XMLExcepts::VALUE_exceed_totalDigit
484                              , compareData->getRawData()
485                              , value1
486                              , value2
487                              , manager);
488        }
489    }
490}
491
492/***
493 * 3.2.3 decimal
494 *
495 * . the preceding optional "+" sign is prohibited.
496 * . The decimal point is required.
497 * . Leading and trailing zeroes are prohibited subject to the following:
498 *   there must be at least one digit to the right and to the left of the decimal point which may be a zero.
499 *
500 *
501 *  3.3.13 integer
502 *  3.3.16 long
503 *  3.3.17 int
504 *  3.3.18 short
505 *  3.3.19 byte
506 *  3.3.20 nonNegativeInteger
507 *  3.3.25 positiveInteger
508 *
509 *   . the preceding optional "+" sign is prohibited and
510 *   . leading zeroes are prohibited.
511 *
512 *
513 *  E2-27
514 *  3.3.14 nonPositiveInteger
515 *
516 *   . In the canonical form for zero, the sign must be omitted.
517 *   . leading zeroes are prohibited.
518 *
519 *  3.3.15 negativeInteger
520 *  3.3.21 unsignedLong
521 *  3.3.22 unsignedInt
522 *  3.3.23 unsignedShort
523 *  3.3.24 unsignedByte
524 *
525 *  . leading zeroes are prohibited.
526 *
527 *  Summary:
528 *  . leading zeros are prohibited for all three groups
529 *  . '-' is required for nonPositiveInteger if it is zero
530 *
531 ***/
532
533const XMLCh* DecimalDatatypeValidator::getCanonicalRepresentation(const XMLCh*         const rawData
534                                                                 ,      MemoryManager* const memMgr
535                                                                 ,      bool                 toValidate) const
536{
537    MemoryManager* toUse = memMgr? memMgr : fMemoryManager;
538    DecimalDatatypeValidator* temp = (DecimalDatatypeValidator*) this;
539
540    if (toValidate)
541    {
542        try
543        {
544            temp->checkContent(rawData, 0, false, toUse);
545        }
546        catch (...)
547        {
548            return 0;
549        }
550    }
551
552    // XMLBigInteger::getCanonicalRepresentation and
553    // XMLBigDecimal::getCanonicalRepresentation will handle exceptional cases
554    XMLCanRepGroup::CanRepGroup dvType = DatatypeValidatorFactory::getCanRepGroup(temp);
555
556    if ((dvType == XMLCanRepGroup::Decimal_Derived_signed)   ||
557        (dvType == XMLCanRepGroup::Decimal_Derived_unsigned) ||
558        (dvType == XMLCanRepGroup::Decimal_Derived_npi)        )
559    {
560        return XMLBigInteger::getCanonicalRepresentation(rawData, toUse, dvType == XMLCanRepGroup::Decimal_Derived_npi);
561    }
562    else if (dvType == XMLCanRepGroup::Decimal)
563    {
564        return XMLBigDecimal::getCanonicalRepresentation(rawData, toUse);
565    }
566    else //in case?
567    {
568        return XMLString::replicate(rawData, toUse);
569    }
570
571}
572
573/***
574 * Support for Serialization/De-serialization
575 ***/
576
577IMPL_XSERIALIZABLE_TOCREATE(DecimalDatatypeValidator)
578
579void DecimalDatatypeValidator::serialize(XSerializeEngine& serEng)
580{
581    /***
582     * Note:
583     *
584     *     During storing, we need write the specific number
585     *     type info before calling base::serialize().
586     *
587     *     While loading, we do nothing here
588     ***/
589
590    if (serEng.isStoring())
591    {
592        serEng<<(int) (XMLNumber::BigDecimal);
593    }
594
595    AbstractNumericValidator::serialize(serEng);
596
597    //don't serialize XMLBigDecimal*
598    if (serEng.isStoring())
599    {
600        serEng<<fTotalDigits;
601        serEng<<fFractionDigits;
602    }
603    else
604    {
605        serEng>>fTotalDigits;
606        serEng>>fFractionDigits;
607    }
608
609}
610
611XERCES_CPP_NAMESPACE_END
612
613/**
614  * End of file DecimalDatatypeValidator::cpp
615  */
Note: See TracBrowser for help on using the repository browser.