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$
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