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 2000 (C) Intalio, Inc. All Rights Reserved.
32   *
33   * $Id$ Date Author Changes 12/05/2000 Arnaud Blandin Added the support for
34   * NotSupportedOperationException 11/07/2000 Arnaud Blandin Added a new constructor and setValues
35   * method 11/02/2000 Arnaud Blandin Changed the constructor 26/10/2000 Arnaud Blandin Created
36   */
37  package org.exolab.castor.types;
38  
39  import org.exolab.castor.types.TimeDuration;
40  import org.exolab.castor.xml.ValidationException;
41  
42  import java.text.ParseException;
43  
44  import javax.naming.OperationNotSupportedException;
45  
46  /**
47   * The base class for recurring Duration types.
48   * <p>
49   * This base class contains all the time fields (including the time zone ones) and also the facets
50   * period and duration
51   * <p>
52   * The validation of the time fields is done in the set methods and follows
53   * <a href="http://www.iso.ch/markete/8601.pdf">the ISO8601 Date and Time Format</a>
54   *
55   * @author <a href="mailto:blandin@intalio.com">Arnaud Blandin</a>
56   * @see RecurringDuration
57   * @see Time
58   * @see TimeInstant
59   * @see TimePeriod
60   * @deprecated since Castor 1.0.6 since type derived from this base class are not in any
61   *             recommendation.
62   */
63  public abstract class RecurringDurationBase implements java.io.Serializable {
64  
65    /** the period facet of this recurringDuration. */
66    private TimeDuration _period = null;
67    /** the duration facet of this recurringDuration. */
68    private TimeDuration _duration = null;
69    /**
70     * the hour field of this recurringDuration. -1 means that the field has been omitted (cf section
71     * 4.5 of ISO 8601)
72     */
73    private short _hour = 0;
74    /**
75     * the minute field of this recurringDuration. -1 means that the field has been omitted (cf
76     * section 4.5 of ISO 8601)
77     */
78    private short _minute = 0;
79    /**
80     * the second field of this recurringDuration. -1 means that the field has been omitted (cf
81     * section 4.5 of ISO 8601)
82     */
83    private short _second = 0;
84    /** the millsecond field of this recurringDuration. */
85    private short _millsecond = 0;
86    /** the time zone hour field of this recurringDuration. */
87    private short _zoneHour = 0;
88    /** the time zone minute field of this recurringDuration. */
89    private short _zoneMinute = 0;
90    /** true if this recurringDuration is UTC related. */
91    private boolean _utc = false;
92    /** true if the time zone is negative. */
93    private boolean _zoneNegative = false;
94    /** true if the recurring duration is negative. */
95    private boolean _isNegative = false;
96  
97    /**
98     * No-arg constructor.
99     */
100   protected RecurringDurationBase() {
101     // Nothing to do
102   }
103 
104   /**
105    * Returns a recurringDurationBase with the facets duration and period set.
106    *
107    * @param duration the TimeDuration representing the duration facet
108    * @param period the TimeDuration reprensenting the period facet
109    */
110   protected RecurringDurationBase(TimeDuration duration, TimeDuration period) {
111     try {
112       this.setDuration(duration);
113       this.setPeriodInternal(period);
114     } catch (UnsupportedOperationException e) {
115       String err = "Recurring Duration: " + e;
116       throw new IllegalArgumentException(err);
117     }
118   }
119 
120   /**
121    * returns a recurringDurationBase with the facets duration and period set up
122    *
123    * @param duration the String representing the duration facet
124    * @param period the String reprensenting the period facet
125    * @throws IllegalArgumentException this exception is thrown when the parameter strings are not
126    *         corresponding to valid TimeDuration
127    */
128   protected RecurringDurationBase(String duration, String period) throws IllegalArgumentException {
129     try {
130       this.setDuration(TimeDuration.parseTimeDuration(duration));
131       this.setPeriodInternal(TimeDuration.parseTimeDuration(period));
132     } catch (Exception e) {
133       String err = "In RecurringDurationBase: " + e;
134       throw new IllegalArgumentException(err);
135     }
136   }
137 
138   /**
139    * returns a recurringDurationBase with the facets duration and period set up but also the fields
140    *
141    * @param duration the String representing the duration facet
142    * @param period the String reprensenting the period facet
143    * @param values an array of shorts which contains the values of the fields
144    * @throws IllegalArgumentException this exception is thrown when the values array is not of
145    *         length 6.
146    * @see #setValues
147    */
148   protected RecurringDurationBase(String duration, String period, short[] values)
149       throws OperationNotSupportedException {
150     new RecurringDuration(duration, period);
151     if (values.length != 6) {
152       throw new IllegalArgumentException("Wrong numbers of values");
153     }
154     this.setValues(values);
155   }
156 
157   /**
158    * set the period facet this recurringDuration this method is used to avoid calling the setPeriod
159    * method of subclasses
160    *
161    * @param period the period to set
162    */
163   private void setPeriodInternal(TimeDuration period) {
164     _period = period;
165   }
166 
167   /**
168    * set the period facet for this recurringDuration
169    *
170    * @param period the period to set
171    * @throws OperationNotSupportedException this exception is thrown when changing the value of the
172    *         period facet is not allowed
173    */
174   public void setPeriod(TimeDuration period) throws UnsupportedOperationException {
175     setPeriodInternal(period);
176   }
177 
178   /**
179    * set the period facet for this recurringDuration
180    *
181    * @param period the period to set
182    * @throws UnsupportedOperationException this exception is thrown when changing the value of the
183    *         period facet is not allowed
184    */
185   public void setPeriod(String period) throws UnsupportedOperationException {
186     try {
187       setPeriodInternal(TimeDuration.parseTimeDuration(period));
188     } catch (ParseException e) {
189       String err = "RecurringDuration, setPeriod: " + e;
190       throw new IllegalArgumentException(err);
191     }
192   }
193 
194   /**
195    * set the duration facet for this recurringDuration
196    *
197    * @param duration the period to set
198    * @throws UnsupportedOperationException this exception is thrown when changing the value of the
199    *         duration facet is not allowed
200    */
201   public void setDuration(TimeDuration duration) throws UnsupportedOperationException {
202     _duration = duration;
203   }
204 
205   /**
206    * set the duration facet for this recurringDuration
207    *
208    * @param duration the period to set
209    * @throws UnsupportedOperationException this exception is thrown when changing the value of the
210    *         duration facet is not allowed
211    */
212   public void setDuration(String duration) throws UnsupportedOperationException {
213     try {
214       _duration = TimeDuration.parseTimeDuration(duration);
215     } catch (ParseException e) {
216       String err = "RecurringDuration, setDuration: " + e;
217       throw new IllegalArgumentException(err);
218     }
219   }
220 
221   /**
222    * set the hour field for this recurringDuration
223    *
224    * @param hour the hour to set
225    * @throws UnsupportedOperationException this exception is thrown when changing the value of the
226    *         hour field is not allowed
227    */
228   public void setHour(short hour) throws UnsupportedOperationException {
229     String err = "";
230     if (hour > 23) {
231       err = "the hour field (" + hour + ")must be strictly lower than 24";
232       throw new IllegalArgumentException(err);
233     }
234     _hour = hour;
235   }
236 
237   /**
238    * set the minute field for this recurringDuration
239    *
240    * @param minute the minute to set
241    * @throws UnsupportedOperationException this exception is thrown when changing the value of the
242    *         minute field is not allowed
243    */
244   public void setMinute(short minute) throws UnsupportedOperationException {
245     String err = "";
246     if (minute == -1 && _hour != -1) {
247       err = "minute cannot be omitted if the previous field is not omitted.";
248       throw new IllegalArgumentException(err);
249     } else if (minute > 59) {
250       err = "the minute field (" + minute + ") must be lower than 59";
251       throw new IllegalArgumentException(err);
252     }
253     _minute = minute;
254   }
255 
256   /**
257    * set the second field for this recurringDuration
258    *
259    * @param second the second to set
260    * @param millsecond the millisecond to set
261    * @throws UnsupportedOperationException this exception is thrown when changing the value of the
262    *         second field is not allowed
263    */
264   public void setSecond(short second, short millsecond) throws UnsupportedOperationException {
265     String err = "";
266     if ((second == -1) && (_minute != -1)) {
267       err = "second cannot be omitted if the previous field is not omitted.";
268       throw new IllegalArgumentException(err);
269     } else if (second > 60) {
270       err = "the second field (" + second + ")must be lower than 60";
271       throw new IllegalArgumentException(err);
272     }
273     _second = second;
274     _millsecond = millsecond;
275   }
276 
277   /**
278    * set the time zone fields for this recurringDuration
279    *
280    * @param hour the time zone hour to set
281    * @param minute the time zone minute to set
282    * @throws UnsupportedOperationException this exception is thrown when changing the value of the
283    *         time zone fields is not allowed
284    */
285   public void setZone(short hour, short minute) throws UnsupportedOperationException {
286     String err = "";
287     if (hour > 23) {
288       err = "the zone hour field (" + hour + ")must be strictly lower than 24";
289       throw new IllegalArgumentException(err);
290     }
291     _zoneHour = hour;
292 
293     if (minute > 59) {
294       err = "the minute field (" + minute + ")must be lower than 59";
295       throw new IllegalArgumentException(err);
296     }
297     _zoneMinute = minute;
298   }
299 
300   /**
301    * set all the fields by reading the values in an array
302    *
303    * @param values an array of shorts with the values the array is supposed to be of length 6 and
304    *        ordered like that:
305    *        <ul>
306    *        <li>hour</li>
307    *        <li>minute</li>
308    *        <li>second</li>
309    *        <li>millisecond</li>
310    *        <li>zoneHour</li>
311    *        <li>zoneMinute</li>
312    *        </ul>
313    * @throws UnsupportedOperationException this exception is thrown when changing the value of a
314    *         time related field is not allowed
315    */
316   public void setValues(short[] values) throws UnsupportedOperationException {
317     this.setHour(values[0]);
318     this.setMinute(values[1]);
319     this.setSecond(values[2], values[3]);
320     this.setZone(values[4], values[5]);
321   }
322 
323   /**
324    * set the negative field to true
325    */
326   public void setNegative() {
327     _isNegative = true;
328   }
329 
330   /**
331    * set the time zone negative field to true
332    *
333    * @throws UnsupportedOperationException this exception is thrown when changing the time zone
334    *         fields is not allowed
335    */
336   public void setZoneNegative() throws UnsupportedOperationException {
337     _zoneNegative = true;
338   }
339 
340   /**
341    * set the UTC field to true
342    */
343   public void setUTC() {
344     _utc = true;
345   }
346 
347   // Get methods
348   public TimeDuration getPeriod() {
349     return _period;
350   }
351 
352   public TimeDuration getDuration() {
353     return _duration;
354   }
355 
356   public short getHour() {
357     return _hour;
358   }
359 
360   public short getMinute() {
361     return _minute;
362   }
363 
364   public short getSeconds() {
365     return _second;
366   }
367 
368   public short getMilli() {
369     return _millsecond;
370   }
371 
372   public short getZoneHour() {
373     return _zoneHour;
374   }
375 
376   public short getZoneMinute() {
377     return _zoneMinute;
378   }
379 
380   /**
381    * returns an array of short with all the fields which describe a RecurringDurationBase
382    *
383    * @return an array of short with all the fields which describe a RecurringDurationBase
384    */
385   public short[] getValues() {
386     short[] result = new short[6];
387     result[0] = this.getHour();
388     result[1] = this.getMinute();
389     result[2] = this.getSeconds();
390     result[3] = this.getMilli();
391     result[4] = this.getZoneHour();
392     result[5] = this.getZoneMinute();
393     return result;
394   } // getValues
395 
396   /**
397    * return true if this recurring Duration type is UTC i.e if there is no time zone.
398    *
399    * @return true if this recurringDuration type is UTC else false.
400    */
401   public boolean isUTC() {
402     _utc = _zoneHour == 0 && _zoneMinute == 0;
403     return _utc;
404   }
405 
406   public boolean isNegative() {
407     return _isNegative;
408   }
409 
410   public boolean isZoneNegative() {
411     return _zoneNegative;
412   }
413 
414   /**
415    * {@inheritDoc} Override the java.lang.equals method
416    * 
417    * @see #equal
418    */
419   public boolean equals(Object object) {
420     if (object instanceof RecurringDurationBase) {
421       try {
422         return equal((RecurringDurationBase) object);
423       } catch (ValidationException e) {
424         e.printStackTrace();
425         return false;
426       }
427     }
428     return false;
429   }
430 
431   /**
432    * Returns true if the present instance of Recurring Duration Base is equal to the parameter.
433    * <p>
434    * The equals relation is the following :
435    * <tt>rd1 equals rd2 iff each field of rd1 is equal to the corresponding field of rd2 </tt>
436    *
437    * @param reccD the recurring duration to compare with the present instance
438    * @return true if the present instance is equal to the parameter false if not
439    */
440   public boolean equal(RecurringDurationBase reccD) throws ValidationException {
441     boolean result = false;
442     if (!(this.getPeriod().equals(reccD.getPeriod()))
443         || !(this.getDuration().equals(reccD.getDuration()))) {
444       String err = "Recurring Duration which have different values "
445           + "for the duration and period can not be compared";
446       throw new ValidationException(err);
447     }
448 
449     result = (this.getHour() == reccD.getHour());
450     result = result && (this.getMinute() == reccD.getMinute());
451     result = result && (this.getSeconds() == reccD.getSeconds());
452     result = result && (this.getMilli() == reccD.getMilli());
453     result = result && (this.isNegative() == this.isNegative());
454     if (!reccD.isUTC()) {
455       result = result && (!this.isUTC());
456       result = result && (this.getZoneHour() == reccD.getZoneHour());
457       result = result && (this.getZoneMinute() == reccD.getZoneMinute());
458     }
459     return result;
460   }// equals
461 
462   /**
463    * Returns true if the present instance of RecurringDurationBase is greater than the parameter
464    * <p>
465    * Note : the order relation follows the W3C XML Schema draft i.e <tt>rd1 < rd2 iff rd2-rd1>0</tt>
466    *
467    * @param reccD the recurring duration base to compare with the present instance
468    * @return true if the present instance is the greatest, false if not
469    */
470   public boolean isGreater(RecurringDurationBase reccD) throws ValidationException {
471     if (!(this.getPeriod().equals(reccD.getPeriod()))
472         || !(this.getDuration().equals(reccD.getDuration()))) {
473       String err = "Recurring Duration which have different values "
474           + "for the duration and period can not be compared";
475       throw new ValidationException(err);
476     }
477 
478     boolean result = false;
479     short[] val_this = this.getValues();
480     short[] val_reccD = reccD.getValues();
481     for (int i = 0; result != true || i < val_this.length; i++) {
482       result = val_this[i] > val_reccD[i];
483       if (val_this[i] < val_reccD[i]) {
484         return false;
485       }
486     }
487     return result;
488   } // isGreater
489 
490 }// -- RecurringDurationBase