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(