KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xerces > jaxp > datatype > XMLGregorianCalendarImpl


1 /*
2  * Copyright 2005 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.xerces.jaxp.datatype;
18
19 import java.io.Serializable JavaDoc;
20 import java.math.BigDecimal JavaDoc;
21 import java.math.BigInteger JavaDoc;
22 import java.util.Calendar JavaDoc;
23 import java.util.Date JavaDoc;
24 import java.util.GregorianCalendar JavaDoc;
25 import java.util.Locale JavaDoc;
26 import java.util.TimeZone JavaDoc;
27
28 import javax.xml.datatype.DatatypeConstants JavaDoc;
29 import javax.xml.datatype.Duration JavaDoc;
30 import javax.xml.datatype.XMLGregorianCalendar JavaDoc;
31 import javax.xml.namespace.QName JavaDoc;
32
33 import org.apache.xerces.util.DatatypeMessageFormatter;
34
35 /**
36  * <p>Representation for W3C XML Schema 1.0 date/time datatypes.
37  * Specifically, these date/time datatypes are
38  * {@link DatatypeConstants#DATETIME dateTime},
39  * {@link DatatypeConstants#TIME time},
40  * {@link DatatypeConstants#DATE date},
41  * {@link DatatypeConstants#GYEARMONTH gYearMonth},
42  * {@link DatatypeConstants#GMONTHDAY gMonthDay},
43  * {@link DatatypeConstants#GYEAR gYear},
44  * {@link DatatypeConstants#GMONTH gMonth} and
45  * {@link DatatypeConstants#GDAY gDay}
46  * defined in the XML Namespace
47  * <code>"http://www.w3.org/2001/XMLSchema"</code>.
48  * These datatypes are normatively defined in
49  * <a HREF="http://www.w3.org/TR/xmlschema-2/#dateTime">W3C XML Schema 1.0 Part 2, Section 3.2.7-14</a>.</p>
50  *
51  * <p>The table below defines the mapping between XML Schema 1.0
52  * date/time datatype fields and this class' fields. It also summarizes
53  * the value constraints for the date and time fields defined in
54  * <a HREF="http://www.w3.org/TR/xmlschema-2/#isoformats">W3C XML Schema 1.0 Part 2, Appendix D,
55  * <i>ISO 8601 Date and Time Formats</i></a>.</p>
56  *
57  * <a name="datetimefieldsmapping"/>
58  * <table border="2" rules="all" cellpadding="2">
59  * <thead>
60  * <tr>
61  * <th align="center" colspan="3">
62  * Date/time datatype field mapping between XML Schema 1.0 and Java representation
63  * </th>
64  * </tr>
65  * </thead>
66  * <tbody>
67  * <tr>
68  * <th>XML Schema 1.0<br/>
69  * datatype<br/>
70  * field</th>
71  * <th>Related<br/>XMLGregorianCalendar<br/>Accessor(s)</th>
72  * <th>Value Range</th>
73  * </tr>
74  * <a name="datetimefield-year"/>
75  * <tr>
76  * <td> year </td>
77  * <td> {@link #getYear()} + {@link #getEon()} or<br/>
78  * {@link #getEonAndYear}
79  * </td>
80  * <td> <code>getYear()</code> is a value between -(10^9-1) to (10^9)-1
81  * or {@link DatatypeConstants#FIELD_UNDEFINED}.<br/>
82  * {@link #getEon()} is high order year value in billion of years.<br/>
83  * <code>getEon()</code> has values greater than or equal to (10^9) or less than or equal to -(10^9).
84  * A value of null indicates field is undefined.</br>
85  * Given that <a HREF="http://www.w3.org/2001/05/xmlschema-errata#e2-63">XML Schema 1.0 errata</a> states that the year zero
86  * will be a valid lexical value in a future version of XML Schema,
87  * this class allows the year field to be set to zero. Otherwise,
88  * the year field value is handled exactly as described
89  * in the errata and [ISO-8601-1988]. Note that W3C XML Schema 1.0
90  * validation does not allow for the year field to have a value of zero.
91  * </td>
92  * </tr>
93  * <a name="datetimefield-month"/>
94  * <tr>
95  * <td> month </td>
96  * <td> {@link #getMonth()} </td>
97  * <td> 1 to 12 or {@link DatatypeConstants#FIELD_UNDEFINED} </td>
98  * </tr>
99  * <a name="datetimefield-day"/>
100  * <tr>
101  * <td> day </td>
102  * <td> {@link #getDay()} </td>
103  * <td> Independent of month, max range is 1 to 31 or {@link DatatypeConstants#FIELD_UNDEFINED}.<br/>
104  * The normative value constraint stated relative to month
105  * field's value is in <a HREF="http://www.w3.org/TR/xmlschema-2/#isoformats">W3C XML Schema 1.0 Part 2, Appendix D</a>.
106  * </td>
107  * </tr>
108  * <a name="datetimefield-hour"/>
109  * <tr>
110  * <td> hour </td>
111  * <td> {@link #getHour()} </td>
112  * <td>
113  * 0 to 24 or {@link DatatypeConstants#FIELD_UNDEFINED}
114  * <a HREF="http://www.w3.org/2001/05/xmlschema-errata#e2-45">For a value of 24, the minute and second field must be zero.</a>
115  * </td>
116  * </tr>
117  * <a name="datetimefield-minute"/>
118  * <tr>
119  * <td> minute </td>
120  * <td> {@link #getMinute()} </td>
121  * <td> 0 to 59 or {@link DatatypeConstants#FIELD_UNDEFINED} </td>
122  * </tr>
123  * <a name="datetimefield-second"/>
124  * <tr>
125  * <td>second</td>
126  * <td>
127  * {@link #getSecond()} + {@link #getMillisecond()}/1000 or<br/>
128  * {@link #getSecond()} + {@link #getFractionalSecond()}
129  * </td>
130  * <td>
131  * {@link #getSecond()} from 0 to 60 or {@link DatatypeConstants#FIELD_UNDEFINED}.<br/>
132  * <i>(Note: 60 only allowable for leap second.)</i><br/>
133  * {@link #getFractionalSecond()} allows for infinite precision over the range from 0.0 to 1.0 when
134  * the {@link #getSecond()} is defined.<br/>
135  * <code>FractionalSecond</code> is optional and has a value of <code>null</code> when it is undefined.<br />
136  * {@link #getMillisecond()} is the convenience
137  * millisecond precision of value of {@link #getFractionalSecond()}.
138  * </td>
139  * </tr>
140  * <tr id="datetimefield-timezone">
141  * <td> timezone </td>
142  * <td> {@link #getTimezone()} </td>
143  * <td> Number of minutes or {@link DatatypeConstants#FIELD_UNDEFINED}.
144  * Value range from -14 hours (-14 * 60 minutes) to 14 hours (14 * 60 minutes).
145  * </td>
146  * </tr>
147  * </tbody>
148  * </table>
149  *
150  * <p>All maximum value space constraints listed for the fields in the table
151  * above are checked by factory methods, setter methods and parse methods of
152  * this class. <code>IllegalArgumentException</code> is thrown when
153  * parameter's value is outside the maximum value constraint for the field.
154  * Validation checks, for example, whether days in month should be
155  * limited to 29, 30 or 31 days, that are dependent on the values of other
156  * fields are not checked by these methods.
157  * </p>
158  *
159  * <p>The following operations are defined for this class:
160  * <ul>
161  * <li>factory methods to create instances</li>
162  * <li>accessors/mutators for independent date/time fields</li>
163  * <li>conversion between this class and W3C XML Schema 1.0 lexical representation</li>
164  * <li>conversion between this class and <code>java.util.GregorianCalendar</code></li>
165  * <li>partial order relation comparator method, {@link #compare(XMLGregorianCalendar)}</li>
166  * <li>{@link #equals(Object)} defined relative to {@link #compare(XMLGregorianCalendar)}.</li>
167  * <li> addition operation with {@link javax.xml.datatype.Duration}.
168  * instance as defined in <a HREF="http://www.w3.org/TR/xmlschema-2/#adding-durations-to-dateTimes">
169  * W3C XML Schema 1.0 Part 2, Appendix E, <i>Adding durations to dateTimes</i></a>.</li>
170  * </ul>
171  * </p>
172  *
173  * @author <a HREF="mailto:Kohsuke.Kawaguchi@Sun.com">Kohsuke Kawaguchi</a>
174  * @author <a HREF="mailto:Joseph.Fialli@Sun.com">Joseph Fialli</a>
175  * @version $Id: XMLGregorianCalendarImpl.java,v 1.4 2005/05/17 20:59:48 mrglavas Exp $
176  * @see javax.xml.datatype.Duration
177  */

