001    /* Duration.java -- 
002       Copyright (C) 2004, 2005, 2006  Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    package javax.xml.datatype;
039    
040    import java.math.BigDecimal;
041    import java.util.Calendar;
042    import java.util.Date;
043    import java.util.GregorianCalendar;
044    import javax.xml.datatype.DatatypeConstants;
045    import javax.xml.namespace.QName;
046    
047    /**
048     * An immutable time space as specified in XML Schema 1.0.
049     *
050     * @author (a href='mailto:dog@gnu.org'>Chris Burdess</a)
051     * @since 1.5
052     */
053    public abstract class Duration
054    {
055    
056      /**
057       * Returns the name of the XML Schema data type this value maps to.
058       */
059      public QName getXMLSchemaType()
060      {
061        int state = 0;
062        state |= isSet(DatatypeConstants.YEARS) ? 32 : 0;
063        state |= isSet(DatatypeConstants.MONTHS) ? 16 : 0;
064        state |= isSet(DatatypeConstants.DAYS) ? 8 : 0;
065        state |= isSet(DatatypeConstants.HOURS) ? 4 : 0;
066        state |= isSet(DatatypeConstants.MINUTES) ? 2 : 0;
067        state |= isSet(DatatypeConstants.SECONDS) ? 1 : 0;
068        switch (state)
069          {
070          case 63:
071            return DatatypeConstants.DURATION;
072          case 15:
073            return DatatypeConstants.DURATION_DAYTIME;
074          case 48:
075            return DatatypeConstants.DURATION_YEARMONTH;
076          default:
077            throw new IllegalStateException();
078          }
079      }
080    
081      /**
082       * Returns the sign of this value.
083       */
084      public abstract int getSign();
085    
086      /**
087       * Returns the years in this duration as an int, or 0 if not present.
088       */
089      public int getYears()
090      {
091        Number val = getField(DatatypeConstants.YEARS);
092        return (val == null) ? 0 : val.intValue();
093      }
094      
095      /**
096       * Returns the months in this duration as an int, or 0 if not present.
097       */
098      public int getMonths()
099      {
100        Number val = getField(DatatypeConstants.MONTHS);
101        return (val == null) ? 0 : val.intValue();
102      }
103      
104      /**
105       * Returns the days in this duration as an int, or 0 if not present.
106       */
107      public int getDays()
108      {
109        Number val = getField(DatatypeConstants.DAYS);
110        return (val == null) ? 0 : val.intValue();
111      }
112      
113      /**
114       * Returns the hours in this duration as an int, or 0 if not present.
115       */
116      public int getHours()
117      {
118        Number val = getField(DatatypeConstants.HOURS);
119        return (val == null) ? 0 : val.intValue();
120      }
121      
122      /**
123       * Returns the minutes in this duration as an int, or 0 if not present.
124       */
125      public int getMinutes()
126      {
127        Number val = getField(DatatypeConstants.MINUTES);
128        return (val == null) ? 0 : val.intValue();
129      }
130      
131      /**
132       * Returns the seconds in this duration as an int, or 0 if not present.
133       */
134      public int getSeconds()
135      {
136        Number val = getField(DatatypeConstants.SECONDS);
137        return (val == null) ? 0 : val.intValue();
138      }
139    
140      /**
141       * Returns the duration length in milliseconds.
142       * Because the length of a month or year may vary depending on the year,
143       * the <code>startInstant</code> parameter is used to specify the duration
144       * offset.
145       */
146      public long getTimeInMillis(Calendar startInstant)
147      {
148        Calendar cal = (Calendar) startInstant.clone();
149        long t1 = cal.getTimeInMillis();
150        addTo(cal);
151        long t2 = cal.getTimeInMillis();
152        return t2 - t1;
153      }
154    
155      /**
156       * Returns the duration length in milliseconds.
157       * Because the length of a month or year may vary depending on the year,
158       * the <code>startInstant</code> parameter is used to specify the duration
159       * offset.
160       */
161      public long getTimeInMillis(Date startInstant)
162      {
163        Date date = (Date) startInstant.clone();
164        long t1 = date.getTime();
165        addTo(date);
166        long t2 = date.getTime();
167        return t2 - t1;
168      }
169    
170      /**
171       * Returns the value of the specified field, or <code>null</code> if the
172       * field is undefined.
173       */
174      public abstract Number getField(DatatypeConstants.Field field);
175    
176      /**
177       * Indicates whether the specified field is set.
178       */
179      public abstract boolean isSet(DatatypeConstants.Field field);
180    
181      /**
182       * Returns the result of adding the specified duration to this duration.
183       */
184      public abstract Duration add(Duration rhs);
185    
186      /**
187       * Adds this duration to the specified calendar.
188       */
189      public abstract void addTo(Calendar calendar);
190      /*{
191        switch (getSign())
192          {
193          case -1:
194            calendar.add(Calendar.YEAR, -getYears());
195            calendar.add(Calendar.MONTH, -getMonths());
196            calendar.add(Calendar.DATE, -getDays());
197            calendar.add(Calendar.HOUR, -getHours());
198            calendar.add(Calendar.MINUTE, -getMinutes());
199            calendar.add(Calendar.SECOND, -getSeconds());
200            break;
201          case 1:
202            calendar.add(Calendar.YEAR, getYears());
203            calendar.add(Calendar.MONTH, getMonths());
204            calendar.add(Calendar.DATE, getDays());
205            calendar.add(Calendar.HOUR, getHours());
206            calendar.add(Calendar.MINUTE, getMinutes());
207            calendar.add(Calendar.SECOND, getSeconds());
208          }
209      }*/
210      
211      /**
212       * Adds this duration to the specified date.
213       */
214      public void addTo(Date date)
215      {
216        Calendar calendar = new GregorianCalendar();
217        calendar.setTimeInMillis(date.getTime());
218        addTo(calendar);
219        date.setTime(calendar.getTimeInMillis());
220      }
221    
222      /**
223       * Returns the result of subtracting the given duration from this
224       * duration.
225       */
226      public Duration subtract(Duration rhs)
227      {
228        // TODO
229        throw new UnsupportedOperationException();
230      }
231    
232      /**
233       * Returns the result of multiplying this duration by the given factor.
234       */
235      public Duration multiply(int factor)
236      {
237        return multiply(BigDecimal.valueOf((long) factor));
238      }
239    
240      /**
241       * Returns the result of multiplying this duration by the given factor.
242       */
243      public abstract Duration multiply(BigDecimal factor);
244    
245      /**
246       * Returns the unary negative of this duration.
247       */
248      public abstract Duration negate();
249      
250      /**
251       * Converts the years and months fields into the days field using a
252       * specific time instant as the reference point.
253       */
254      public abstract Duration normalizeWith(Calendar startTimeInstant);
255    
256      /**
257       * Partial order relation comparison with this duration, in accordance
258       * with XML Schema 1.0 Part 2, Section 3.2.7.6.2.
259       */
260      public abstract int compare(Duration duration);
261    
262      public boolean isLongerThan(Duration duration)
263      {
264        // TODO
265        throw new UnsupportedOperationException();
266      }
267    
268      public boolean isShorterThan(Duration duration)
269      {
270        // TODO
271        throw new UnsupportedOperationException();
272      }
273    
274      public boolean equals(java.lang.Object duration)
275      {
276        // TODO
277        throw new UnsupportedOperationException();
278      }
279      
280      public abstract int hashCode();
281    
282      /**
283       * Returns the lexical representation of this duration.
284       */
285      public String toString()
286      {
287        // TODO
288        throw new UnsupportedOperationException();
289      }
290      
291    }