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: DateTimeValidator.cpp 676911 2008-07-15 13:27:32Z amassari $
20  */
21 
22 // ---------------------------------------------------------------------------
23 //  Includes
24 // ---------------------------------------------------------------------------
25 #include <xercesc/validators/datatype/DateTimeValidator.hpp>
26 #include <xercesc/validators/datatype/InvalidDatatypeFacetException.hpp>
27 #include <xercesc/validators/datatype/InvalidDatatypeValueException.hpp>
28 #include <xercesc/validators/schema/SchemaSymbols.hpp>
29 #include <xercesc/util/OutOfMemoryException.hpp>
30 
31 XERCES_CPP_NAMESPACE_BEGIN
32 
33 // ---------------------------------------------------------------------------
34 //  Macro
35 // ---------------------------------------------------------------------------
36 #define  REPORT_VALUE_ERROR(val1, val2, except_code, manager)    \
37   ThrowXMLwithMemMgr2(InvalidDatatypeValueException               \
38           , except_code                                 \
39           , val1->getRawData()                          \
40           , val2->getRawData()                          \
41           , manager);
42 
43 // ---------------------------------------------------------------------------
44 //  Constructors and Destructor
45 // ---------------------------------------------------------------------------
~DateTimeValidator()46 DateTimeValidator::~DateTimeValidator()
47 {
48 }
49 
DateTimeValidator(DatatypeValidator * const baseValidator,RefHashTableOf<KVStringPair> * const facets,const int finalSet,const ValidatorType type,MemoryManager * const manager)50 DateTimeValidator::DateTimeValidator(
51                           DatatypeValidator*            const baseValidator
52                         , RefHashTableOf<KVStringPair>* const facets
53                         , const int                           finalSet
54                         , const ValidatorType                 type
55                         , MemoryManager* const                manager)
56 :AbstractNumericFacetValidator(baseValidator, facets, finalSet, type, manager)
57 {
58     //do not invoke init() here !!!
59 }
60 
validate(const XMLCh * const content,ValidationContext * const context,MemoryManager * const manager)61 void DateTimeValidator::validate(const XMLCh*             const content
62                                ,       ValidationContext* const context
63                                ,       MemoryManager*     const manager)
64 {
65     checkContent(content, context, false, manager);
66 }
67 
compare(const XMLCh * const value1,const XMLCh * const value2,MemoryManager * const manager)68 int DateTimeValidator::compare(const XMLCh* const value1
69                              , const XMLCh* const value2
70                              , MemoryManager* const manager)
71 {
72     try
73     {
74         XMLDateTime *pDate1 = parse(value1, manager);
75         Janitor<XMLDateTime> jName1(pDate1);
76         XMLDateTime *pDate2 = parse(value2, manager);
77         Janitor<XMLDateTime> jName2(pDate2);
78         int result = compareDates(pDate1, pDate2, true);
79         return (result==INDETERMINATE)? -1 : result;
80     }
81     catch(const OutOfMemoryException&)
82     {
83         throw;
84     }
85     catch (...) // RuntimeException e
86     {
87         return -1; // revisit after implement compareDates()
88     }
89 
90 }
91 
92 
checkContent(const XMLCh * const content,ValidationContext * const context,bool asBase,MemoryManager * const manager)93 void DateTimeValidator::checkContent(const XMLCh*             const content
94                                    ,       ValidationContext* const context
95                                    ,       bool                     asBase
96                                    ,       MemoryManager*     const manager)
97 {
98     //validate against base validator if any
99     DateTimeValidator *pBaseValidator = (DateTimeValidator*) this->getBaseValidator();
100     if (pBaseValidator)
101         pBaseValidator->checkContent(content, context, true, manager);
102 
103     int thisFacetsDefined = getFacetsDefined();
104 
105     // we check pattern first
106     if ( (thisFacetsDefined & DatatypeValidator::FACET_PATTERN ) != 0 )
107     {
108         if (getRegex()->matches(content, manager) ==false)
109         {
110             ThrowXMLwithMemMgr2(InvalidDatatypeValueException
111                     , XMLExcepts::VALUE_NotMatch_Pattern
112                     , content
113                     , getPattern()
114                     , manager);
115         }
116     }
117 
118     // if this is a base validator, we only need to check pattern facet
119     // all other facet were inherited by the derived type
120     if (asBase)
121         return;
122 
123     // the derived classes' parse() method constructs an
124     // XMLDateTime object anc invokes appropriate XMLDateTime's
125     // parser to parse the content.
126     XMLDateTime dateTimeValue(content, manager);
127     XMLDateTime* dateTime = &dateTimeValue;
128 
129     parse(dateTime);
130 
131     // must be < MaxExclusive
132     if ((thisFacetsDefined & DatatypeValidator::FACET_MAXEXCLUSIVE) != 0)
133     {
134         if (compareValues(dateTime, getMaxExclusive()) != XMLDateTime::LESS_THAN)
135         {
136             REPORT_VALUE_ERROR( dateTime
137                               , getMaxExclusive()
138                               , XMLExcepts::VALUE_exceed_maxExcl
139                               , manager)
140         }
141     }
142 
143     // must be <= MaxInclusive
144     if ((thisFacetsDefined & DatatypeValidator::FACET_MAXINCLUSIVE) != 0)
145     {
146         int result = compareValues(dateTime, getMaxInclusive());
147         if ( result == XMLDateTime::GREATER_THAN || result == XMLDateTime::INDETERMINATE )
148         {
149             REPORT_VALUE_ERROR( dateTime
150                               , getMaxInclusive()
151                               , XMLExcepts::VALUE_exceed_maxIncl
152                               , manager)
153         }
154     }
155 
156     // must be >= MinInclusive
157     if ((thisFacetsDefined & DatatypeValidator::FACET_MININCLUSIVE) != 0)
158     {
159         int result = compareValues(dateTime, getMinInclusive());
160         if (result == XMLDateTime::LESS_THAN || result == XMLDateTime::INDETERMINATE)
161         {
162             REPORT_VALUE_ERROR( dateTime
163                               , getMinInclusive()
164                               , XMLExcepts::VALUE_exceed_minIncl
165                               , manager)
166         }
167     }
168 
169     // must be > MinExclusive
170     if ( (thisFacetsDefined & DatatypeValidator::FACET_MINEXCLUSIVE) != 0 )
171     {
172         if (compareValues(dateTime, getMinExclusive()) != XMLDateTime::GREATER_THAN)
173         {
174             REPORT_VALUE_ERROR( dateTime
175                               , getMinExclusive()
176                               , XMLExcepts::VALUE_exceed_minExcl
177                               , manager)
178         }
179     }
180 
181     if ((thisFacetsDefined & DatatypeValidator::FACET_ENUMERATION) != 0 &&
182         (getEnumeration() != 0))
183     {
184         XMLSize_t i=0;
185         XMLSize_t enumLength = getEnumeration()->size();
186         for ( ; i < enumLength; i++)
187         {
188             if (compareValues(dateTime, getEnumeration()->elementAt(i)) == XMLDateTime::EQUAL)
189                 break;
190         }
191 
192         if (i == enumLength)
193             ThrowXMLwithMemMgr1(InvalidDatatypeValueException, XMLExcepts::VALUE_NotIn_Enumeration, content, manager);
194     }
195 }
196 
197 //
198 // Comparision methods
199 //
compareValues(const XMLNumber * const lValue,const XMLNumber * const rValue)200 int DateTimeValidator::compareValues(const XMLNumber* const lValue
201                                    , const XMLNumber* const rValue)
202 {
203     return compareDates((XMLDateTime*) lValue, (XMLDateTime*) rValue, true);
204 }
205 
206 /**
207  * Compare algorithm described in dateDime (3.2.7).
208  * Duration datatype overwrites this method
209  *
210  * @param date1  normalized date representation of the first value
211  * @param date2  normalized date representation of the second value
212  * @param strict
213  * @return less, greater, less_equal, greater_equal, equal
214  */
compareDates(const XMLDateTime * const date1,const XMLDateTime * const date2,bool)215 int DateTimeValidator::compareDates(const XMLDateTime* const date1
216                                   , const XMLDateTime* const date2
217                                   , bool)
218 {
219     return XMLDateTime::compare(date1, date2);
220 }
221 
222 //
223 // In fact, the proper way of the following set*() shall be
224 // {
225 // if (fMaxInclusive)
226 //     delete fMaxInclusive;
227 //
228 //    fMaxInclusive = parse(value);
229 //
230 // }
231 //
232 // But we know this function is invoked once and only once
233 // since there is no duplicated facet passed in, therefore
234 // fMaxInclusive is alwasy zero before, so for the
235 // sake of performance, we do not do the checking/delete.
236 //
237 
setMaxInclusive(const XMLCh * const value)238 void DateTimeValidator::setMaxInclusive(const XMLCh* const value)
239 {
240     fMaxInclusive = parse(value, fMemoryManager);
241 }
242 
setMaxExclusive(const XMLCh * const value)243 void DateTimeValidator::setMaxExclusive(const XMLCh* const value)
244 {
245     fMaxExclusive = parse(value, fMemoryManager);
246 }
247 
setMinInclusive(const XMLCh * const value)248 void DateTimeValidator::setMinInclusive(const XMLCh* const value)
249 {
250     fMinInclusive = parse(value, fMemoryManager);
251 }
252 
setMinExclusive(const XMLCh * const value)253 void DateTimeValidator::setMinExclusive(const XMLCh* const value)
254 {
255     fMinExclusive = parse(value, fMemoryManager);
256 }
257 
setEnumeration(MemoryManager * const)258 void DateTimeValidator::setEnumeration(MemoryManager* const)
259 {
260 // to do: do we need to check against base value space???
261 
262     if (!fStrEnumeration)
263         return;
264 
265     XMLSize_t enumLength = fStrEnumeration->size();
266     fEnumeration = new (fMemoryManager) RefVectorOf<XMLNumber>(enumLength, true, fMemoryManager);
267     fEnumerationInherited = false;
268 
269     for ( XMLSize_t i = 0; i < enumLength; i++)
270         fEnumeration->insertElementAt(parse(fStrEnumeration->elementAt(i), fMemoryManager), i);
271 
272 }
273 
274 /***
275  * Support for Serialization/De-serialization
276  ***/
277 
IMPL_XSERIALIZABLE_NOCREATE(DateTimeValidator)278 IMPL_XSERIALIZABLE_NOCREATE(DateTimeValidator)
279 
280 void DateTimeValidator::serialize(XSerializeEngine& serEng)
281 {
282     /***
283      *
284      * Note: All its derivatives share the same number type, that is
285      *       XMLNumber::DateTime, so this class would write it.
286      ***/
287 
288     if (serEng.isStoring())
289     {
290         serEng<<(int) XMLNumber::DateTime;
291     }
292 
293     AbstractNumericFacetValidator::serialize(serEng);
294 
295     //dateTime can be instantiated during checkContent(), so don't serialize it.
296 }
297 
298 XERCES_CPP_NAMESPACE_END
299 
300 /**
301   * End of file DateTimeValidator::cpp
302   */
303 
304