178
179 class XMLGregorianCalendarImpl
180     extends XMLGregorianCalendar JavaDoc
181     implements Serializable JavaDoc, Cloneable JavaDoc {
182
183     /** Backup values **/
184     private BigInteger JavaDoc orig_eon;
185     private int orig_year = DatatypeConstants.FIELD_UNDEFINED;
186     private int orig_month = DatatypeConstants.FIELD_UNDEFINED;
187     private int orig_day = DatatypeConstants.FIELD_UNDEFINED;
188     private int orig_hour = DatatypeConstants.FIELD_UNDEFINED;
189     private int orig_minute = DatatypeConstants.FIELD_UNDEFINED;
190     private int orig_second = DatatypeConstants.FIELD_UNDEFINED;
191     private BigDecimal JavaDoc orig_fracSeconds;
192     private int orig_timezone = DatatypeConstants.FIELD_UNDEFINED;
193     
194     /**
195      * <p>Eon of this <code>XMLGregorianCalendar</code>.</p>
196      */

197     private BigInteger JavaDoc eon = null;
198     
199     /**
200      * <p>Year of this <code>XMLGregorianCalendar</code>.</p>
201      */

202     private int year = DatatypeConstants.FIELD_UNDEFINED;
203
204     /**
205      * <p>Month of this <code>XMLGregorianCalendar</code>.</p>
206      */

207     private int month = DatatypeConstants.FIELD_UNDEFINED;
208     
209     /**
210      * <p>Day of this <code>XMLGregorianCalendar</code>.</p>
211      */

212     private int day = DatatypeConstants.FIELD_UNDEFINED;
213     
214     /**
215      * <p>Timezone of this <code>XMLGregorianCalendar</code> in minutes.</p>
216      */

217     private int timezone = DatatypeConstants.FIELD_UNDEFINED;
218     
219     /**
220      * <p>Hour of this <code>XMLGregorianCalendar</code>.</p>
221      */

222     private int hour = DatatypeConstants.FIELD_UNDEFINED;
223     
224     /**
225      * <p>Minute of this <code>XMLGregorianCalendar</code>.</p>
226      */

227     private int minute = DatatypeConstants.FIELD_UNDEFINED;
228     
229     /**
230      * <p>Second of this <code>XMLGregorianCalendar</code>.</p>
231      */

232     private int second = DatatypeConstants.FIELD_UNDEFINED ;
233     
234     /**
235      * <p>Fractional second of this <code>XMLGregorianCalendar</code>.</p>
236      */

237     private BigDecimal JavaDoc fractionalSecond = null;
238
239     /**
240      * <p>Constant to represent a billion.</p>
241      */

242     private static final BigInteger JavaDoc BILLION = new BigInteger JavaDoc("1000000000");
243
244     /**
245      * <p>Obtain a pure Gregorian Calendar by calling
246      * GregorianCalendar.setChange(PURE_GREGORIAN_CHANGE). </p>
247      */

248     private static final Date JavaDoc PURE_GREGORIAN_CHANGE =
249     new Date JavaDoc(Long.MIN_VALUE);
250
251     /**
252      * Year index for MIN_ and MAX_FIELD_VALUES.
253      */

254     private static final int YEAR = 0;
255
256     /**
257      * Month index for MIN_ and MAX_FIELD_VALUES.
258      */

259     private static final int MONTH = 1;
260
261     /**
262      * Day index for MIN_ and MAX_FIELD_VALUES.
263      */

264     private static final int DAY = 2;
265
266     /**
267      * Hour index for MIN_ and MAX_FIELD_VALUES.
268      */

269     private static final int HOUR = 3;
270
271     /**
272      * Minute index for MIN_ and MAX_FIELD_VALUES.
273      */

274     private static final int MINUTE = 4;
275
276     /**
277      * Second index for MIN_ and MAX_FIELD_VALUES.
278      */

279     private static final int SECOND = 5;
280
281     /**
282      * Second index for MIN_ and MAX_FIELD_VALUES.
283      */

284     private static final int MILLISECOND = 6;
285
286     /**
287      * Timezone index for MIN_ and MAX_FIELD_VALUES
288      */

289     private static final int TIMEZONE = 7;
290
291     /**
292      * Minimum field values indexed by YEAR..TIMEZONE.
293      */

294     private static final int MIN_FIELD_VALUE[] = {
295     Integer.MIN_VALUE, //Year field can be smaller than this,
296
// only constraint on integer value of year.
297
DatatypeConstants.JANUARY,
298     1, //day of month
299
0, //hour
300
0, //minute
301
0, //second
302
0, //millisecond
303
-14 * 60 //timezone
304
};
305
306     /**
307      * Maximum field values indexed by YEAR..TIMEZONE.
308      */

309     private static final int MAX_FIELD_VALUE[] = {
310     Integer.MAX_VALUE, // Year field can be bigger than this,
311
// only constraint on integer value of year.
312
DatatypeConstants.DECEMBER,
313     31, //day of month
314
23, //hour
315
59, //minute
316
60, //second (leap second allows for 60)
317
999, //millisecond
318
14 * 60 //timezone
319
};
320
321     /**
322      * field names indexed by YEAR..TIMEZONE.
323      */

324     private static final String JavaDoc FIELD_NAME[] = {
325     "Year",
326     "Month",
327     "Day",
328     "Hour",
329     "Minute",
330     "Second",
331     "Millisecond",
332     "Timezone"
333     };
334
335     /**
336      * <p>Stream Unique Identifier.</p>
337      *
338      * <p>TODO: Serialization should use the XML string representation as
339      * the serialization format to ensure future compatibility.</p>
340      */

341     private static final long serialVersionUID = 1L;
342
343     /**
344      * <p>Use as a template for default field values when
345      * converting to a {@link GregorianCalendar}, set to a leap
346      * year date of January 1, 0400 at midnight.</p>
347      *
348      * <p>Fields that are optional for an <code>xsd:dateTime</code> instances are defaulted to not being set to any value.
349      * <code>XMLGregorianCalendar</code> fields millisecond, fractional second and timezone return the value indicating
350      * that the field is not set, {@link DatatypeConstants#FIELD_UNDEFINED} for millisecond and timezone
351      * and <code>null</code> for fractional second.</p>
352      *
353      * @see #toGregorianCalendar(TimeZone, Locale, XMLGregorianCalendar)
354      */

355     public static final XMLGregorianCalendar JavaDoc LEAP_YEAR_DEFAULT =
356         createDateTime(
357             400, //year
358
DatatypeConstants.JANUARY, //month
359
1, // day
360
0, // hour
361
0, // minute
362
0, // second
363
DatatypeConstants.FIELD_UNDEFINED, // milliseconds
364
DatatypeConstants.FIELD_UNDEFINED // timezone
365
);
366
367     // Constructors
368

369     /**
370      * Constructs a new XMLGregorianCalendar object.
371      *
372      * String parsing documented by {@link #parse(String)}.
373      *
374      * Returns a non-null valid XMLGregorianCalendar object that holds the
375      * value indicated by the lexicalRepresentation parameter.
376      *
377      * @param lexicalRepresentation
378      * Lexical representation of one the eight
379      * XML Schema date/time datatypes.
380      * @throws IllegalArgumentException
381      * If the given string does not conform as documented in
382      * {@link #parse(String)}.
383      * @throws NullPointerException
384      * If the given string is null.
385      */

386     protected XMLGregorianCalendarImpl(String JavaDoc lexicalRepresentation)
387         throws IllegalArgumentException JavaDoc {
388             
389     // compute format string for this lexical representation.
390
String JavaDoc format = null;
391     String JavaDoc lexRep = lexicalRepresentation;
392     final int NOT_FOUND = -1;
393     int lexRepLength = lexRep.length();
394     
395     
396     // current parser needs a format string,
397
// use following heuristics to figure out what xml schema date/time
398
// datatype this lexical string could represent.
399
if (lexRep.indexOf('T') != NOT_FOUND) {
400         // found Date Time separater, must be xsd:DateTime
401
format = "%Y-%M-%DT%h:%m:%s" + "%z";
402     } else if (lexRepLength >= 3 && lexRep.charAt(2) == ':') {
403         // found ":", must be xsd:Time
404
format = "%h:%m:%s" +"%z";
405     } else if (lexRep.startsWith("--")) {
406         // check for GDay || GMonth || GMonthDay
407
if (lexRepLength >= 3 && lexRep.charAt(2) == '-') {
408         // GDAY
409
// Fix 4971612: invalid SCCS macro substitution in data string
410
format = "---%D" + "%z";
411         } else if (lexRepLength == 4 || (lexRepLength >= 6 && (lexRep.charAt(4) == '+' || (lexRep.charAt(4) == '-' && (lexRep.charAt(5) == '-' || lexRepLength == 10))))) {
412         // GMonth
413
// Fix 4971612: invalid SCCS macro substitution in data string
414
format = "--%M--%z";
415         Parser p = new Parser(format, lexRep);
416         try {
417             p.parse();
418             // check for validity
419
if (!isValid()) {
420                 throw new IllegalArgumentException JavaDoc(
421                     DatatypeMessageFormatter.formatMessage(null,"InvalidXGCRepresentation", new Object JavaDoc[]{lexicalRepresentation})
422                     //"\"" + lexicalRepresentation + "\" is not a valid representation of an XML Gregorian Calendar value."
423
);
424             }
425             save();
426             return;
427         }
428         catch(IllegalArgumentException JavaDoc e) {
429             format = "--%M%z";
430         }
431         } else {
432         // GMonthDay or invalid lexicalRepresentation
433
format = "--%M-%D" + "%z";
434         }
435     } else {
436         // check for Date || GYear | GYearMonth
437
int countSeparator = 0;
438
439         // start at index 1 to skip potential negative sign for year.
440

441         
442         int timezoneOffset = lexRep.indexOf(':');
443         if (timezoneOffset != NOT_FOUND) {
444
445         // found timezone, strip it off for distinguishing
446
// between Date, GYear and GYearMonth so possible
447
// negative sign in timezone is not mistaken as
448
// a separator.
449
lexRepLength -= 6;
450         }
451         
452         for (int i=1; i < lexRepLength; i++) {
453         if (lexRep.charAt(i) == '-') {
454             countSeparator++;
455         }
456         }
457         if (countSeparator == 0) {
458         // GYear
459
format = "%Y" + "%z";
460         } else if (countSeparator == 1) {
461         // GYearMonth
462
format = "%Y-%M" + "%z";
463         } else {
464         // Date or invalid lexicalRepresentation
465
// Fix 4971612: invalid SCCS macro substitution in data string
466
format = "%Y-%M-%D" + "%z";
467         }
468     }
469     Parser p = new Parser(format, lexRep);
470     p.parse();
471     
472         // check for validity
473
if (!isValid()) {
474             throw new IllegalArgumentException JavaDoc(
475                 DatatypeMessageFormatter.formatMessage(null,"InvalidXGCRepresentation", new Object JavaDoc[]{lexicalRepresentation})
476                 //"\"" + lexicalRepresentation + "\" is not a valid representation of an XML Gregorian Calendar value."
477
);
478         }
479         save();
480     }
481     
482     /**
483      *
484      */

485     private void save() {
486         orig_eon = eon;
487         orig_year = year;
488         orig_month = month;
489         orig_day = day;
490         orig_hour = hour;
491         orig_minute = minute;
492         orig_second = second;
493         orig_fracSeconds = fractionalSecond;
494         orig_timezone = timezone;
495     }
496
497     /**
498      * <p>Create an instance with all date/time datatype fields set to
499      * {@link DatatypeConstants#FIELD_UNDEFINED} or null respectively.</p>
500      */

501     public XMLGregorianCalendarImpl() {
502         
503         // field initializers already do the correct initialization.
504
}
505
506     /**
507      * <p>Private constructor allowing for complete value spaces allowed by
508      * W3C XML Schema 1.0 recommendation for xsd:dateTime and related
509      * builtin datatypes. Note that <code>year</code> parameter supports
510      * arbitrarily large numbers and fractionalSecond has infinite
511      * precision.</p>
512      *
513      * @param year of <code>XMLGregorianCalendar</code> to be created.
514      * @param month of <code>XMLGregorianCalendar</code> to be created.
515      * @param day of <code>XMLGregorianCalendar</code> to be created.
516      * @param hour of <code>XMLGregorianCalendar</code> to be created.
517      * @param minute of <code>XMLGregorianCalendar</code> to be created.
518      * @param second of <code>XMLGregorianCalendar</code> to be created.
519      * @param fractionalSecond of <code>XMLGregorianCalendar</code> to be created.
520      * @param timezone of <code>XMLGregorianCalendar</code> to be created.
521      *
522      */

523     protected XMLGregorianCalendarImpl(
524         BigInteger JavaDoc year,
525         int month,
526         int day,
527         int hour,
528         int minute,
529         int second,
530         BigDecimal JavaDoc fractionalSecond,
531         int timezone) {
532             
533         setYear(year);
534         setMonth(month);
535         setDay(day);
536         setTime(hour, minute, second, fractionalSecond);
537         setTimezone(timezone);
538         
539         // check for validity
540
if (!isValid()) {
541             
542             throw new IllegalArgumentException JavaDoc(
543                 DatatypeMessageFormatter.formatMessage(null,
544                     "InvalidXGCValue-fractional",
545                     new Object JavaDoc[] { year, new Integer JavaDoc(month), new Integer JavaDoc(day),
546                     new Integer JavaDoc(hour), new Integer JavaDoc(minute), new Integer JavaDoc(second),
547                     fractionalSecond, new Integer JavaDoc(timezone)})
548             );
549                     
550             /**
551                 String yearString = "null";
552                 if (year != null) {
553                     yearString = year.toString();
554                 }
555                 String fractionalSecondString = "null";
556                 if (fractionalSecond != null) {
557                     fractionalSecondString = fractionalSecond.toString();
558                 }
559              
560                 throw new IllegalArgumentException(
561                     "year = " + yearString
562                     + ", month = " + month
563                     + ", day = " + day
564                     + ", hour = " + hour
565                     + ", minute = " + minute
566                     + ", second = " + second
567                     + ", fractionalSecond = " + fractionalSecondString
568                     + ", timezone = " + timezone
569                     + ", is not a valid representation of an XML Gregorian Calendar value."
570                 );
571                 */

572             
573         }
574         
575         save();
576         
577     }
578
579     /**
580      * <p>Private constructor of value spaces that a
581      * <code>java.util.GregorianCalendar</code> instance would need to convert to an
582      * <code>XMLGregorianCalendar</code> instance.</p>
583      *
584      * <p><code>XMLGregorianCalendar eon</code> and
585      * <code>fractionalSecond</code> are set to <code>null</code></p>
586      *
587      * @param year of <code>XMLGregorianCalendar</code> to be created.
588      * @param month of <code>XMLGregorianCalendar</code> to be created.
589      * @param day of <code>XMLGregorianCalendar</code> to be created.
590      * @param hour of <code>XMLGregorianCalendar</code> to be created.
591      * @param minute of <code>XMLGregorianCalendar</code> to be created.
592      * @param second of <code>XMLGregorianCalendar</code> to be created.
593      * @param millisecond of <code>XMLGregorianCalendar</code> to be created.
594      * @param timezone of <code>XMLGregorianCalendar</code> to be created.
595      */

596     private XMLGregorianCalendarImpl(
597         int year,
598         int month,
599         int day,
600         int hour,
601         int minute,
602         int second,
603         int millisecond,
604         int timezone) {
605             
606         setYear(year);
607         setMonth(month);
608         setDay(day);
609         setTime(hour, minute, second);
610         setTimezone(timezone);
611         setMillisecond(millisecond);
612
613         if (!isValid()) {
614             
615             throw new IllegalArgumentException JavaDoc(
616                 DatatypeMessageFormatter.formatMessage(null,
617                 "InvalidXGCValue-milli",
618                 new Object JavaDoc[] { new Integer JavaDoc(year), new Integer JavaDoc(month), new Integer JavaDoc(day),
619                 new Integer JavaDoc(hour), new Integer JavaDoc(minute), new Integer JavaDoc(second),
620                 new Integer JavaDoc(millisecond), new Integer JavaDoc(timezone)})
621             );
622                 /*
623                 throw new IllegalArgumentException(
624                     "year = " + year
625                     + ", month = " + month
626                     + ", day = " + day
627                     + ", hour = " + hour
628                     + ", minute = " + minute
629                     + ", second = " + second
630                     + ", millisecond = " + millisecond
631                     + ", timezone = " + timezone
632                     + ", is not a valid representation of an XML Gregorian Calendar value."
633                     );
634                  */

635             
636         }
637         save();
638     }
639     
640     /**
641      * <p>Convert a <code>java.util.GregorianCalendar</code> to XML Schema 1.0
642      * representation.</p>
643      *
644      * <table border="2" rules="all" cellpadding="2">
645      * <thead>
646      * <tr>
647      * <th align="center" colspan="2">
648      * Field by Field Conversion from
649      * <code>java.util.GregorianCalendar</code> to this class
650      * </th>
651      * </tr>
652      * </thead>
653      * <tbody>
654      * <tr>
655      * <th><code>javax.xml.datatype.XMLGregorianCalendar</code> field</th>
656      * <th><code>java.util.GregorianCalendar</code> field</th>
657      * </tr>
658      * <tr>
659      * <th>{@link #setYear(int)}</th>
660      * <th><code>ERA == GregorianCalendar.BC ? -YEAR : YEAR</code></th>
661      * </tr>
662      * <tr>
663      * <th>{@link #setMonth(int)}</th>
664      * <th><code>MONTH + 1</code></th>
665      * </tr>
666      * <tr>
667      * <th>{@link #setDay(int)}</th>
668      * <th><code>DAY_OF_MONTH</code></th>
669      * </tr>
670      * <tr>
671      * <th>{@link #setTime(int,int,int, BigDecimal)}</th>
672      * <th><code>HOUR_OF_DAY, MINUTE, SECOND, MILLISECOND</code></th>
673      * </tr>
674      * <tr>
675      * <th>{@link #setTimezone(int)}<i>*</i></th>
676      * <th><code>(ZONE_OFFSET + DST_OFFSET) / (60*1000)</code><br/>
677      * <i>(in minutes)</i>
678      * </th>
679      * </tr>
680      * </tbody>
681      * </table>
682      * <p><i>*</i>conversion loss of information. It is not possible to represent
683      * a <code>java.util.GregorianCalendar</code> daylight savings timezone id in the
684      * XML Schema 1.0 date/time datatype representation.</p>
685      *
686      * <p>To compute the return value's <code>TimeZone</code> field,
687      * <ul>
688      * <li>when <code>this.getTimezone() != DatatypeConstants.FIELD_UNDEFINED</code>,
689      * create a <code>java.util.TimeZone</code> with a custom timezone id
690      * using the <code>this.getTimezone()</code>.</li>
691      * <li>else use the <code>GregorianCalendar</code> default timezone value
692      * for the host is defined as specified by
693      * <code>java.util.TimeZone.getDefault()</code>.</li></p>
694      *
695      * @param cal <code>java.util.GregorianCalendar</code> used to create <code>XMLGregorianCalendar</code>
696      */

697     public XMLGregorianCalendarImpl(GregorianCalendar JavaDoc cal) {
698         
699     int year = cal.get(Calendar.YEAR);
700     if (cal.get(Calendar.ERA) == GregorianCalendar.BC) {
701         year = -year;
702     }
703     this.setYear(year);
704     
705     // Calendar.MONTH is zero based, XSD Date datatype's month field starts
706
// with JANUARY as 1.
707
this.setMonth(cal.get(Calendar.MONTH) + 1);
708     this.setDay(cal.get(Calendar.DAY_OF_MONTH));
709     this.setTime(
710         cal.get(Calendar.HOUR_OF_DAY),
711         cal.get(Calendar.MINUTE),
712         cal.get(Calendar.SECOND),
713         cal.get(Calendar.MILLISECOND));
714     
715     // Calendar ZONE_OFFSET and DST_OFFSET fields are in milliseconds.
716
int offsetInMinutes = (cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET)) / (60 * 1000);
717     this.setTimezone(offsetInMinutes);
718     save();
719     }
720
721     // Factories
722

723     /**
724      * <p>Create a Java representation of XML Schema builtin datatype <code>dateTime</code>.
725      * All possible fields are specified for this factory method.</p>
726      *
727      * @param year represents both high-order eons and low-order year.
728      * @param month of <code>dateTime</code>
729      * @param day of <code>dateTime</code>
730      * @param hours of <code>dateTime</code>
731      * @param minutes of <code>dateTime</code>
732      * @param seconds of <code>dateTime</code>
733      * @param fractionalSecond value of null indicates optional field is absent.
734      * @param timezone offset in minutes. {@link DatatypeConstants#FIELD_UNDEFINED} indicates optional field is not set.
735      *
736      * @return <code>XMLGregorianCalendar</code> created from parameter values.
737      *
738      * @see DatatypeConstants#FIELD_UNDEFINED
739      *
740      * @throws IllegalArgumentException if any parameter is outside value
741      * constraints for the field as specified in
742      * <a HREF="#datetimefieldmapping">date/time field mapping table</a>.
743      */

744     public static XMLGregorianCalendar JavaDoc createDateTime(
745         BigInteger JavaDoc year,
746         int month,
747         int day,
748         int hours,
749         int minutes,
750         int seconds,
751         BigDecimal JavaDoc fractionalSecond,
752         int timezone) {
753     
754     return new XMLGregorianCalendarImpl(
755         year,
756         month,
757         day,
758         hours,
759         minutes,
760         seconds,
761         fractionalSecond,
762         timezone);
763     }
764
765     /**
766      * <p>Create a Java instance of XML Schema builtin datatype dateTime.</p>
767      *
768      * @param year represents both high-order eons and low-order year.
769      * @param month of <code>dateTime</code>
770      * @param day of <code>dateTime</code>
771      * @param hour of <code>dateTime</code>
772      * @param minute of <code>dateTime</code>
773      * @param second of <code>dateTime</code>
774      *
775      * @return <code>XMLGregorianCalendar</code> created from parameter values.
776      *
777      * @throws IllegalArgumentException if any parameter is outside value constraints for the field as specified in
778      * <a HREF="#datetimefieldmapping">date/time field mapping table</a>.
779      *
780      * @see DatatypeConstants#FIELD_UNDEFINED
781      */

