1 /*
2 * Redistribution and use of this software and associated documentation
3 * ("Software"), with or without modification, are permitted provided
4 * that the following conditions are met:
5 *
6 * 1. Redistributions of source code must retain copyright
7 * statements and notices. Redistributions must also contain a
8 * copy of this document.
9 *
10 * 2. Redistributions in binary form must reproduce the
11 * above copyright notice, this list of conditions and the
12 * following disclaimer in the documentation and/or other
13 * materials provided with the distribution.
14 *
15 * 3. The name "Exolab" must not be used to endorse or promote
16 * products derived from this Software without prior written
17 * permission of Intalio, Inc. For written permission,
18 * please contact info@exolab.org.
19 *
20 * 4. Products derived from this Software may not be called "Exolab"
21 * nor may "Exolab" appear in their names without prior written
22 * permission of Intalio, Inc. Exolab is a registered
23 * trademark of Intalio, Inc.
24 *
25 * 5. Due credit should be given to the Exolab Project
26 * (http://www.exolab.org/).
27 *
28 * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
32 * INTALIO, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39 * OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Copyright 2001-2003 (C) Intalio, Inc. All Rights Reserved.
42 *
43 * $Id$
44 * Date Author Changes
45 * 05/30/2001 Arnaud Blandin Created
46 */
47 package org.exolab.castor.xml.validators;
48
49 import org.exolab.castor.types.DateTime;
50 import org.exolab.castor.types.DateTimeBase;
51
52 import org.exolab.castor.xml.ValidationContext;
53 import org.exolab.castor.xml.ValidationException;
54 import org.exolab.castor.xml.TypeValidator;
55
56 /**
57 * The Date/Time Validation class. This class handles validation for all
58 * XML Schema date & time types.
59 *
60 * @version $Revision$ $Date: $
61 */
62 public class DateTimeValidator extends PatternValidator implements TypeValidator {
63 /** Maximum allowed value (Inclusive) for a valid instance. */
64 private DateTimeBase _maxInclusive;
65 /** Maximum allowed value (Exclusive) for a valid instance. */
66 private DateTimeBase _maxExclusive;
67 /** Minimum allowed value (Inclusive) for a valid instance. */
68 private DateTimeBase _minInclusive;
69 /** Minimum allowed value (Exclusive) for a valid instance. */
70 private DateTimeBase _minExclusive;
71 /** Fixed value. If not null, a valid DateTime instance MUST have this value. */
72 private DateTimeBase _fixed;
73
74 /**
75 * No-arg constructor.
76 */
77 public DateTimeValidator() {
78 super();
79 } //-- DateTimeValidator
80
81 /**
82 * Clears the fixed value for this DateTimeValidator.
83 */
84 public void clearFixed() {
85 _fixed = null;
86 } // -- clearFixed
87
88 /**
89 * Clears the maximum value for this DateTimeValidator.
90 */
91 public void clearMax() {
92 _maxInclusive = null;
93 _maxExclusive = null;
94 } // -- clearMax
95
96 /**
97 * Clears the minimum value for this DateTimeValidator.
98 */
99 public void clearMin() {
100 _minInclusive = null;
101 _minExclusive = null;
102 } // -- clearMin
103
104 /**
105 * Returns the configured fixed value for date/time validation. Returns
106 * null if no fixed value has been configured.
107 *
108 * @return the fixed value to validate against.
109 */
110 public DateTimeBase getFixed() {
111 return _fixed;
112 } // -- getFixed
113
114 /**
115 * Returns the configured inclusive maximum value for date/time validation.
116 * Returns null if no inclusive maximum has been configured.
117 *
118 * @return the maximum (inclusive) value to validate against.
119 */
120 public DateTimeBase getMaxInclusive() {
121 return _maxInclusive;
122 } // -- getMaxInclusive
123
124 /**
125 * Returns the configured exclusive maximum value for date/time validation.
126 * Returns null if no exclusive maximum has been configured.
127 *
128 * @return the maximum (exclusive) value to validate against.
129 */
130 public DateTimeBase getMaxExclusive() {
131 return _maxExclusive;
132 } // -- getMaxInclusive
133
134 /**
135 * Returns the configured inclusive minimum value for date/time validation.
136 * Returns null if no inclusive minimum has been configured.
137 *
138 * @return the minimum inclusive value to validate against.
139 */
140 public DateTimeBase getMinInclusive() {
141 return _minInclusive;
142 } // -- getMinInclusive
143
144 /**
145 * Returns the configured exclusive minimum value for date/time validation.
146 * Returns null if no exclusive minimum has been configured.
147 *
148 * @return the minimum exclusive value to validate against.
149 */
150 public DateTimeBase getMinExclusive() {
151 return _minExclusive;
152 } // -- getMinInclusive
153
154 /**
155 * Returns true if a fixed value to validate against has been set.
156 *
157 * @return true if a fixed value has been set.
158 */
159 public boolean hasFixed() {
160 return _fixed != null;
161 } // -- hasFixed
162
163 /**
164 * Sets the fixed value for date/time validation.
165 * <p>
166 * NOTE: If maximum and/or minimum values have been set and the fixed value
167 * is not within that max/min range, then no date/time will pass validation.
168 * This is as according to the XML Schema spec.
169 *
170 * @param fixedValue
171 * the fixed value that a date/time validated with this validator
172 * must be equal to.
173 */
174 public void setFixed(final DateTimeBase fixedValue) {
175 _fixed = fixedValue;
176 }
177
178 /**
179 * Sets the minimum (exclusive) value for date/time validation. To pass
180 * validation, a date/time must be greater than this value.
181 *
182 * @param minValue
183 * the minimum (exclusive) value for date/time validation.
184 */
185 public void setMinExclusive(final DateTimeBase minValue) {
186 _minExclusive = minValue;
187 _minInclusive = null;
188 } //-- setMinExclusive
189
190 /**
191 * Sets the minimum (inclusive) value for date/time validation. To pass
192 * validation, a date/time must be greater than or equal to this value.
193 *
194 * @param minValue
195 * the minimum (inclusive) value for date/time validation.
196 */
197 public void setMinInclusive(final DateTimeBase minValue) {
198 _minExclusive = null;
199 _minInclusive = minValue;
200 } //-- setMinInclusive
201
202 /**
203 * Sets the maximum (exclusive) value for date/time validation. To pass
204 * validation, a date/time must be less than this value.
205 *
206 * @param maxValue
207 * the maximum (exclusive) value for date/time validation.
208 */
209 public void setMaxExclusive(final DateTimeBase maxValue) {
210 _maxExclusive = maxValue;
211 _maxInclusive = null;
212 } //-- setMaxExclusive
213
214 /**
215 * Sets the maximum (inclusive) value for date/time validation. To pass
216 * validation, a date/time must be less than or equal to this value.
217 *
218 * @param maxValue
219 * the maximum (inclusive) value for date/time validation.
220 */
221 public void setMaxInclusive(final DateTimeBase maxValue) {
222 _maxExclusive = null;
223 _maxInclusive = maxValue;
224 } //-- setMaxInclusive
225
226 /**
227 * Validates a Date/Time instance.
228 * @param dateTime the date/time type to validate
229 * @throws ValidationException if the DateTime fails validation
230 */
231 public void validate(final DateTimeBase dateTime) throws ValidationException {
232 validate(dateTime, (ValidationContext) null);
233 }
234
235 /**
236 * Validates a Date/Time instance.
237 * @param dateTime the date/time type to validate
238 * @param context the ValidationContext
239 * @throws ValidationException if the DateTime fails validation
240 */
241 public void validate(final DateTimeBase dateTime, final ValidationContext context)
242 throws ValidationException {
243 boolean isThereMinInclusive = (_minInclusive != null);
244 boolean isThereMinExclusive = (_minExclusive != null);
245 boolean isThereMaxInclusive = (_maxInclusive != null);
246 boolean isThereMaxExclusive = (_maxExclusive != null);
247
248 if (isThereMinExclusive && isThereMinInclusive) {
249 throw new ValidationException("Both minInclusive and minExclusive are defined");
250 }
251
252 if (isThereMaxExclusive && isThereMaxInclusive) {
253 throw new ValidationException("Both maxInclusive and maxExclusive are defined");
254 }
255
256 if (_fixed != null) {
257 int comparison = dateTime.compareTo(_fixed);
258 if (comparison == DateTimeBase.INDETERMINATE) {
259 String err = dateTime.getClass().getName() + " " + dateTime
260 + " comparison to the fixed value " + _fixed
261 + " is indeterminate";
262 throw new ValidationException(err);
263 } else if (comparison != DateTimeBase.EQUALS) {
264 String err = dateTime.getClass().getName() + " " + dateTime
265 + " is not equal to the fixed value: " + _fixed;
266 throw new ValidationException(err);
267 }
268 }
269
270 if (isThereMinInclusive && dateTime.compareTo(_minInclusive) != DateTimeBase.GREATER_THAN
271 && !dateTime.equals(_minInclusive)) {
272 String err = dateTime.getClass().getName() + " " + dateTime
273 + " is less than the minimum allowed value: " + _minInclusive;
274 throw new ValidationException(err);
275 }
276
277 if (isThereMinExclusive && dateTime.compareTo(_minExclusive) != DateTimeBase.GREATER_THAN) {
278 String err = dateTime.getClass().getName() + " " + dateTime
279 + " is less than or equal to the minimum (exclusive) value: " + _minExclusive;
280 throw new ValidationException(err);
281 }
282
283 if (isThereMaxInclusive && dateTime.compareTo(_maxInclusive) != DateTimeBase.LESS_THAN
284 && !dateTime.equals(_maxInclusive)) {
285 String err = dateTime.getClass().getName() + " " + dateTime
286 + " is greater than the maximum allowed value: " + _maxInclusive;
287 throw new ValidationException(err);
288 }
289
290 if (isThereMaxExclusive && dateTime.compareTo(_maxExclusive) != DateTimeBase.LESS_THAN) {
291 String err = dateTime.getClass().getName() + " " + dateTime
292 + " is greater than or equal to the maximum (exclusive) value: "
293 + _maxExclusive;
294 throw new ValidationException(err);
295 }
296
297 if (hasPattern()) {
298 super.validate(dateTime.toString(), context);
299 }
300 } //-- validate
301
302 /**
303 * Validates the given Object.
304 *
305 * @param object the Object to validate
306 * @throws ValidationException if the object fails validation
307 */
308 public void validate(final Object object) throws ValidationException {
309 validate(object, (ValidationContext) null);
310 } //-- validate
311
312 /**
313 * Validates the given Object.
314 *
315 * @param object the Object to validate
316 * @param context the ValidationContext
317 * @throws ValidationException if the object fails validation
318 */
319 public void validate(final Object object, final ValidationContext context)
320 throws ValidationException {
321 if (object == null) {
322 String err = "DateTimeValidator cannot validate a null object.";
323 throw new ValidationException(err);
324 }
325
326 if (object instanceof String) {
327 try {
328 DateTime dateTime = new DateTime((String) object);
329 validate(dateTime, context);
330 return;
331 } catch (java.text.ParseException pe) {
332 String err = "String provided fails to parse into a DateTime: " + (String) object;
333 throw new ValidationException(err, pe);
334 }
335 }
336
337 DateTimeBase value = null;
338
339 try {
340 value = (DateTimeBase) object;
341 } catch (Exception ex) {
342 String err = ex.toString() + "\nExpecting a DateTime, received instead: "
343 + object.getClass().getName();
344 throw new ValidationException(err);
345 }
346
347 validate(value, context);
348 } //-- validate
349
350 }