View Javadoc
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 }