782     public static XMLGregorianCalendar JavaDoc createDateTime(
783         int year,
784         int month,
785         int day,
786         int hour,
787         int minute,
788         int second) {
789             
790         return new XMLGregorianCalendarImpl(
791             year,
792             month,
793             day,
794             hour,
795             minute,
796             second,
797             DatatypeConstants.FIELD_UNDEFINED, //millisecond
798
DatatypeConstants.FIELD_UNDEFINED //timezone
799
);
800     }
801
802     /**
803      * <p>Create a Java representation of XML Schema builtin datatype <code>dateTime</code>.
804      * All possible fields are specified for this factory method.</p>
805      *
806      * @param year represents low-order year.
807      * @param month of <code>dateTime</code>
808      * @param day of <code>dateTime</code>
809      * @param hours of <code>dateTime</code>
810      * @param minutes of <code>dateTime</code>
811      * @param seconds of <code>dateTime</code>
812      * @param milliseconds of <code>dateTime</code>. {@link DatatypeConstants#FIELD_UNDEFINED} indicates optional field is not set.
813      * @param timezone offset in minutes. {@link DatatypeConstants#FIELD_UNDEFINED} indicates optional field is not set.
814      *
815      * @return <code>XMLGregorianCalendar</code> created from parameter values.
816      *
817      * @throws IllegalArgumentException if any parameter is outside value constraints for the field as specified in
818      * <a HREF="#datetimefieldmapping">date/time field mapping table</a>.
819      *
820      * @see DatatypeConstants#FIELD_UNDEFINED
821      */

822     public static XMLGregorianCalendar JavaDoc createDateTime(
823         int year,
824         int month,
825         int day,
826         int hours,
827         int minutes,
828         int seconds,
829         int milliseconds,
830         int timezone) {
831             
832         return new XMLGregorianCalendarImpl(
833             year,
834             month,
835             day,
836             hours,
837             minutes,
838             seconds,
839             milliseconds,
840             timezone);
841     }
842
843     /**
844      * <p>Create a Java representation of XML Schema builtin datatype <code>date</code> or <code>g*</code>.</p>
845      *
846      * <p>For example, an instance of <code>gYear</code> can be created invoking this factory
847      * with <code>month</code> and <code>day</code> parameters set to
848      * {@link DatatypeConstants#FIELD_UNDEFINED}.</p>
849      *
850      * @param year of <code>XMLGregorianCalendar</code> to be created.
851      * @param month of <code>XMLGregorianCalendar</code> to be created.
852      * @param day of <code>XMLGregorianCalendar</code> to be created.
853      * @param timezone offset in minutes. {@link DatatypeConstants#FIELD_UNDEFINED} indicates optional field is not set.
854      *
855      * @return <code>XMLGregorianCalendar</code> created from parameter values.
856      *
857      * @see DatatypeConstants#FIELD_UNDEFINED
858      *
859      * @throws IllegalArgumentException if any parameter is outside value
860      * constraints for the field as specified in
861      * <a HREF="#datetimefieldmapping">date/time field mapping table</a>.
862      */

863     public static XMLGregorianCalendar JavaDoc createDate(
864         int year,
865         int month,
866         int day,
867         int timezone) {
868             
869         return new XMLGregorianCalendarImpl(
870             year,
871             month,
872             day,
873             DatatypeConstants.FIELD_UNDEFINED, // hour
874
DatatypeConstants.FIELD_UNDEFINED, // minute
875
DatatypeConstants.FIELD_UNDEFINED, // second
876
DatatypeConstants.FIELD_UNDEFINED, // millisecond
877
timezone);
878     }
879
880     /**
881      * Create a Java instance of XML Schema builtin datatype <code>time</code>.
882      * @param hours number of hours
883      * @param minutes number of minutes
884      * @param seconds number of seconds
885      * @param timezone offset in minutes. {@link DatatypeConstants#FIELD_UNDEFINED} indicates optional field is not set.
886      *
887      * @return <code>XMLGregorianCalendar</code> created from parameter values.
888      *
889      * @see DatatypeConstants#FIELD_UNDEFINED
890      *
891      * @throws IllegalArgumentException if any parameter is outside value
892      * constraints for the field as specified in
893      * <a HREF="#datetimefieldmapping">date/time field mapping table</a>.
894      */

895     public static XMLGregorianCalendar JavaDoc createTime(
896         int hours,
897         int minutes,
898         int seconds,
899         int timezone) {
900             
901         return new XMLGregorianCalendarImpl(
902             DatatypeConstants.FIELD_UNDEFINED, // Year
903
DatatypeConstants.FIELD_UNDEFINED, // Month
904
DatatypeConstants.FIELD_UNDEFINED, // Day
905
hours,
906             minutes,
907             seconds,
908             DatatypeConstants.FIELD_UNDEFINED, //Millisecond
909
timezone);
910     }
911
912     /**
913      * <p>Create a Java instance of XML Schema builtin datatype time.</p>
914      *
915      * @param hours number of hours
916      * @param minutes number of minutes
917      * @param seconds number of seconds
918      * @param fractionalSecond value of <code>null</code> indicates that this optional field is not set.
919      * @param timezone offset in minutes. {@link DatatypeConstants#FIELD_UNDEFINED} indicates optional field is not set.
920      *
921      * @return <code>XMLGregorianCalendar</code> created from parameter values.
922      *
923      * @see DatatypeConstants#FIELD_UNDEFINED
924      *
925      * @throws IllegalArgumentException if any parameter is outside value
926      * constraints for the field as specified in
927      * <a HREF="#datetimefieldmapping">date/time field mapping table</a>.
928      */

929     public static XMLGregorianCalendar JavaDoc createTime(
930         int hours,
931         int minutes,
932         int seconds,
933         BigDecimal JavaDoc fractionalSecond,
934         int timezone) {
935             
936         return new XMLGregorianCalendarImpl(
937             null, // Year
938
DatatypeConstants.FIELD_UNDEFINED, // month
939
DatatypeConstants.FIELD_UNDEFINED, // day
940
hours,
941             minutes,
942             seconds,
943             fractionalSecond,
944             timezone);
945     }
946
947     /**
948      * <p>Create a Java instance of XML Schema builtin datatype time.</p>
949      *
950      * @param hours number of hours
951      * @param minutes number of minutes
952      * @param seconds number of seconds
953      * @param milliseconds number of milliseconds
954      * @param timezone offset in minutes. {@link DatatypeConstants#FIELD_UNDEFINED} indicates optional field is not set.
955      *
956      * @return <code>XMLGregorianCalendar</code> created from parameter values.
957      *
958      * @see DatatypeConstants#FIELD_UNDEFINED
959      *
960      * @throws IllegalArgumentException if any parameter is outside value
961      * constraints for the field as specified in
962      * <a HREF="#datetimefieldmapping">date/time field mapping table</a>.
963      */

964     public static XMLGregorianCalendar JavaDoc createTime(
965         int hours,
966         int minutes,
967         int seconds,
968     int milliseconds,
969         int timezone) {
970             
971         return new XMLGregorianCalendarImpl(
972             DatatypeConstants.FIELD_UNDEFINED, // year
973
DatatypeConstants.FIELD_UNDEFINED, // month
974
DatatypeConstants.FIELD_UNDEFINED, // day
975
hours,
976             minutes,
977             seconds,
978         milliseconds,
979             timezone);
980     }
981
982     // Accessors
983

984     /**
985      * <p>Return high order component for XML Schema 1.0 dateTime datatype field for
986      * <code>year</code>.
987      * <code>null</code> if this optional part of the year field is not defined.</p>
988      *
989      * <p>Value constraints for this value are summarized in
990      * <a HREF="#datetimefield-year">year field of date/time field mapping table</a>.</p>
991      * @return eon of this <code>XMLGregorianCalendar</code>. The value
992      * returned is an integer multiple of 10^9.
993      *
994      * @see #getYear()
995      * @see #getEonAndYear()
996      */

997     public BigInteger JavaDoc getEon() {
998        return eon;
999     }
1000
1001    /**
1002     * <p>Return low order component for XML Schema 1.0 dateTime datatype field for
1003     * <code>year</code> or {@link DatatypeConstants#FIELD_UNDEFINED}.</p>
1004     *
1005     * <p>Value constraints for this value are summarized in
1006     * <a HREF="#datetimefield-year">year field of date/time field mapping table</a>.</p>
1007     *
1008     * @return year of this <code>XMLGregorianCalendar</code>.
1009     *
1010     * @see #getEon()
1011     * @see #getEonAndYear()
1012     */

1013    public int getYear() {
1014       return year;
1015    }
1016
1017    /**
1018     * <p>Return XML Schema 1.0 dateTime datatype field for
1019     * <code>year</code>.</p>
1020     *
1021     * <p>Value constraints for this value are summarized in
1022     * <a HREF="#datetimefield-year">year field of date/time field mapping table</a>.</p>
1023     *
1024     * @return sum of <code>eon</code> and <code>BigInteger.valueOf(year)</code>
1025     * when both fields are defined. When only <code>year</code> is defined,
1026     * return it. When both <code>eon</code> and <code>year</code> are not
1027     * defined, return <code>null</code>.
1028     *
1029     * @see #getEon()
1030     * @see #getYear()
1031     */

1032    public BigInteger JavaDoc getEonAndYear() {
1033        
1034        // both are defined
1035
if (year != DatatypeConstants.FIELD_UNDEFINED
1036            && eon != null) {
1037                
1038            return eon.add(BigInteger.valueOf((long) year));
1039        }
1040
1041        // only year is defined
1042
if (year != DatatypeConstants.FIELD_UNDEFINED
1043            && eon == null) {
1044                
1045            return BigInteger.valueOf((long) year);
1046        }
1047
1048        // neither are defined
1049
// or only eon is defined which is not valid without a year
1050
return null;
1051    }
1052
1053    /**
1054     * <p>Return number of month or {@link DatatypeConstants#FIELD_UNDEFINED}.</p>
1055     *
1056     * <p>Value constraints for this value are summarized in
1057     * <a HREF="#datetimefield-month">month field of date/time field mapping table</a>.</p>
1058     *
1059     * @return year of this <code>XMLGregorianCalendar</code>.
1060     *
1061     */

1062    public int getMonth() {
1063        return month;
1064    }
1065
1066    /**
1067     * Return day in month or {@link DatatypeConstants#FIELD_UNDEFINED}.</p>
1068     *
1069     * <p>Value constraints for this value are summarized in
1070     * <a HREF="#datetimefield-day">day field of date/time field mapping table</a>.</p>
1071     *
1072     * @see #setDay(int)
1073     */

1074    public int getDay() {
1075    return day;
1076    }
1077
1078    /**
1079     * Return timezone offset in minutes or
1080     * {@link DatatypeConstants#FIELD_UNDEFINED} if this optional field is not defined.
1081     *
1082     * <p>Value constraints for this value are summarized in
1083     * <a HREF="#datetimefield-timezone">timezone field of date/time field mapping table</a>.</p>
1084     *
1085     * @see #setTimezone(int)
1086     */

1087    public int getTimezone() {
1088    return timezone;
1089    }
1090
1091    /**
1092     * Return hours or {@link DatatypeConstants#FIELD_UNDEFINED}.
1093     * Returns {@link DatatypeConstants#FIELD_UNDEFINED} if this field is not defined.
1094     *
1095     * <p>Value constraints for this value are summarized in
1096     * <a HREF="#datetimefield-hour">hour field of date/time field mapping table</a>.</p>
1097     * @see #setTime(int, int, int)
1098     */

1099    public int getHour() {
1100    return hour;
1101    }
1102
1103    /**
1104     * Return minutes or {@link DatatypeConstants#FIELD_UNDEFINED}.<\p>
1105     * Returns {@link DatatypeConstants#FIELD_UNDEFINED} if this field is not defined.
1106     *
1107     * <p>Value constraints for this value are summarized in
1108     * <a HREF="#datetimefield-minute">minute field of date/time field mapping table</a>.</p>
1109     * @see #setTime(int, int, int)
1110     */

1111    public int getMinute() {
1112    return minute;
1113    }
1114
1115    /**
1116     * <p>Return seconds or {@link DatatypeConstants#FIELD_UNDEFINED}.<\p>
1117     *
1118     * <p>Returns {@link DatatypeConstants#FIELD_UNDEFINED} if this field is not defined.
1119     * When this field is not defined, the optional xs:dateTime
1120     * fractional seconds field, represented by
1121     * {@link #getFractionalSecond()} and {@link #getMillisecond()},
1122     * must not be defined.</p>
1123     *
1124     * <p>Value constraints for this value are summarized in
1125     * <a HREF="#datetimefield-second">second field of date/time field mapping table</a>.</p>
1126     *
1127     * @return Second of this <code>XMLGregorianCalendar</code>.
1128     *
1129     * @see #getFractionalSecond()
1130     * @see #getMillisecond()
1131     * @see #setTime(int, int, int)
1132     */

1133    public int getSecond() {
1134       return second;
1135    }
1136
1137    /**
1138     * @return result of adding second and fractional second field
1139     */

1140    private BigDecimal JavaDoc getSeconds() {
1141        
1142    if (second == DatatypeConstants.FIELD_UNDEFINED) {
1143        return DECIMAL_ZERO;
1144    }
1145    BigDecimal JavaDoc result = BigDecimal.valueOf((long)second);
1146    if (fractionalSecond != null){
1147        return result.add(fractionalSecond);
1148    } else {
1149        return result;
1150    }
1151    }
1152
1153
1154    /**
1155     * <p>Return millisecond precision of {@link #getFractionalSecond()}.<\p>
1156     *
1157     * <p>This method represents a convenience accessor to infinite
1158     * precision fractional second value returned by
1159     * {@link #getFractionalSecond()}. The returned value is the rounded
1160     * down to milliseconds value of
1161     * {@link #getFractionalSecond()}. When {@link #getFractionalSecond()}
1162     * returns <code>null</code>, this method must return
1163     * {@link DatatypeConstants#FIELD_UNDEFINED}.</p>
1164     *
1165     * <p>Value constraints for this value are summarized in
1166     * <a HREF="#datetimefield-second">second field of date/time field mapping table</a>.</p>
1167     *
1168     * @return Millisecond of this <code>XMLGregorianCalendar</code>.
1169     *
1170     * @see #getFractionalSecond()
1171     * @see #setTime(int, int, int)
1172     */

1173    public int getMillisecond() {
1174        if (fractionalSecond == null) {
1175            return DatatypeConstants.FIELD_UNDEFINED;
1176        } else {
1177            // TODO: Non-optimal solution for now.
1178
// Efficient implementation would only store as BigDecimal
1179
// when needed and millisecond otherwise.
1180
return fractionalSecond.movePointRight(3).intValue();
1181        }
1182    }
1183
1184    /**
1185     * <p>Return fractional seconds.</p>
1186     *
1187     * <p><code>null</code> is returned when this optional field is not defined.</p>
1188     *
1189     * <p>Value constraints are detailed in
1190     * <a HREF="#datetimefield-second">second field of date/time field mapping table</a>.</p>
1191     *
1192     * <p>This optional field can only have a defined value when the
1193     * xs:dateTime second field, represented by ({@link #getSecond()},
1194     * does not return {@link DatatypeConstants#FIELD_UNDEFINED}).</p>
1195     *
1196     * @return fractional seconds of this <code>XMLGregorianCalendar</code>.
1197     *
1198     * @see #getSecond()
1199     * @see #setTime(int, int, int, BigDecimal)
1200     */

1201    public BigDecimal JavaDoc getFractionalSecond() {
1202       return fractionalSecond;
1203    }
1204
1205    // setters
1206

1207    /**
1208     * <p>Set low and high order component of XSD <code>dateTime</code> year field.</p>
1209     *
1210     * <p>Unset this field by invoking the setter with a parameter value of <code>null</code>.</p>
1211     *
1212     * @param year value constraints summarized in <a HREF="#datetimefield-year">year field of date/time field mapping table</a>.
1213     *
1214     * @throws IllegalArgumentException if <code>year</code> parameter is
1215     * outside value constraints for the field as specified in
1216     * <a HREF="#datetimefieldmapping">date/time field mapping table</a>.
1217     */

