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