1218    public void setYear(BigInteger JavaDoc year) {
1219    if (year == null) {
1220        this.eon = null;
1221        this.year = DatatypeConstants.FIELD_UNDEFINED;
1222    } else {
1223        BigInteger JavaDoc temp = year.remainder(BILLION);
1224        this.year = temp.intValue();
1225        setEon(year.subtract(temp));
1226    }
1227    }
1228
1229    /**
1230     * <p>Set year of XSD <code>dateTime</code> year field.</p>
1231     *
1232     * <p>Unset this field by invoking the setter with a parameter value of
1233     * {@link DatatypeConstants#FIELD_UNDEFINED}.</p>
1234     *
1235     * <p>Note: if the absolute value of the <code>year</code> parameter
1236     * is less than 10^9, the eon component of the XSD year field is set to
1237     * <code>null</code> by this method.</p>
1238     *
1239     * @param year value constraints are summarized in <a HREF="#datetimefield-year">year field of date/time field mapping table</a>.
1240     * If year is {@link DatatypeConstants#FIELD_UNDEFINED}, then eon is set to <code>null</code>.
1241     */

1242    public void setYear(int year) {
1243    if (year == DatatypeConstants.FIELD_UNDEFINED) {
1244        this.year = DatatypeConstants.FIELD_UNDEFINED;
1245        this.eon = null;
1246    } else if (Math.abs(year) < BILLION.intValue()) {
1247        this.year = year;
1248        this.eon = null;
1249    } else {
1250        BigInteger JavaDoc theYear = BigInteger.valueOf((long) year);
1251        BigInteger JavaDoc remainder = theYear.remainder(BILLION);
1252        this.year = remainder.intValue();
1253        setEon(theYear.subtract(remainder));
1254    }
1255    }
1256
1257    /**
1258     * <p>Set high order part of XSD <code>dateTime</code> year field.</p>
1259     *
1260     * <p>Unset this field by invoking the setter with a parameter value of
1261     * <code>null</code>.</p>
1262     *
1263     * @param eon value constraints summarized in <a HREF="#datetimefield-year">year field of date/time field mapping table</a>.
1264     */

1265    private void setEon(BigInteger JavaDoc eon) {
1266        if (eon != null && eon.compareTo(BigInteger.ZERO) == 0) {
1267            // Treat ZERO as field being undefined.
1268
this.eon = null;
1269        } else {
1270            this.eon = eon;
1271        }
1272    }
1273
1274    /**
1275     * <p>Set month.</p>
1276     *
1277     * <p>Unset this field by invoking the setter with a parameter value of {@link DatatypeConstants#FIELD_UNDEFINED}.</p>
1278     *
1279     * @param month value constraints summarized in <a HREF="#datetimefield-month">month field of date/time field mapping table</a>.
1280     *
1281     * @throws IllegalArgumentException if <code>month</code> parameter is
1282     * outside value constraints for the field as specified in
1283     * <a HREF="#datetimefieldmapping">date/time field mapping table</a>.
1284     */

1285    public void setMonth(int month) {
1286    checkFieldValueConstraint(MONTH, month);
1287    this.month = month;
1288    }
1289
1290    /**
1291     * <p>Set days in month.</p>
1292     *
1293     * <p>Unset this field by invoking the setter with a parameter value of {@link DatatypeConstants#FIELD_UNDEFINED}.</p>
1294     *
1295     * @param day value constraints summarized in <a HREF="#datetimefield-day">day field of date/time field mapping table</a>.
1296     *
1297     * @throws IllegalArgumentException if <code>day</code> parameter is
1298     * outside value constraints for the field as specified in
1299     * <a HREF="#datetimefieldmapping">date/time field mapping table</a>.
1300     */

1301    public void setDay(int day) {
1302    checkFieldValueConstraint(DAY, day);
1303    this.day = day;
1304    }
1305
1306    /**
1307     * <p>Set the number of minutes in the timezone offset.</p>
1308     *
1309     * <p>Unset this field by invoking the setter with a parameter value of {@link DatatypeConstants#FIELD_UNDEFINED}.</p>
1310     *
1311     * @param offset value constraints summarized in <a HREF="#datetimefield-timezone">
1312     * timezone field of date/time field mapping table</a>.
1313     *
1314     * @throws IllegalArgumentException if <code>offset</code> parameter is
1315     * outside value constraints for the field as specified in
1316     * <a HREF="#datetimefieldmapping">date/time field mapping table</a>.
1317     */

1318    public void setTimezone(int offset) {
1319    checkFieldValueConstraint(TIMEZONE, offset);
1320    this.timezone = offset;
1321    }
1322
1323    /**
1324     * <p>Set time as one unit.</p>
1325     *
1326     * @param hour value constraints are summarized in
1327     * <a HREF="#datetimefield-hour">hour field of date/time field mapping table</a>.
1328     * @param minute value constraints are summarized in
1329     * <a HREF="#datetimefield-minute">minute field of date/time field mapping table</a>.
1330     * @param second value constraints are summarized in
1331     * <a HREF="#datetimefield-second">second field of date/time field mapping table</a>.
1332     *
1333     * @see #setTime(int, int, int, BigDecimal)
1334     *
1335     * @throws IllegalArgumentException if any parameter is
1336     * outside value constraints for the field as specified in
1337     * <a HREF="#datetimefieldmapping">date/time field mapping table</a>.
1338     */

1339    public void setTime(int hour, int minute, int second) {
1340    setTime(hour, minute, second, null);
1341    }
1342
1343    private void checkFieldValueConstraint(int field, int value)
1344    throws IllegalArgumentException JavaDoc
1345    {
1346    if ((value < MIN_FIELD_VALUE[field] && value != DatatypeConstants.FIELD_UNDEFINED) ||
1347        value > MAX_FIELD_VALUE[field]) {
1348         /**
1349            throw new IllegalArgumentException("invalid value " + value +
1350                           " for " + FIELD_NAME[field] +
1351                           " field");
1352             */

1353        throw new IllegalArgumentException JavaDoc(
1354            DatatypeMessageFormatter.formatMessage(null, "InvalidFieldValue", new Object JavaDoc[]{ new Integer JavaDoc(value), FIELD_NAME[field]})
1355        );
1356    }
1357    }
1358
1359    public void setHour(int hour) {
1360    checkFieldValueConstraint(HOUR, hour);
1361    this.hour = hour;
1362    }
1363
1364    public void setMinute(int minute) {
1365    checkFieldValueConstraint(MINUTE, minute);
1366    this.minute = minute;
1367    }
1368
1369    public void setSecond(int second) {
1370    checkFieldValueConstraint(SECOND, second);
1371    this.second = second;
1372    }
1373
1374    /**
1375     * <p>Set time as one unit, including the optional infinite precison
1376     * fractional seconds.</p>
1377     *
1378     * @param hour value constraints are summarized in
1379     * <a HREF="#datetimefield-hour">hour field of date/time field mapping table</a>.
1380     * @param minute value constraints are summarized in
1381     * <a HREF="#datetimefield-minute">minute field of date/time field mapping table</a>.
1382     * @param second value constraints are summarized in
1383     * <a HREF="#datetimefield-second">second field of date/time field mapping table</a>.
1384     * @param fractional value of <code>null</code> indicates this optional
1385     * field is not set.
1386     *
1387     * @throws IllegalArgumentException if any parameter is
1388     * outside value constraints for the field as specified in
1389     * <a HREF="#datetimefieldmapping">date/time field mapping table</a>.
1390     */

1391    public void setTime(
1392        int hour,
1393        int minute,
1394        int second,
1395        BigDecimal JavaDoc fractional) {
1396    setHour(hour);
1397        setMinute(minute);
1398        setSecond(second);
1399        setFractionalSecond(fractional);
1400    }
1401    
1402
1403    /**
1404     * <p>Set time as one unit, including optional milliseconds.</p>
1405     *
1406     * @param hour value constraints are summarized in
1407     * <a HREF="#datetimefield-hour">hour field of date/time field mapping table</a>.
1408     * @param minute value constraints are summarized in
1409     * <a HREF="#datetimefield-minute">minute field of date/time field mapping table</a>.
1410     * @param second value constraints are summarized in
1411     * <a HREF="#datetimefield-second">second field of date/time field mapping table</a>.
1412     * @param millisecond value of {@link DatatypeConstants#FIELD_UNDEFINED} indicates this
1413     * optional field is not set.
1414     *
1415     * @throws IllegalArgumentException if any parameter is
1416     * outside value constraints for the field as specified in
1417     * <a HREF="#datetimefieldmapping">date/time field mapping table</a>.
1418     */

1419    public void setTime(int hour, int minute, int second, int millisecond) {
1420        setHour(hour);
1421        setMinute(minute);
1422        setSecond(second);
1423        setMillisecond(millisecond);
1424    }
1425
1426    // comparisons
1427
/**
1428     * <p>Compare two instances of W3C XML Schema 1.0 date/time datatypes
1429     * according to partial order relation defined in
1430     * <a HREF="http://www.w3.org/TR/xmlschema-2/#dateTime-order">W3C XML Schema 1.0 Part 2, Section 3.2.7.3,
1431     * <i>Order relation on dateTime</i></a>.</p>
1432     *
1433     * <p><code>xsd:dateTime</code> datatype field mapping to accessors of
1434     * this class are defined in
1435     * <a HREF="#datetimefieldmapping">date/time field mapping table</a>.</p>
1436     *
1437     * @param rhs instance of <code>XMLGregorianCalendar</code> to compare
1438     *
1439     * @return the relationship between <code>lhs</code> and <code>rhs</code> as
1440     * {@link DatatypeConstants#LESSER},
1441     * {@link DatatypeConstants#EQUAL},
1442     * {@link DatatypeConstants#GREATER} or
1443     * {@link DatatypeConstants#INDETERMINATE}.
1444     *
1445     * @throws NullPointerException if <code>lhs</code> or <code>rhs</code>
1446     * parameters are null.
1447     */

1448    public int compare(XMLGregorianCalendar JavaDoc rhs) {
1449            
1450        //MLGregorianCalendar lhs = this;
1451

1452    int result = DatatypeConstants.INDETERMINATE;
1453        XMLGregorianCalendar JavaDoc P = this;
1454        XMLGregorianCalendar JavaDoc Q = rhs;
1455
1456        if (P.getTimezone() == Q.getTimezone()) {
1457        // Optimization:
1458
// both instances are in same timezone or
1459
// both are FIELD_UNDEFINED.
1460
// Avoid costly normalization of timezone to 'Z' time.
1461
return internalCompare(P, Q);
1462
1463    } else if (P.getTimezone() != DatatypeConstants.FIELD_UNDEFINED &&
1464           Q.getTimezone() != DatatypeConstants.FIELD_UNDEFINED) {
1465
1466        // Both instances have different timezones.
1467
// Normalize to UTC time and compare.
1468
P = (XMLGregorianCalendarImpl) P.normalize();
1469        Q = (XMLGregorianCalendarImpl) Q.normalize();
1470        return internalCompare(P, Q);
1471    } else if (P.getTimezone() != DatatypeConstants.FIELD_UNDEFINED) {
1472        
1473        if (P.getTimezone() != 0) {
1474        P = (XMLGregorianCalendarImpl) P.normalize();
1475        }
1476        
1477        // C. step 1
1478
XMLGregorianCalendar JavaDoc MinQ = normalizeToTimezone(Q, DatatypeConstants.MIN_TIMEZONE_OFFSET);
1479        result = internalCompare(P, MinQ);
1480        if (result == DatatypeConstants.LESSER) {
1481        return result;
1482        }
1483
1484        // C. step 2
1485
XMLGregorianCalendar JavaDoc MaxQ = normalizeToTimezone(Q, DatatypeConstants.MAX_TIMEZONE_OFFSET);
1486        result = internalCompare(P, MaxQ);
1487        if (result == DatatypeConstants.GREATER) {
1488        return result;
1489        } else {
1490        // C. step 3
1491
return DatatypeConstants.INDETERMINATE;
1492        }
1493    } else { // Q.getTimezone() != DatatypeConstants.FIELD_UNDEFINED
1494
// P has no timezone and Q does.
1495
if (Q.getTimezone() != 0 ) {
1496            Q = (XMLGregorianCalendarImpl) normalizeToTimezone(Q, Q.getTimezone());
1497        }
1498        
1499        // D. step 1
1500
XMLGregorianCalendar JavaDoc MaxP = normalizeToTimezone(P, DatatypeConstants.MAX_TIMEZONE_OFFSET);
1501        result = internalCompare(MaxP, Q);
1502        if (result == DatatypeConstants.LESSER) {
1503        return result;
1504        }
1505
1506        // D. step 2
1507
XMLGregorianCalendar JavaDoc MinP = normalizeToTimezone(P, DatatypeConstants.MIN_TIMEZONE_OFFSET);
1508        result = internalCompare(MinP, Q);
1509        if (result == DatatypeConstants.GREATER) {
1510        return result;
1511        } else {
1512        // D. step 3
1513
return DatatypeConstants.INDETERMINATE;
1514        }
1515        }
1516    }
1517
1518    /**
1519     * <p>Normalize this instance to UTC.</p>
1520     *
1521     * <p>2000-03-04T23:00:00+03:00 normalizes to 2000-03-04T20:00:00Z</p>
1522     * <p>Implements W3C XML Schema Part 2, Section 3.2.7.3 (A).</p>
1523     */

1524    public XMLGregorianCalendar JavaDoc normalize() {
1525
1526        XMLGregorianCalendar JavaDoc normalized = normalizeToTimezone(this, timezone);
1527        
1528        // if timezone was undefined, leave it undefined
1529
if (getTimezone() == DatatypeConstants.FIELD_UNDEFINED) {
1530            normalized.setTimezone(DatatypeConstants.FIELD_UNDEFINED);
1531        }
1532        
1533        // if milliseconds was undefined, leave it undefined
1534
if (getMillisecond() == DatatypeConstants.FIELD_UNDEFINED) {
1535            normalized.setMillisecond(DatatypeConstants.FIELD_UNDEFINED);
1536        }
1537        
1538        return normalized;
1539    }
1540    
1541    /**
1542     * <p>Normalize this instance to UTC.</p>
1543     *
1544     * <p>2000-03-04T23:00:00+03:00 normalizes to 2000-03-04T20:00:00Z</p>
1545     * <p>Implements W3C XML Schema Part 2, Section 3.2.7.3 (A).</p>
1546     */

1547    private XMLGregorianCalendar JavaDoc normalizeToTimezone(XMLGregorianCalendar JavaDoc cal, int timezone) {
1548
1549    int minutes = timezone;
1550    XMLGregorianCalendar JavaDoc result = (XMLGregorianCalendar JavaDoc) cal.clone();
1551    
1552    // normalizing to UTC time negates the timezone offset before
1553
// addition.
1554
minutes = -minutes;
1555    Duration JavaDoc d = new DurationImpl(minutes >= 0, // isPositive
1556
0, //years
1557
0, //months
1558
0, //days
1559
0, //hours
1560
minutes < 0 ? -minutes : minutes, // absolute
1561
0 //seconds
1562
);
1563    result.add(d);
1564
1565    // set to zulu UTC time.
1566
result.setTimezone(0);
1567    return result;
1568    }
1569
1570    /**
1571     *
1572     * <p>Implements Step B from http://www.w3.org/TR/xmlschema-2/#dateTime-order </p>
1573     * @param P calendar instance with normalized timezone offset or
1574     * having same timezone as Q
1575     * @param Q calendar instance with normalized timezone offset or
1576     * having same timezone as P
1577     *
1578     * @return result of comparing P and Q, value of
1579     * {@link DatatypeConstants#EQUAL},
1580     * {@link DatatypeConstants#LESSER},
1581     * {@link DatatypeConstants#GREATER} or
1582     * {@link DatatypeConstants#INDETERMINATE}.
1583     */

1584    private static int internalCompare(XMLGregorianCalendar JavaDoc P,
1585                       XMLGregorianCalendar JavaDoc Q) {
1586
1587    int result;
1588
1589    // compare Year.
1590
if (P.getEon() == Q.getEon()) {
1591        
1592        // Eon field is only equal when null.
1593
// optimized case for comparing year not requiring eon field.
1594
result = compareField(P.getYear(), Q.getYear());
1595        if (result != DatatypeConstants.EQUAL) {
1596        return result;
1597        }
1598    } else {
1599        result = compareField(P.getEonAndYear(), Q.getEonAndYear());
1600        if (result != DatatypeConstants.EQUAL) {
1601        return result;
1602        }
1603    }
1604
1605    result = compareField(P.getMonth(), Q.getMonth());
1606    if (result != DatatypeConstants.EQUAL) {
1607        return result;
1608    }
1609
1610    result = compareField(P.getDay(), Q.getDay());
1611    if (result != DatatypeConstants.EQUAL) {
1612        return result;
1613    }
1614
1615    result = compareField(P.getHour(), Q.getHour());
1616    if (result != DatatypeConstants.EQUAL) {
1617        return result;
1618    }
1619    
1620    result = compareField(P.getMinute(), Q.getMinute());
1621    if (result != DatatypeConstants.EQUAL) {
1622        return result;
1623    }
1624    result = compareField(P.getSecond(), Q.getSecond());
1625    if (result != DatatypeConstants.EQUAL) {
1626        return result;
1627    }
1628    
1629    result = compareField(P.getFractionalSecond(), Q.getFractionalSecond());
1630    return result;
1631   }
1632
1633    /**
1634     * <p>Implement Step B from
1635     * http://www.w3.org/TR/xmlschema-2/#dateTime-order.</p>
1636     */

1637    private static int compareField(int Pfield, int Qfield) {
1638    if (Pfield == Qfield) {
1639
1640        //fields are either equal in value or both undefined.
1641
// Step B. 1.1 AND optimized result of performing 1.1-1.4.
1642
return DatatypeConstants.EQUAL;
1643    } else {
1644        if (Pfield == DatatypeConstants.FIELD_UNDEFINED || Qfield == DatatypeConstants.FIELD_UNDEFINED) {
1645        // Step B. 1.2
1646
return DatatypeConstants.INDETERMINATE;
1647        } else {
1648        // Step B. 1.3-4.
1649
return (Pfield < Qfield ? DatatypeConstants.LESSER : DatatypeConstants.GREATER);
1650        }
1651    }
1652    }
1653
1654    private static int compareField(BigInteger JavaDoc Pfield, BigInteger JavaDoc Qfield) {
1655    if (Pfield == null) {
1656        return (Qfield == null ? DatatypeConstants.EQUAL : DatatypeConstants.INDETERMINATE);
1657    }
1658    if (Qfield == null) {
1659        return DatatypeConstants.INDETERMINATE;
1660    }
1661    return Pfield.compareTo(Qfield);
1662    }
1663
1664    private static int compareField(BigDecimal JavaDoc Pfield, BigDecimal JavaDoc Qfield) {
1665    // optimization. especially when both arguments are null.
1666
if (Pfield == Qfield) {
1667        return DatatypeConstants.EQUAL;
1668    }
1669
1670    if (Pfield == null) {
1671        Pfield = DECIMAL_ZERO;
1672    }
1673
1674    if (Qfield == null) {
1675        Qfield = DECIMAL_ZERO;
1676    }
1677    
1678    return Pfield.compareTo(Qfield);
1679    }
1680
1681    /**
1682     * <p>Indicates whether parameter <code>obj</code> is "equal to" this one.</p>
1683     *
1684     * @param obj to compare.
1685     *
1686     * @return <code>true</code> when <code>compare(this,(XMLGregorianCalendar)obj) == EQUAL.</code>.
1687     */

1688    public boolean equals(Object JavaDoc obj) {
1689       boolean result = false;
1690       if (obj instanceof XMLGregorianCalendar JavaDoc) {
1691           result = compare((XMLGregorianCalendar JavaDoc) obj) == DatatypeConstants.EQUAL;
1692       }
1693       return result;
1694    }
1695
1696    /**
1697     * <p>Returns a hash code consistent with the definition of the equals method.</p>
1698     *
1699     * @return hash code of this object.
1700     */

1701    public int hashCode() {
1702
1703    // Following two dates compare to EQUALS since in different timezones.
1704
// 2000-01-15T12:00:00-05:00 == 2000-01-15T13:00:00-04:00
1705
//
1706
// Must ensure both instances generate same hashcode by normalizing
1707
// this to UTC timezone.
1708
int timezone = getTimezone();
1709    if (timezone == DatatypeConstants.FIELD_UNDEFINED){
1710        timezone = 0;
1711    }
1712    XMLGregorianCalendar JavaDoc gc = this;
1713    if (timezone != 0) {
1714        gc = normalizeToTimezone(this, getTimezone());
1715    }
1716    return gc.getYear() + gc.getMonth() + gc.getDay() +
1717        gc.getHour() + gc.getMinute() + gc.getSecond();
1718    }
1719    
1720    
1721    /**
1722     * <p>Constructs a new XMLGregorianCalendar object by
1723     * parsing its lexical string representation as defined in
1724     * <a HREF="http://www.w3.org/TR/xmlschema-2/#dateTime-order">XML Schema 1.0 Part 2, Section 3.2.[7-14].1,
1725     * <i>Lexical Representation</i>.</a></p>
1726     *
1727     * <p>The string representation may not have any leading and trailing whitespaces.</p>
1728     *
1729     * <p>The parsing is done field by field so that
1730     * the following holds for any lexically correct string x:</p>
1731     * <pre>
1732     * new XMLGregorianCalendar(x).toXMLFormat().equals(x)
1733     * </pre>
1734     * Except for the noted lexical/canonical representation mismatches
1735     * listed in <a HREF="http://www.w3.org/2001/05/xmlschema-errata#e2-45">
1736     * XML Schema 1.0 errata, Section 3.2.7.2</a>.
1737     *
1738     * <p>Returns a non-null valid XMLGregorianCalendar object that holds the value
1739     * indicated by the lexicalRepresentation parameter.</p>
1740     *
1741     * @param lexicalRepresentation Lexical representation of one the 8 XML Schema calendar datatypes.
1742     *
1743     * @return <code>XMLGregorianCalendar</code> created from parsing <code>lexicalRepresentation</code> parameter.
1744     *
1745     * @throws IllegalArgumentException
1746     * If the given string does not conform to the aforementioned
1747     * specification.
1748     * @throws NullPointerException
1749     * If the given string is null.
1750     */

1751    public static XMLGregorianCalendar JavaDoc parse(String JavaDoc lexicalRepresentation) {
1752        
1753        return new XMLGregorianCalendarImpl(lexicalRepresentation);
1754    }
1755
1756    /**
1757     * <p>Return the lexical representation of <code>this</code> instance.
1758     * The format is specified in
1759     * <a HREF="http://www.w3.org/TR/xmlschema-2/#dateTime-order">XML Schema 1.0 Part 2, Section 3.2.[7-14].1,
1760     * <i>Lexical Representation</i>".</a></p>
1761     *
1762     * <p>Specific target lexical representation format is determined by
1763     * {@link #getXMLSchemaType()}.</p>
1764     *
1765     * @return XML, as <code>String</code>, representation of this <code>XMLGregorianCalendar</code>
1766     *
1767     * @throws java.lang.IllegalStateException if the combination of set fields
1768     * does not match one of the eight defined XML Schema builtin date/time datatypes.
1769     */

1770    public String JavaDoc toXMLFormat() {
1771        
1772    QName JavaDoc typekind = getXMLSchemaType();
1773    
1774    String JavaDoc formatString = null;
1775    if (typekind == DatatypeConstants.DATETIME) {
1776        formatString = "%Y-%M-%DT%h:%m:%s"+ "%z";
1777    } else if (typekind == DatatypeConstants.DATE) {
1778        // Fix 4971612: invalid SCCS macro substitution in data string
1779
formatString = "%Y-%M-%D" +"%z";
1780    } else if (typekind == DatatypeConstants.TIME) {
1781        formatString = "%h:%m:%s"+ "%z";
1782    } else if (typekind == DatatypeConstants.GMONTH) {
1783        formatString = "--%M--%z";
1784    } else if (typekind == DatatypeConstants.GDAY) {
1785        // Fix 4971612: invalid SCCS macro substitution in data string
1786
formatString = "---%D" + "%z";
1787    } else if (typekind == DatatypeConstants.GYEAR) {
1788        formatString = "%Y" + "%z";
1789    } else if (typekind == DatatypeConstants.GYEARMONTH) {
1790        // Fix 4971612: invalid SCCS macro substitution in data string
1791
formatString = "%Y-%M" + "%z";
1792    } else if (typekind == DatatypeConstants.GMONTHDAY) {
1793        // Fix 4971612: invalid SCCS macro substitution in data string
1794
formatString = "--%M-%D" +"%z";
1795    }
1796    return format(formatString);
1797    }
1798    
1799    /**
1800     * <p>Return the name of the XML Schema date/time type that this instance
1801     * maps to. Type is computed based on fields that are set.</p>
1802     *
1803     * <table border="2" rules="all" cellpadding="2">
1804     * <thead>
1805     * <tr>
1806     * <th align="center" colspan="7">
1807     * Required fields for XML Schema 1.0 Date/Time Datatypes.<br/>
1808     * <i>(timezone is optional for all date/time datatypes)</i>
1809     * </th>
1810     * </tr>
1811     * </thead>
1812     * <tbody>
1813     * <tr>
1814     * <td>Datatype</td>
1815     * <td>year</td>
1816     * <td>month</td>
1817     * <td>day</td>
1818     * <td>hour</td>
1819     * <td>minute</td>
1820     * <td>second</td>
1821     * </tr>
1822     * <tr>
1823     * <td>{@link DatatypeConstants#DATETIME}</td>
1824     * <td>X</td>
1825     * <td>X</td>
1826     * <td>X</td>
1827     * <td>X</td>
1828     * <td>X</td>
1829     * <td>X</td>
1830     * </tr>
1831     * <tr>
1832     * <td>{@link DatatypeConstants#DATE}</td>
1833     * <td>X</td>
1834     * <td>X</td>
1835     * <td>X</td>
1836     * <td></td>
1837     * <td></td>
1838     * <td></td>
1839     * </tr>
1840     * <tr>
1841     * <td>{@link DatatypeConstants#TIME}</td>
1842     * <td></td>
1843     * <td></td>
1844     * <td></td>
1845     * <td>X</td>
1846     * <td>X</td>
1847     * <td>X</td>
1848     * </tr>
1849     * <tr>
1850     * <td>{@link DatatypeConstants#GYEARMONTH}</td>
1851     * <td>X</td>
1852     * <td>X</td>
1853     * <td></td>
1854     * <td></td>
1855     * <td></td>
1856     * <td></td>
1857     * </tr>
1858     * <tr>
1859     * <td>{@link DatatypeConstants#GMONTHDAY}</td>
1860     * <td></td>
1861     * <td>X</td>
1862     * <td>X</td>
1863     * <td></td>
1864     * <td></td>
1865     * <td></td>
1866     * </tr>
1867     * <tr>
1868     * <td>{@link DatatypeConstants#GYEAR}</td>
1869     * <td>X</td>
1870     * <td></td>
1871     * <td></td>
1872     * <td></td>
1873     * <td></td>
1874     * <td></td>
1875     * </tr>
1876     * <tr>
1877     * <td>{@link DatatypeConstants#GMONTH}</td>
1878     * <td></td>
1879     * <td>X</td>
1880     * <td></td>
1881     * <td></td>
1882     * <td></td>
1883     * <td></td>
1884     * </tr>
1885     * <tr>
1886     * <td>{@link DatatypeConstants#GDAY}</td>
1887     * <td></td>
1888     * <td></td>
1889     * <td>X</td>
1890     * <td></td>
1891     * <td></td>
1892     * <td></td>
1893     * </tr>
1894     * </tbody>
1895     * </table>
1896     *
1897     * @throws java.lang.IllegalStateException if the combination of set fields
1898     * does not match one of the eight defined XML Schema builtin
1899     * date/time datatypes.
1900     * @return One of the following class constants:
1901     * {@link DatatypeConstants#DATETIME},
1902     * {@link DatatypeConstants#TIME},
1903     * {@link DatatypeConstants#DATE},
1904     * {@link DatatypeConstants#GYEARMONTH},
1905     * {@link DatatypeConstants#GMONTHDAY},
1906     * {@link DatatypeConstants#GYEAR},
1907     * {@link DatatypeConstants#GMONTH} or
1908     * {@link DatatypeConstants#GDAY}.
1909     */

1910    public QName JavaDoc getXMLSchemaType() {
1911        
1912        // DATETIME
1913
if (year != DatatypeConstants.FIELD_UNDEFINED
1914            && month != DatatypeConstants.FIELD_UNDEFINED
1915            && day != DatatypeConstants.FIELD_UNDEFINED
1916            && hour != DatatypeConstants.FIELD_UNDEFINED
1917            && minute != DatatypeConstants.FIELD_UNDEFINED
1918            && second != DatatypeConstants.FIELD_UNDEFINED) {
1919            return DatatypeConstants.DATETIME;
1920        }
1921
1922        // DATE
1923
if (year != DatatypeConstants.FIELD_UNDEFINED
1924            && month != DatatypeConstants.FIELD_UNDEFINED
1925            && day != DatatypeConstants.FIELD_UNDEFINED
1926            && hour == DatatypeConstants.FIELD_UNDEFINED
1927            && minute == DatatypeConstants.FIELD_UNDEFINED
1928            && second == DatatypeConstants.FIELD_UNDEFINED) {
1929            return DatatypeConstants.DATE;
1930        }
1931
1932        // TIME
1933
if (year == DatatypeConstants.FIELD_UNDEFINED
1934            && month == DatatypeConstants.FIELD_UNDEFINED
1935            && day == DatatypeConstants.FIELD_UNDEFINED
1936            && hour != DatatypeConstants.FIELD_UNDEFINED
1937            && minute != DatatypeConstants.FIELD_UNDEFINED
1938            && second != DatatypeConstants.FIELD_UNDEFINED) {
1939            return DatatypeConstants.TIME;
1940        }
1941
1942
1943        // GYEARMONTH
1944
if (year != DatatypeConstants.FIELD_UNDEFINED
1945            && month != DatatypeConstants.FIELD_UNDEFINED
1946            && day == DatatypeConstants.FIELD_UNDEFINED
1947            && hour == DatatypeConstants.FIELD_UNDEFINED
1948            && minute == DatatypeConstants.FIELD_UNDEFINED
1949            && second == DatatypeConstants.FIELD_UNDEFINED) {
1950            return DatatypeConstants.GYEARMONTH;
1951        }
1952
1953        // GMONTHDAY
1954
if (year == DatatypeConstants.FIELD_UNDEFINED
1955            && month != DatatypeConstants.FIELD_UNDEFINED
1956            && day != DatatypeConstants.FIELD_UNDEFINED
1957            && hour == DatatypeConstants.FIELD_UNDEFINED
1958            && minute == DatatypeConstants.FIELD_UNDEFINED
1959            && second == DatatypeConstants.FIELD_UNDEFINED) {
1960            return DatatypeConstants.GMONTHDAY;
1961        }
1962
1963        // GYEAR
1964
if (year != DatatypeConstants.FIELD_UNDEFINED
1965            && month == DatatypeConstants.FIELD_UNDEFINED
1966            && day == DatatypeConstants.FIELD_UNDEFINED
1967            && hour == DatatypeConstants.FIELD_UNDEFINED
1968            && minute == DatatypeConstants.FIELD_UNDEFINED
1969            && second == DatatypeConstants.FIELD_UNDEFINED) {
1970            return DatatypeConstants.GYEAR;
1971        }
1972
1973        // GMONTH
1974
if (year == DatatypeConstants.FIELD_UNDEFINED
1975            && month != DatatypeConstants.FIELD_UNDEFINED
1976            && day == DatatypeConstants.FIELD_UNDEFINED
1977            && hour == DatatypeConstants.FIELD_UNDEFINED
1978            && minute == DatatypeConstants.FIELD_UNDEFINED
1979            && second == DatatypeConstants.FIELD_UNDEFINED) {
1980            return DatatypeConstants.GMONTH;
1981        }
1982
1983        // GDAY
1984
if (year == DatatypeConstants.FIELD_UNDEFINED
1985            && month == DatatypeConstants.FIELD_UNDEFINED
1986            && day != DatatypeConstants.FIELD_UNDEFINED
1987            && hour == DatatypeConstants.FIELD_UNDEFINED
1988            && minute == DatatypeConstants.FIELD_UNDEFINED
1989            && second == DatatypeConstants.FIELD_UNDEFINED) {
1990            return DatatypeConstants.GDAY;
1991        }
1992
1993        // unknown
1994
throw new IllegalStateException JavaDoc(
1995            this.getClass().getName()
1996            + "#getXMLSchemaType() :"
1997            + DatatypeMessageFormatter.formatMessage(null, "InvalidXGCFields", null)
1998        );
1999    }
2000
2001    
2002    /**
2003     * Validate instance by <code>getXMLSchemaType()</code> constraints.
2004     * @return true if data values are valid.
2005     */

2006    public boolean isValid() {
2007    // since setters do not allow for invalid values,
2008
// (except for exceptional case of year field of zero),
2009
// no need to check for anything except for constraints
2010
// between fields.
2011

2012    //check if days in month is valid. Can be dependent on leap year.
2013
if (getMonth() == DatatypeConstants.FEBRUARY) {
2014        // years could not be set
2015
int maxDays = DatatypeConstants.FIELD_UNDEFINED;
2016        BigInteger JavaDoc years = getEonAndYear();
2017        if (years != null) {
2018            maxDays = maximumDayInMonthFor(getEonAndYear(), DatatypeConstants.FEBRUARY);
2019        } else {
2020            // year is undefined, allow 29 days
2021
maxDays = 29;
2022        }
2023        if (getDay() > maxDays) {
2024        return false;
2025        }
2026    }
2027
2028    // http://www.w3.org/2001/05/xmlschema-errata#e2-45
2029
if (getHour() == 24) {
2030        if(getMinute() != 0) {
2031        return false;
2032        } else if (getSecond() != 0) {
2033        return false;
2034        }
2035    }
2036
2037    // XML Schema 1.0 specification defines year value of zero as
2038
// invalid. Allow this class to set year field to zero
2039
// since XML Schema 1.0 errata states that lexical zero will
2040
// be allowed in next version and treated as 1 B.C.E.
2041
if (eon == null) {
2042        // optimize check.
2043
if (year == 0) {
2044        return false;
2045        }
2046    } else {
2047        BigInteger JavaDoc yearField = getEonAndYear();
2048        if (yearField != null) {
2049        int result = compareField(yearField, BigInteger.ZERO);
2050        if (result == DatatypeConstants.EQUAL) {
2051            return false;
2052        }
2053        }
2054    }
2055    return true;
2056    }
2057
2058    /**
2059     * <p>Add <code>duration</code> to this instance.<\p>
2060     *
2061     * <p>The computation is specified in
2062     * <a HREF="http://www.w3.org/TR/xmlschema-2/#adding-durations-to-dateTimes">XML Schema 1.0 Part 2, Appendix E,
2063     * <i>Adding durations to dateTimes</i>></a>.
2064     * <a HREF="#datetimefieldsmapping">date/time field mapping table</a>
2065     * defines the mapping from XML Schema 1.0 <code>dateTime</code> fields
2066     * to this class' representation of those fields.</p>
2067     *
2068     * @param duration Duration to add to this <code>XMLGregorianCalendar</code>.
2069     *
2070     * @throws NullPointerException when <code>duration</code> parameter is <code>null</code>.
2071     */

2072    public void add(Duration JavaDoc duration) {
2073        
2074        /*
2075         * Extracted from
2076         * http://www.w3.org/TR/xmlschema-2/#adding-durations-to-dateTimes
2077         * to ensure implemented properly. See spec for definitions of methods
2078         * used in algorithm.
2079         *
2080         * Given a dateTime S and a duration D, specifies how to compute a
2081         * dateTime E where E is the end of the time period with start S and
2082         * duration D i.e. E = S + D.
2083         *
2084         * The following is the precise specification.
2085         * These steps must be followed in the same order.
2086         * If a field in D is not specified, it is treated as if it were zero.
2087         * If a field in S is not specified, it is treated in the calculation
2088         * as if it were the minimum allowed value in that field, however,
2089         * after the calculation is concluded, the corresponding field in
2090         * E is removed (set to unspecified).
2091         *
2092         * Months (may be modified additionally below)
2093             * temp := S[month] + D[month]
2094             * E[month] := modulo(temp, 1, 13)
2095             * carry := fQuotient(temp, 1, 13)
2096         */

2097     
2098        boolean fieldUndefined[] = {
2099            false,
2100            false,
2101            false,
2102            false,
2103            false,
2104            false
2105        };
2106        
2107        int signum = duration.getSign();
2108        
2109        int startMonth = getMonth();
2110        if (startMonth == DatatypeConstants.FIELD_UNDEFINED) {
2111            startMonth = MIN_FIELD_VALUE[MONTH];
2112            fieldUndefined[MONTH] = true;
2113        }
2114        
2115        BigInteger JavaDoc dMonths = sanitize(duration.getField(DatatypeConstants.MONTHS), signum);
2116        BigInteger JavaDoc temp = BigInteger.valueOf((long) startMonth).add(dMonths);
2117        setMonth(temp.subtract(BigInteger.ONE).mod(TWELVE).intValue() + 1);
2118        BigInteger JavaDoc carry =
2119            new BigDecimal JavaDoc(temp.subtract(BigInteger.ONE)).divide(new BigDecimal JavaDoc(TWELVE), BigDecimal.ROUND_FLOOR).toBigInteger();
2120
2121         /* Years (may be modified additionally below)
2122          * E[year] := S[year] + D[year] + carry
2123          */

2124        BigInteger JavaDoc startYear = getEonAndYear();
2125        if (startYear == null) {
2126            fieldUndefined[YEAR] = true;
2127            startYear = BigInteger.ZERO;
2128        }
2129        BigInteger JavaDoc dYears = sanitize(duration.getField(DatatypeConstants.YEARS), signum);
2130        BigInteger JavaDoc endYear = startYear.add(dYears).add(carry);
2131        setYear(endYear);
2132
2133        /* Zone
2134             * E[zone] := S[zone]
2135         *
2136         * no-op since adding to this, not to a new end point.
2137         */

2138    
2139         /* Seconds
2140          * temp := S[second] + D[second]
2141          * E[second] := modulo(temp, 60)
2142          * carry := fQuotient(temp, 60)
2143          */

2144        BigDecimal JavaDoc startSeconds;
2145        if (getSecond() == DatatypeConstants.FIELD_UNDEFINED) {
2146            fieldUndefined[SECOND] = true;
2147            startSeconds = DECIMAL_ZERO;
2148        } else {
2149            // seconds + fractionalSeconds
2150
startSeconds = getSeconds();
2151        }
2152
2153        // Duration seconds is SECONDS + FRACTIONALSECONDS.
2154
BigDecimal JavaDoc dSeconds = DurationImpl.sanitize((BigDecimal JavaDoc) duration.getField(DatatypeConstants.SECONDS), signum);
2155        BigDecimal JavaDoc tempBD = startSeconds.add(dSeconds);
2156        BigDecimal JavaDoc fQuotient =
2157            new BigDecimal JavaDoc(new BigDecimal JavaDoc(tempBD.toBigInteger()).divide(DECIMAL_SIXTY, BigDecimal.ROUND_FLOOR).toBigInteger());
2158        BigDecimal JavaDoc endSeconds = tempBD.subtract(fQuotient.multiply(DECIMAL_SIXTY));
2159
2160        carry = fQuotient.toBigInteger();
2161        setSecond(endSeconds.intValue());
2162        BigDecimal JavaDoc tempFracSeconds = endSeconds.subtract(new BigDecimal JavaDoc(BigInteger.valueOf((long) getSecond())));
2163        if (tempFracSeconds.compareTo(DECIMAL_ZERO) < 0) {
2164            setFractionalSecond(DECIMAL_ONE.add(tempFracSeconds));
2165            if (getSecond() == 0) {
2166                setSecond(59);
2167                carry = carry.subtract(BigInteger.ONE);
2168            } else {
2169                setSecond(getSecond() - 1);
2170            }
2171        } else {
2172            setFractionalSecond(tempFracSeconds);
2173        }
2174 
2175        /* Minutes
2176             * temp := S[minute] + D[minute] + carry
2177             * E[minute] := modulo(temp, 60)
2178             * carry := fQuotient(temp, 60)
2179         */

2180        int startMinutes = getMinute();
2181        if (startMinutes == DatatypeConstants.FIELD_UNDEFINED) {
2182            fieldUndefined[MINUTE] = true;
2183            startMinutes = MIN_FIELD_VALUE[MINUTE];
2184        }
2185        BigInteger JavaDoc dMinutes = sanitize(duration.getField(DatatypeConstants.MINUTES), signum);
2186        
2187        temp = BigInteger.valueOf(startMinutes).add(dMinutes).add(carry);
2188        setMinute(temp.mod(SIXTY).intValue());
2189        carry = new BigDecimal JavaDoc(temp).divide(DECIMAL_SIXTY, BigDecimal.ROUND_FLOOR).toBigInteger();
2190
2191        /* Hours
2192             * temp := S[hour] + D[hour] + carry
2193             * E[hour] := modulo(temp, 24)
2194             * carry := fQuotient(temp, 24)
2195         */

2196        int startHours = getHour();
2197        if (startHours == DatatypeConstants.FIELD_UNDEFINED) {
2198            fieldUndefined[HOUR] = true;
2199            startHours = MIN_FIELD_VALUE[HOUR];
2200        }
2201        BigInteger JavaDoc dHours = sanitize(duration.getField(DatatypeConstants.HOURS), signum);
2202        
2203        temp = BigInteger.valueOf(startHours).add(dHours).add(carry);
2204        setHour(temp.mod(TWENTY_FOUR).intValue());
2205        carry = new BigDecimal JavaDoc(temp).divide(new BigDecimal JavaDoc(TWENTY_FOUR), BigDecimal.ROUND_FLOOR).toBigInteger();
2206    
2207        /* Days
2208         * if S[day] > maximumDayInMonthFor(E[year], E[month])
2209         * + tempDays := maximumDayInMonthFor(E[year], E[month])
2210         * else if S[day] < 1
2211         * + tempDays := 1
2212         * else
2213         * + tempDays := S[day]
2214         * E[day] := tempDays + D[day] + carry
2215         * START LOOP
2216         * + IF E[day] < 1
2217         * # E[day] := E[day] +
2218         * maximumDayInMonthFor(E[year], E[month] - 1)
2219         * # carry := -1
2220         * + ELSE IF E[day] > maximumDayInMonthFor(E[year], E[month])
2221         * # E[day] :=
2222         * E[day] - maximumDayInMonthFor(E[year], E[month])
2223         * # carry := 1
2224         * + ELSE EXIT LOOP
2225         * + temp := E[month] + carry
2226         * + E[month] := modulo(temp, 1, 13)
2227         * + E[year] := E[year] + fQuotient(temp, 1, 13)
2228         * + GOTO START LOOP
2229         */

2230        BigInteger JavaDoc tempDays;
2231        int startDay = getDay();
2232        if (startDay == DatatypeConstants.FIELD_UNDEFINED) {
2233            fieldUndefined[DAY] = true;
2234            startDay = MIN_FIELD_VALUE[DAY];
2235        }
2236        BigInteger JavaDoc dDays = sanitize(duration.getField(DatatypeConstants.DAYS), signum);
2237        int maxDayInMonth = maximumDayInMonthFor(getEonAndYear(), getMonth());
2238        if (startDay > maxDayInMonth) {
2239                tempDays = BigInteger.valueOf(maxDayInMonth);
2240        } else if (startDay < 1) {
2241            tempDays = BigInteger.ONE;
2242        } else {
2243            tempDays = BigInteger.valueOf(startDay);
2244        }
2245        BigInteger JavaDoc endDays = tempDays.add(dDays).add(carry);
2246        int monthCarry;
2247        int intTemp;
2248        while (true) {
2249            if (endDays.compareTo(BigInteger.ONE) < 0) {
2250                // calculate days in previous month, watch for month roll over
2251
BigInteger JavaDoc mdimf = null;
2252                if (month >= 2) {
2253                    mdimf = BigInteger.valueOf(maximumDayInMonthFor(getEonAndYear(), getMonth() - 1));
2254                } else {
2255                    // roll over to December of previous year
2256
mdimf = BigInteger.valueOf(maximumDayInMonthFor(getEonAndYear().subtract(BigInteger.valueOf((long) 1)), 12));
2257                }
2258                endDays = endDays.add(mdimf);
2259                monthCarry = -1;
2260            } else if (endDays.compareTo(BigInteger.valueOf(maximumDayInMonthFor(getEonAndYear(), getMonth()))) > 0) {
2261                endDays = endDays.add(BigInteger.valueOf(-maximumDayInMonthFor(getEonAndYear(), getMonth())));
2262                monthCarry = 1;
2263            } else {
2264                break;
2265            }
2266
2267            intTemp = getMonth() + monthCarry;
2268            int endMonth = (intTemp - 1) % (13 - 1);
2269            int quotient;
2270            if (endMonth < 0) {
2271                endMonth = (13 - 1) + endMonth + 1;
2272                quotient = new BigDecimal JavaDoc(intTemp - 1).divide(new BigDecimal JavaDoc(TWELVE), BigDecimal.ROUND_UP).intValue();
2273            } else {
2274                quotient = (intTemp - 1) / (13 - 1);
2275                endMonth += 1;
2276            }
2277            setMonth(endMonth);
2278            if (quotient != 0) {
2279                setYear(getEonAndYear().add(BigInteger.valueOf(quotient)));
2280            }
2281        }
2282        setDay(endDays.intValue());
2283    
2284        // set fields that where undefined before this addition, back to undefined.
2285
for (int i = YEAR; i <= SECOND; i++) {
2286            if (fieldUndefined[i]) {
2287                switch (i) {
2288                case YEAR:
2289                    setYear(DatatypeConstants.FIELD_UNDEFINED);
2290                    break;
2291                case MONTH:
2292                    setMonth(DatatypeConstants.FIELD_UNDEFINED);
2293                    break;
2294                case DAY:
2295                    setDay(DatatypeConstants.FIELD_UNDEFINED);
2296                    break;
2297                case HOUR:
2298                    setHour(DatatypeConstants.FIELD_UNDEFINED);
2299                    break;
2300                case MINUTE:
2301                    setMinute(DatatypeConstants.FIELD_UNDEFINED);
2302                    break;
2303                case SECOND:
2304                    setSecond(DatatypeConstants.FIELD_UNDEFINED);
2305                    setFractionalSecond(null);
2306                    break;
2307                }
2308            }
2309        }
2310    }
2311
2312    private static final BigInteger JavaDoc FOUR = BigInteger.valueOf(4);
2313    private static final BigInteger JavaDoc HUNDRED = BigInteger.valueOf(100);
2314    private static final BigInteger JavaDoc FOUR_HUNDRED = BigInteger.valueOf(400);
2315    private static final BigInteger JavaDoc SIXTY = BigInteger.valueOf(60);
2316    private static final BigInteger JavaDoc TWENTY_FOUR = BigInteger.valueOf(24);
2317    private static final BigInteger JavaDoc TWELVE = BigInteger.valueOf(12);
2318    private static final BigDecimal JavaDoc DECIMAL_ZERO = new BigDecimal JavaDoc("0");
2319    private static final BigDecimal JavaDoc DECIMAL_ONE = new BigDecimal JavaDoc("1");
2320    private static final BigDecimal JavaDoc DECIMAL_SIXTY = new BigDecimal JavaDoc("60");
2321
2322
2323    private static int daysInMonth[] = { 0, // XML Schema months start at 1.
2324
31, 28, 31, 30, 31, 30,
2325                                       31, 31, 30, 31, 30, 31};
2326
2327    private static int maximumDayInMonthFor(BigInteger JavaDoc year, int month) {
2328    if (month != DatatypeConstants.FEBRUARY) {
2329        return daysInMonth[month];
2330    } else {
2331        if (year.mod(FOUR_HUNDRED).equals(BigInteger.ZERO) ||
2332        (!year.mod(HUNDRED).equals(BigInteger.ZERO) &&
2333         year.mod(FOUR).equals(BigInteger.ZERO))) {
2334        // is a leap year.
2335
return 29;
2336        } else {
2337        return daysInMonth[month];
2338        }
2339    }
2340    }
2341
2342    private static int maximumDayInMonthFor(int year, int month) {
2343    if (month != DatatypeConstants.FEBRUARY) {
2344        return daysInMonth[month];
2345    } else {
2346        if ( ((year %400) == 0) ||
2347         ( ((year % 100) != 0) && ((year % 4) == 0))) {
2348        // is a leap year.
2349
return 29;
2350        } else {
2351        return daysInMonth[DatatypeConstants.FEBRUARY];
2352        }
2353    }
2354    }
2355
2356    /**
2357     * <p>Convert <code>this</code> to <code>java.util.GregorianCalendar</code>.</p>
2358     *
2359     * <p>When <code>this</code> instance has an undefined field, this
2360     * conversion relies on the <code>java.util.GregorianCalendar</code> default
2361     * for its corresponding field. A notable difference between
2362     * XML Schema 1.0 date/time datatypes and <code>java.util.GregorianCalendar</code>
2363     * is that Timezone value is optional for date/time datatypes and it is
2364     * a required field for <code>java.util.GregorianCalendar</code>. See javadoc
2365     * for <code>java.util.TimeZone.getDefault()</code> on how the default
2366     * is determined. To explicitly specify the <code>TimeZone</code>
2367     * instance, see
2368     * {@link #toGregorianCalendar(TimeZone, Locale, XMLGregorianCalendar)}.</p>
2369     *
2370     * <table border="2" rules="all" cellpadding="2">
2371     * <thead>
2372     * <tr>
2373     * <th align="center" colspan="2">
2374     * Field by Field Conversion from this class to
2375     * <code>java.util.GregorianCalendar</code>
2376     * </th>
2377     * </tr>
2378     * </thead>
2379     * <tbody>
2380     * <tr>
2381     * <th><code>java.util.GregorianCalendar</code> field</th>
2382     * <th><code>javax.xml.datatype.XMLGregorianCalendar</code> field</th>
2383     * </tr>
2384     * <tr>
2385     * <th><code>ERA</code></th>
2386     * <th>{@link #getEonAndYear()}<code>.signum() < 0 ? GregorianCalendar.BC : GregorianCalendar.AD</code></th>
2387     * </tr>
2388     * <tr>
2389     * <th><code>YEAR</code></th>
2390     * <th>{@link #getEonAndYear()}<code>.abs().intValue()</code><i>*</i></th>
2391     * </tr>
2392     * <tr>
2393     * <th><code>MONTH</code></th>
2394     * <th>{@link #getMonth()}<code> - 1</code></th>
2395     * </tr>
2396     * <tr>
2397     * <th><code>DAY_OF_MONTH</code></th>
2398     * <th>{@link #getDay()}</th>
2399     * </tr>
2400     * <tr>
2401     * <th><code>AM_PM</code></th>
2402     * <th>{@link #getHour()} < 12 : Calendar.AM : Calendar.PM</th>
2403     * </tr>
2404     * <tr>
2405     * <th><code>HOUR_OF_DAY</code></th>
2406     * <th>{@link #getHour()}</th>
2407     * </tr>
2408     * <tr>
2409     * <th><code>MINUTE</code></th>
2410     * <th>{@link #getMinute()}</th>
2411     * </tr>
2412     * <tr>
2413     * <th><code>SECOND</code></th>
2414     * <th>{@link #getSecond()}</th>
2415     * </tr>
2416     * <tr>
2417     * <th><code>MILLISECOND</code></th>
2418     * <th>get millisecond order from {@link #getFractionalSecond()}<i>*</i> </th>
2419     * </tr>
2420     * <tr>
2421     * <th><code>GregorianCalendar.setTimeZone(TimeZone)</code></th>
2422     * <th>{@link #getTimezone()} formatted into Custom timezone id</th>
2423     * </tr>
2424     * </tbody>
2425     * </table>
2426     * <i>*</i> designates possible loss of precision during the conversion due
2427     * to source datatype having higer precison than target datatype.
2428     *
2429     * <p>To ensure consistency in conversion implementations, the new
2430     * <code>GregorianCalendar</code> should be instantiated in following
2431     * manner.
2432     * <ul>
2433     * <li>Using <code>timeZone</code> value as defined above, create a new
2434     * <code>java.util.GregorianCalendar(timeZone,Locale.getDefault())</code>.
2435     * </li>
2436     * <li>Initialize all GregorianCalendar fields by calling {(@link GegorianCalendar#clear()}.</li>
2437     * <li>Obtain a pure Gregorian Calendar by invoking
2438     * <code>GregorianCalendar.setGregorianChange(
2439     * new Date(Long.MIN_VALUE))</code>.</li>
2440     * <li>Its fields ERA, YEAR, MONTH, DAY_OF_MONTH, HOUR_OF_DAY,
2441     * MINUTE, SECOND and MILLISECOND are set using the method
2442     * <code>Calendar.set(int,int)</code></li>
2443     * </ul>
2444     * </p>
2445     *
2446     * @see #toGregorianCalendar(java.util.TimeZone, java.util.Locale, XMLGregorianCalendar)
2447     */

2448    public java.util.GregorianCalendar JavaDoc toGregorianCalendar() {
2449
2450    GregorianCalendar JavaDoc result = null;
2451    final int DEFAULT_TIMEZONE_OFFSET = DatatypeConstants.FIELD_UNDEFINED;
2452    TimeZone JavaDoc tz = getTimeZone(DEFAULT_TIMEZONE_OFFSET);
2453    Locale JavaDoc locale = java.util.Locale.getDefault();
2454
2455    result = new GregorianCalendar JavaDoc(tz, locale);
2456    result.clear();
2457    result.setGregorianChange(PURE_GREGORIAN_CHANGE);
2458    
2459    // if year( and eon) are undefined, leave default Calendar values
2460
BigInteger JavaDoc year = getEonAndYear();
2461    if (year != null) {
2462        result.set(Calendar.ERA, year.signum() == -1 ? GregorianCalendar.BC : GregorianCalendar.AD);
2463        result.set(Calendar.YEAR, year.abs().intValue());
2464    }
2465    
2466    // only set month if it is set
2467
if (month != DatatypeConstants.FIELD_UNDEFINED) {
2468        // Calendar.MONTH is zero based while XMLGregorianCalendar month field is not.
2469
result.set(Calendar.MONTH, month - 1);
2470    }
2471    
2472    // only set day if it is set
2473
if (day != DatatypeConstants.FIELD_UNDEFINED) {
2474        result.set(Calendar.DAY_OF_MONTH, day);
2475    }
2476    
2477    // only set hour if it is set
2478
if (hour != DatatypeConstants.FIELD_UNDEFINED) {
2479        result.set(Calendar.HOUR_OF_DAY, hour);
2480    }
2481    
2482    // only set minute if it is set
2483
if (minute != DatatypeConstants.FIELD_UNDEFINED) {
2484        result.set(Calendar.MINUTE, minute);
2485    }
2486    
2487    // only set second if it is set
2488
if (second != DatatypeConstants.FIELD_UNDEFINED) {
2489        result.set(Calendar.SECOND, second);
2490    }
2491    
2492    // only set millisend if it is set
2493
if (fractionalSecond != null) {
2494        result.set(Calendar.MILLISECOND, getMillisecond());
2495    }
2496
2497    return result;
2498    }
2499
2500    /**
2501     * <p>Convert <code>this</code> along with provided parameters
2502     * to <code>java.util.GregorianCalendar</code> instance.</p>
2503     *
2504     * <p> Since XML Schema 1.0 date/time datetypes has no concept of
2505     * timezone ids or daylight savings timezone ids, this conversion operation
2506     * allows the user to explicitly specify one with
2507     * <code>timezone</code> parameter.</p>
2508     *
2509     * <p>To compute the return value's <code>TimeZone</code> field,
2510     * <ul>
2511     * <li>when parameter <code>timeZone</code> is non-null,
2512     * it is the timezone field.</li>
2513     * <li>else when <code>this.getTimezone() != DatatypeConstants.FIELD_UNDEFINED</code>,
2514     * create a <code>java.util.TimeZone</code> with a custom timezone id
2515     * using the <code>this.getTimezone()</code>.</li>
2516     * <li>else when <code>defaults.getTimezone() != DatatypeConstants.FIELD_UNDEFINED</code>,
2517     * create a <code>java.util.TimeZone</code> with a custom timezone id
2518     * using <code>defaults.getTimezone()</code>.</li>
2519     * <li>else use the <code>GregorianCalendar</code> default timezone value
2520     * for the host is definedas specified by
2521     * <code>java.util.TimeZone.getDefault()</code>.</li></p>
2522     *
2523     * <p>To ensure consistency in conversion implementations, the new
2524     * <code>GregorianCalendar</code> should be instantiated in following
2525     * manner.
2526     * <ul>
2527     * <li>Create a new <code>java.util.GregorianCalendar(TimeZone,
2528     * Locale)</code> with TimeZone set as specified above and the
2529     * <code>Locale</code> parameter.
2530     * </li>
2531     * <li>Initialize all GregorianCalendar fields by calling {(@link GegorianCalendar#clear()}.</li>
2532     * <li>Obtain a pure Gregorian Calendar by invoking
2533     * <code>GregorianCalendar.setGregorianChange(
2534     * new Date(Long.MIN_VALUE))</code>.</li>
2535     * <li>Its fields ERA, YEAR, MONTH, DAY_OF_MONTH, HOUR_OF_DAY,
2536     * MINUTE, SECOND and MILLISECOND are set using the method
2537     * <code>Calendar.set(int,int)</code></li>
2538     * </ul>
2539     *
2540     * @param timezone provide Timezone. <code>null</code> is a legal value.
2541     * @param aLocale provide explicit Locale. Use default GregorianCalendar locale if
2542     * value is <code>null</code>.
2543     * @param defaults provide default field values to use when corresponding
2544     * field for this instance is DatatypeConstants.FIELD_UNDEFINED or null.
2545     * If <code>defaults</code>is <code>null</code> or a field
2546     * within the specified <code>defaults</code> is undefined,
2547     * just use <code>java.util.GregorianCalendar</code> defaults.
2548     * @return a java.util.GregorianCalendar conversion of this instance.
2549     *
2550     * @see #LEAP_YEAR_DEFAULT
2551     */

2552    public GregorianCalendar JavaDoc toGregorianCalendar(java.util.TimeZone JavaDoc timezone,
2553                     java.util.Locale JavaDoc aLocale,
2554                     XMLGregorianCalendar JavaDoc defaults) {
2555    GregorianCalendar JavaDoc result = null;
2556    TimeZone JavaDoc tz = timezone;
2557    if (tz == null) {
2558        int defaultZoneoffset = DatatypeConstants.FIELD_UNDEFINED;
2559        if (defaults != null) {
2560            defaultZoneoffset = defaults.getTimezone();
2561        }
2562        tz = getTimeZone(defaultZoneoffset);
2563    }
2564    if (aLocale == null) {
2565        aLocale = java.util.Locale.getDefault();
2566    }
2567    result = new GregorianCalendar JavaDoc(tz, aLocale);
2568    result.clear();
2569    result.setGregorianChange(PURE_GREGORIAN_CHANGE);
2570
2571    // if year( and eon) are undefined, leave default Calendar values
2572
BigInteger JavaDoc year = getEonAndYear();
2573    if (year != null) {
2574        result.set(Calendar.ERA, year.signum() == -1 ? GregorianCalendar.BC : GregorianCalendar.AD);
2575        result.set(Calendar.YEAR, year.abs().intValue());
2576    } else {
2577        // use default if set
2578
BigInteger JavaDoc defaultYear = (defaults != null) ? defaults.getEonAndYear() : null;
2579        if (defaultYear != null) {
2580            result.set(Calendar.ERA, defaultYear.signum() == -1 ? GregorianCalendar.BC : GregorianCalendar.AD);
2581            result.set(Calendar.YEAR, defaultYear.abs().intValue());
2582        }
2583    }
2584    
2585    // only set month if it is set
2586
if (month != DatatypeConstants.FIELD_UNDEFINED) {
2587        // Calendar.MONTH is zero based while XMLGregorianCalendar month field is not.
2588
result.set(Calendar.MONTH, month - 1);
2589    } else {
2590        // use default if set
2591
int defaultMonth = (defaults != null) ? defaults.getMonth() : DatatypeConstants.FIELD_UNDEFINED;
2592        if (defaultMonth != DatatypeConstants.FIELD_UNDEFINED) {
2593            // Calendar.MONTH is zero based while XMLGregorianCalendar month field is not.
2594
result.set(Calendar.MONTH, defaultMonth - 1);
2595        }
2596    }
2597        
2598    // only set day if it is set
2599
if (day != DatatypeConstants.FIELD_UNDEFINED) {
2600        result.set(Calendar.DAY_OF_MONTH, day);
2601    } else {
2602        // use default if set
2603
int defaultDay = (defaults != null) ? defaults.getDay() : DatatypeConstants.FIELD_UNDEFINED;
2604        if (defaultDay != DatatypeConstants.FIELD_UNDEFINED) {
2605            result.set(Calendar.DAY_OF_MONTH, defaultDay);
2606        }
2607    }
2608    
2609    // only set hour if it is set
2610
if (hour != DatatypeConstants.FIELD_UNDEFINED) {
2611        result.set(Calendar.HOUR_OF_DAY, hour);
2612    } else {
2613        // use default if set
2614
int defaultHour = (defaults != null) ? defaults.getHour() : DatatypeConstants.FIELD_UNDEFINED;
2615        if (defaultHour != DatatypeConstants.FIELD_UNDEFINED) {
2616            result.set(Calendar.HOUR_OF_DAY, defaultHour);
2617        }
2618    }
2619    
2620    // only set minute if it is set
2621
if (minute != DatatypeConstants.FIELD_UNDEFINED) {
2622        result.set(Calendar.MINUTE, minute);
2623    } else {
2624        // use default if set
2625
int defaultMinute = (defaults != null) ? defaults.getMinute() : DatatypeConstants.FIELD_UNDEFINED;
2626        if (defaultMinute != DatatypeConstants.FIELD_UNDEFINED) {
2627            result.set(Calendar.MINUTE, defaultMinute);
2628        }
2629    }
2630    
2631    // only set second if it is set
2632
if (second != DatatypeConstants.FIELD_UNDEFINED) {
2633        result.set(Calendar.SECOND, second);
2634    } else {
2635        // use default if set
2636
int defaultSecond = (defaults != null) ? defaults.getSecond() : DatatypeConstants.FIELD_UNDEFINED;
2637        if (defaultSecond != DatatypeConstants.FIELD_UNDEFINED) {
2638            result.set(Calendar.SECOND, defaultSecond);
2639        }
2640    }
2641    
2642    // only set millisend if it is set
2643
if (fractionalSecond != null) {
2644        result.set(Calendar.MILLISECOND, getMillisecond());
2645    } else {
2646        // use default if set
2647
BigDecimal JavaDoc defaultFractionalSecond = (defaults != null) ? defaults.getFractionalSecond() : null;
2648        if (defaultFractionalSecond != null) {
2649            result.set(Calendar.MILLISECOND, defaults.getMillisecond());
2650        }
2651    }
2652
2653    return result;
2654    }
2655
2656    /**
2657     * <p>Returns a <code>java.util.TimeZone</code> for this class.</p>
2658     *
2659     * <p>If timezone field is defined for this instance,
2660     * returns TimeZone initialized with custom timezone id
2661     * of zoneoffset. If timezone field is undefined,
2662     * try the defaultZoneoffset that was passed in.
2663     * If defaultZoneoffset is DatatypeConstants.FIELD_UNDEFINED, return
2664     * default timezone for this host.
2665     * (Same default as java.util.GregorianCalendar).</p>
2666     *
2667     * @param defaultZoneoffset default zoneoffset if this zoneoffset is
2668     * {@link DatatypeConstants#FIELD_UNDEFINED}.
2669     *
2670     * @return TimeZone for this.
2671     */

2672    public TimeZone JavaDoc getTimeZone(int defaultZoneoffset) {
2673    TimeZone JavaDoc result = null;
2674    int zoneoffset = getTimezone();
2675
2676    if (zoneoffset == DatatypeConstants.FIELD_UNDEFINED) {
2677        zoneoffset = defaultZoneoffset;
2678    }
2679    if (zoneoffset == DatatypeConstants.FIELD_UNDEFINED) {
2680        result = TimeZone.getDefault();
2681    } else {
2682        // zoneoffset is in minutes. Convert to custom timezone id format.
2683
char sign = zoneoffset < 0 ? '-' : '+';
2684        if (sign == '-') {
2685        zoneoffset = -zoneoffset;
2686        }
2687        int hour = zoneoffset / 60;
2688        int minutes = zoneoffset - (hour * 60);
2689        
2690        // Javadoc for java.util.TimeZone documents max length
2691
// for customTimezoneId is 8 when optional ':' is not used.
2692
// Format is
2693
// "GMT" ('-'|''+') (digit digit?) (digit digit)?
2694
// hour minutes
2695
StringBuffer JavaDoc customTimezoneId = new StringBuffer JavaDoc(8);
2696        customTimezoneId.append("GMT");
2697        customTimezoneId.append(sign);
2698        customTimezoneId.append(hour);
2699        if (minutes != 0) {
2700        customTimezoneId.append(minutes);
2701        }
2702        result = TimeZone.getTimeZone(customTimezoneId.toString());
2703    }
2704    return result;
2705    }
2706    
2707    /**
2708     * <p>Creates and returns a copy of this object.</p>
2709     *
2710     * @return copy of this <code>Object</code>
2711     */

2712   public Object JavaDoc clone() {
2713        // Both this.eon and this.fractionalSecond are instances
2714
// of immutable classes, so they do not need to be cloned.
2715
return new XMLGregorianCalendarImpl(getEonAndYear(),
2716                        this.month, this.day,
2717            this.hour, this.minute, this.second,
2718            this.fractionalSecond,
2719            this.timezone);
2720    }
2721
2722    /**
2723     * <p>Unset all fields to undefined.</p>
2724     *
2725     * <p>Set all int fields to {@link DatatypeConstants#FIELD_UNDEFINED} and reference fields
2726     * to null.</p>
2727     */

2728    public void clear() {
2729    eon = null;
2730    year = DatatypeConstants.FIELD_UNDEFINED;
2731    month = DatatypeConstants.FIELD_UNDEFINED;
2732    day = DatatypeConstants.FIELD_UNDEFINED;
2733    timezone = DatatypeConstants.FIELD_UNDEFINED; // in minutes
2734
hour = DatatypeConstants.FIELD_UNDEFINED;
2735    minute = DatatypeConstants.FIELD_UNDEFINED;
2736    second = DatatypeConstants.FIELD_UNDEFINED;
2737    fractionalSecond = null;
2738    }
2739
2740    public void setMillisecond(int millisecond) {
2741    if (millisecond == DatatypeConstants.FIELD_UNDEFINED) {
2742        fractionalSecond = null;
2743    } else {
2744        checkFieldValueConstraint(MILLISECOND, millisecond);
2745        fractionalSecond = new BigDecimal JavaDoc((long) millisecond).movePointLeft(3);
2746    }
2747    }
2748
2749    public void setFractionalSecond(BigDecimal JavaDoc fractional) {
2750    if (fractional != null) {
2751        if ((fractional.compareTo(DECIMAL_ZERO) < 0) ||
2752        (fractional.compareTo(DECIMAL_ONE) > 0)) {
2753        throw new IllegalArgumentException JavaDoc(DatatypeMessageFormatter.formatMessage(null,
2754            "InvalidFractional", new Object JavaDoc[]{fractional}));
2755        }
2756    }
2757    this.fractionalSecond = fractional;
2758    }
2759
2760    private final class Parser {
2761        private final String JavaDoc format;
2762        private final String JavaDoc value;
2763
2764        private final int flen;
2765        private final int vlen;
2766
2767        private int fidx;
2768        private int vidx;
2769
2770        private Parser(String JavaDoc format, String JavaDoc value) {
2771            this.format = format;
2772            this.value = value;
2773            this.flen = format.length();
2774            this.vlen = value.length();
2775        }
2776        
2777        /**
2778         * <p>Parse a formated <code>String</code> into an <code>XMLGregorianCalendar</code>.</p>
2779         *
2780         * <p>If <code>String</code> is not formated as a legal <code>XMLGregorianCalendar</code> value,
2781         * an <code>IllegalArgumentException</code> is thrown.</p>
2782         *
2783         * @throws IllegalArgumentException If <code>String</code> is not formated as a legal <code>XMLGregorianCalendar</code> value.
2784         */

2785        public void parse() throws IllegalArgumentException JavaDoc {
2786            while (fidx < flen) {
2787                char fch = format.charAt(fidx++);
2788
2789                if (fch != '%') { // not a meta character
2790
skip(fch);
2791                    continue;
2792                }
2793
2794                // seen meta character. we don't do error check against the format
2795
switch (format.charAt(fidx++)) {
2796                    case 'Y' : // year
2797
setYear(parseBigInteger(4));
2798                        break;
2799
2800                    case 'M' : // month
2801
setMonth(parseInt(2, 2));
2802                        break;
2803
2804                    case 'D' : // days
2805
setDay(parseInt(2, 2));
2806                        break;
2807
2808                    case 'h' : // hours
2809
setHour(parseInt(2, 2));
2810                        break;
2811
2812                    case 'm' : // minutes
2813
setMinute(parseInt(2, 2));
2814                        break;
2815
2816                    case 's' : // parse seconds.
2817
setSecond(parseInt(2, 2));
2818
2819                        if (peek() == '.') {
2820                setFractionalSecond(parseBigDecimal());
2821                        }
2822                        break;
2823
2824                    case 'z' : // time zone. missing, 'Z', or [+-]nn:nn
2825
char vch = peek();
2826                        if (vch == 'Z') {
2827                            vidx++;
2828                            setTimezone(0);
2829                        } else if (vch == '+' || vch == '-') {
2830                            vidx++;
2831                            int h = parseInt(2, 2);
2832                            skip(':');
2833                            int m = parseInt(2, 2);
2834                            setTimezone((h * 60 + m) * (vch == '+' ? 1 : -1));
2835                        }
2836            
2837                        break;
2838
2839                    default :
2840                        // illegal meta character. impossible.
2841
throw new InternalError JavaDoc();
2842                }
2843            }
2844
2845            if (vidx != vlen) {
2846                // some tokens are left in the input
2847
throw new IllegalArgumentException JavaDoc(value); //,vidx);
2848
}
2849        }
2850        
2851        private char peek() throws IllegalArgumentException JavaDoc {
2852            if (vidx == vlen) {
2853                return (char) -1;
2854            }
2855            return value.charAt(vidx);
2856        }
2857        
2858        private char read() throws IllegalArgumentException JavaDoc {
2859            if (vidx == vlen) {
2860                throw new IllegalArgumentException JavaDoc(value); //,vidx);
2861
}
2862            return value.charAt(vidx++);
2863        }
2864        
2865        private void skip(char ch) throws IllegalArgumentException JavaDoc {
2866            if (read() != ch) {
2867                throw new IllegalArgumentException JavaDoc(value); //,vidx-1);
2868
}
2869        }
2870        
2871        private int parseInt(int minDigits, int maxDigits)
2872            throws IllegalArgumentException JavaDoc {
2873            int vstart = vidx;
2874            while (isDigit(peek()) && (vidx - vstart) <= maxDigits) {
2875                vidx++;
2876            }
2877            if ((vidx - vstart) < minDigits) {
2878                // we are expecting more digits
2879
throw new IllegalArgumentException JavaDoc(value); //,vidx);
2880
}
2881
2882            // NumberFormatException is IllegalArgumentException
2883
// try {
2884
return Integer.parseInt(value.substring(vstart, vidx));
2885            // } catch( NumberFormatException e ) {
2886
// // if the value is too long for int, NumberFormatException is thrown
2887
// throw new IllegalArgumentException(value,vstart);
2888
// }
2889
}
2890
2891        private BigInteger JavaDoc parseBigInteger(int minDigits)
2892            throws IllegalArgumentException JavaDoc {
2893            int vstart = vidx;
2894
2895        // skip leading negative, if it exists
2896
if (peek() == '-') {
2897        vidx++;
2898        }
2899            while (isDigit(peek())) {
2900                vidx++;
2901            }
2902            if ((vidx - vstart) < minDigits) {
2903                // we are expecting more digits
2904
throw new IllegalArgumentException JavaDoc(value); //,vidx);
2905
}
2906
2907            return new BigInteger JavaDoc(value.substring(vstart, vidx));
2908        }
2909
2910        private BigDecimal JavaDoc parseBigDecimal()
2911            throws IllegalArgumentException JavaDoc {
2912            int vstart = vidx;
2913
2914        if (peek() == '.') {
2915        vidx++;
2916        } else {
2917                throw new IllegalArgumentException JavaDoc(value);
2918        }
2919            while (isDigit(peek())) {
2920                vidx++;
2921            }
2922            return new BigDecimal JavaDoc(value.substring(vstart, vidx));
2923        }
2924    }
2925
2926    private static boolean isDigit(char ch) {
2927        return '0' <= ch && ch <= '9';
2928    }
2929
2930    private String JavaDoc format( String JavaDoc format ) {
2931        StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
2932        int fidx=0,flen=format.length();
2933        
2934        while(fidx<flen) {
2935            char fch = format.charAt(fidx++);
2936            if(fch!='%') {// not a meta char
2937
buf.append(fch);
2938                continue;
2939            }
2940            
2941            switch(format.charAt(fidx++)) {
2942            case 'Y':
2943                printNumber(buf,getEonAndYear(), 4);
2944                break;
2945            case 'M':
2946                printNumber(buf,getMonth(),2);
2947                break;
2948            case 'D':
2949                printNumber(buf,getDay(),2);
2950                break;
2951            case 'h':
2952                printNumber(buf,getHour(),2);
2953                break;
2954            case 'm':
2955                printNumber(buf,getMinute(),2);
2956                break;
2957            case 's':
2958                printNumber(buf,getSecond(),2);
2959        if (getFractionalSecond() != null) {
2960            String JavaDoc frac = getFractionalSecond().toString();
2961            //skip leading zero.
2962
buf.append(frac.substring(1, frac.length()));
2963        }
2964                break;
2965            case 'z':
2966        int offset = getTimezone();
2967                if(offset == 0) {
2968            buf.append('Z');
2969        } else if (offset != DatatypeConstants.FIELD_UNDEFINED) {
2970            if(offset<0) {
2971            buf.append('-');
2972            offset *= -1;
2973            } else {
2974            buf.append('+');
2975            }
2976            printNumber(buf,offset/60,2);
2977                    buf.append(':');
2978                    printNumber(buf,offset%60,2);
2979                }
2980                break;
2981            default:
2982                throw new InternalError JavaDoc(); // impossible
2983
}
2984        }
2985        
2986        return buf.toString();
2987    }
2988    
2989    /**
2990     * Prints an integer as a String.
2991     *
2992     * @param out
2993     * The formatted string will be appended into this buffer.
2994     * @param number
2995     * The integer to be printed.
2996     * @param nDigits
2997     * The field will be printed by using at least this
2998     * number of digits. For example, 5 will be printed as "0005"
2999     * if nDigits==4.
3000     */

3001    private void printNumber( StringBuffer JavaDoc out, int number, int nDigits ) {
3002        String JavaDoc s = String.valueOf(number);
3003        for( int i=s.length(); i<nDigits; i++ )
3004            out.append('0');
3005        out.append(s);
3006    }
3007
3008    /**
3009     * Prints an BigInteger as a String.
3010     *
3011     * @param out
3012     * The formatted string will be appended into this buffer.
3013     * @param number
3014     * The integer to be printed.
3015     * @param nDigits
3016     * The field will be printed by using at least this
3017     * number of digits. For example, 5 will be printed as "0005"
3018     * if nDigits==4.
3019     */

3020    private void printNumber( StringBuffer JavaDoc out, BigInteger JavaDoc number, int nDigits) {
3021        String JavaDoc s = number.toString();
3022        for( int i=s.length(); i<nDigits; i++ )
3023            out.append('0');
3024        out.append(s);
3025    }
3026
3027    /**
3028     * Compute <code>value*signum</code> where value==null is treated as
3029     * value==0.
3030     * @return non-null {@link BigInteger}.
3031     */

3032    static BigInteger JavaDoc sanitize(Number JavaDoc value, int signum) {
3033        if (signum == 0 || value == null) {
3034            return BigInteger.ZERO;
3035        }
3036        return (signum < 0)? ((BigInteger JavaDoc)value).negate() : (BigInteger JavaDoc)value;
3037    }
3038
3039    /** <p><code>reset()</code> is designed to allow the reuse of existing
3040     * <code>XMLGregorianCalendar</code>s thus saving resources associated
3041     * with the creation of new <code>XMLGregorianCalendar</code>s.</p>
3042     */

3043    public void reset() {
3044        eon = orig_eon;
3045        year = orig_year;
3046        month = orig_month;
3047        day = orig_day;
3048        hour = orig_hour;
3049        minute = orig_minute;
3050        second = orig_second;
3051        fractionalSecond = orig_fracSeconds;
3052        timezone = orig_timezone;
3053    }
3054}
3055
3056
Popular Tags