View Javadoc
1   /*
2    * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  
26  package javax.xml.datatype;
27  
28  import java.math.BigDecimal;
29  import java.math.BigInteger;
30  import java.util.GregorianCalendar;
31  import java.util.regex.Matcher;
32  import java.util.regex.Pattern;
33  
34  /**
35   * <p>Factory that creates new <code>javax.xml.datatype</code> <code>Object</code>s that map XML to/from Java <code>Object</code>s.</p>
36   *
37   * <p>A new instance of the <code>DatatypeFactory</code> is created through the {@link #newInstance()} method
38   * that uses the following implementation resolution mechanisms to determine an implementation:</p>
39   * <ol>
40   *    <li>
41   *      If the system property specified by {@link #DATATYPEFACTORY_PROPERTY}, "<code>javax.xml.datatype.DatatypeFactory</code>",
42   *      exists, a class with the name of the property value is instantiated.
43   *      Any Exception thrown during the instantiation process is wrapped as a {@link DatatypeConfigurationException}.
44   *    </li>
45   *    <li>
46   *      If the file ${JAVA_HOME}/lib/jaxp.properties exists, it is loaded in a {@link java.util.Properties} <code>Object</code>.
47   *      The <code>Properties</code> <code>Object </code> is then queried for the property as documented in the prior step
48   *      and processed as documented in the prior step.
49   *    </li>
50   *    <li>
51   *     Uses the service-provider loading facilities, defined by the {@link java.util.ServiceLoader} class, to attempt
52   *     to locate and load an implementation of the service using the {@linkplain
53   *     java.util.ServiceLoader#load(java.lang.Class) default loading mechanism}:
54   *     the service-provider loading facility will use the {@linkplain
55   *     java.lang.Thread#getContextClassLoader() current thread's context class loader}
56   *     to attempt to load the service. If the context class
57   *     loader is null, the {@linkplain
58   *     ClassLoader#getSystemClassLoader() system class loader} will be used.
59   *     <br>
60   *     In case of {@link java.util.ServiceConfigurationError service
61   *     configuration error} a {@link javax.xml.datatype.DatatypeConfigurationException}
62   *     will be thrown.
63   *    </li>
64   *    <li>
65   *      The final mechanism is to attempt to instantiate the <code>Class</code> specified by
66   *      {@link #DATATYPEFACTORY_IMPLEMENTATION_CLASS}.
67   *      Any Exception thrown during the instantiation process is wrapped as a {@link DatatypeConfigurationException}.
68   *    </li>
69   * </ol>
70   *
71   * @author <a href="mailto:Joseph.Fialli@Sun.COM">Joseph Fialli</a>
72   * @author <a href="mailto:Jeff.Suttor@Sun.com">Jeff Suttor</a>
73   * @author <a href="mailto:Neeraj.Bajaj@sun.com">Neeraj Bajaj</a>
74   *
75   * @version $Revision: 1.13 $, $Date: 2010/03/11 23:10:53 $
76   * @since 1.5
77   */
78  public abstract class DatatypeFactory {
79  
80      /**
81       * <p>Default property name as defined in JSR 206: Java(TM) API for XML Processing (JAXP) 1.3.</p>
82       *
83       * <p>Default value is <code>javax.xml.datatype.DatatypeFactory</code>.</p>
84       */
85      public static final String DATATYPEFACTORY_PROPERTY =
86              // We use a String constant here, rather than calling
87              // DatatypeFactory.class.getName() - in order to make javadoc
88              // generate a See Also: Constant Field Value link.
89              "javax.xml.datatype.DatatypeFactory";
90  
91      /**
92       * <p>Default implementation class name as defined in
93       * <em>JSR 206: Java(TM) API for XML Processing (JAXP) 1.3</em>.</p>
94       *
95       * <p>Implementers should specify the name of an appropriate class
96       * to be instantiated if no other implementation resolution mechanism
97       * succeeds.</p>
98       *
99       * <p>Users should not refer to this field; it is intended only to
100      * document a factory implementation detail.
101      * </p>
102      */
103     public static final String DATATYPEFACTORY_IMPLEMENTATION_CLASS =
104         // We use new String() here to prevent javadoc from generating
105         // a See Also: Constant Field Value link.
106         new String("com.sun.org.apache.xerces.internal.jaxp.datatype.DatatypeFactoryImpl");
107 
108     /**
109      * http://www.w3.org/TR/xpath-datamodel/#xdtschema defines two regexps
110      * to constrain the value space of dayTimeDuration ([^YM]*[DT].*)
111      * and yearMonthDuration ([^DT]*). Note that these expressions rely on
112      * the fact that the value must be an xs:Duration, they simply exclude
113      * some Durations.
114      */
115     private static final Pattern XDTSCHEMA_YMD =
116         Pattern.compile("[^DT]*");
117 
118     private static final Pattern XDTSCHEMA_DTD =
119         Pattern.compile("[^YM]*[DT].*");
120 
121     /**
122      * <p>Protected constructor to prevent instaniation outside of package.</p>
123      *
124      * <p>Use {@link #newInstance()} to create a <code>DatatypeFactory</code>.</p>
125      */
126     protected DatatypeFactory() {
127     }
128 
129     /**
130      * <p>Obtain a new instance of a <code>DatatypeFactory</code>.</p>
131      *
132      * <p>The implementation resolution mechanisms are <a href="#DatatypeFactory.newInstance">defined</a> in this
133      * <code>Class</code>'s documentation.</p>
134      *
135      * @return New instance of a <code>DatatypeFactory</code>
136      *
137      * @throws DatatypeConfigurationException If the implementation is not
138      *   available or cannot be instantiated.
139      *
140      * @see #newInstance(String factoryClassName, ClassLoader classLoader)
141      */
142     public static DatatypeFactory newInstance()
143             throws DatatypeConfigurationException {
144 
145             return FactoryFinder.find(
146                     /* The default property name according to the JAXP spec */
147                     DatatypeFactory.class,
148                     /* The fallback implementation class name */
149                     DATATYPEFACTORY_IMPLEMENTATION_CLASS);
150     }
151 
152     /**
153      * <p>Obtain a new instance of a <code>DatatypeFactory</code> from class name.
154      * This function is useful when there are multiple providers in the classpath.
155      * It gives more control to the application as it can specify which provider
156      * should be loaded.</p>
157      *
158      * <p>Once an application has obtained a reference to a <code>DatatypeFactory</code>
159      * it can use the factory to configure and obtain datatype instances.</P>
160      *
161      *
162      * <h2>Tip for Trouble-shooting</h2>
163      * <p>Setting the <code>jaxp.debug</code> system property will cause
164      * this method to print a lot of debug messages
165      * to <code>System.err</code> about what it is doing and where it is looking at.</p>
166      *
167      * <p> If you have problems try:</p>
168      * <pre>
169      * java -Djaxp.debug=1 YourProgram ....
170      * </pre>
171      *
172      * @param factoryClassName fully qualified factory class name that provides implementation of <code>javax.xml.datatype.DatatypeFactory</code>.
173      *
174      * @param classLoader <code>ClassLoader</code> used to load the factory class. If <code>null</code>
175      *                     current <code>Thread</code>'s context classLoader is used to load the factory class.
176      *
177      * @return New instance of a <code>DatatypeFactory</code>
178      *
179      * @throws DatatypeConfigurationException if <code>factoryClassName</code> is <code>null</code>, or
180      *                                   the factory class cannot be loaded, instantiated.
181      *
182      * @see #newInstance()
183      *
184      * @since 1.6
185      */
186     public static DatatypeFactory newInstance(String factoryClassName, ClassLoader classLoader)
187         throws DatatypeConfigurationException {
188         return FactoryFinder.newInstance(DatatypeFactory.class,
189                     factoryClassName, classLoader, false);
190      }
191 
192     /**
193      * <p>Obtain a new instance of a <code>Duration</code>
194      * specifying the <code>Duration</code> as its string representation, "PnYnMnDTnHnMnS",
195      * as defined in XML Schema 1.0 section 3.2.6.1.</p>
196      *
197      * <p>XML Schema Part 2: Datatypes, 3.2.6 duration, defines <code>duration</code> as:</p>
198      * <blockquote>
199      * duration represents a duration of time.
200      * The value space of duration is a six-dimensional space where the coordinates designate the
201      * Gregorian year, month, day, hour, minute, and second components defined in Section 5.5.3.2 of [ISO 8601], respectively.
202      * These components are ordered in their significance by their order of appearance i.e. as
203      * year, month, day, hour, minute, and second.
204      * </blockquote>
205      * <p>All six values are set and available from the created {@link Duration}</p>
206      *
207      * <p>The XML Schema specification states that values can be of an arbitrary size.
208      * Implementations may chose not to or be incapable of supporting arbitrarily large and/or small values.
209      * An {@link UnsupportedOperationException} will be thrown with a message indicating implementation limits
210      * if implementation capacities are exceeded.</p>
211      *
212      * @param lexicalRepresentation <code>String</code> representation of a <code>Duration</code>.
213      *
214      * @return New <code>Duration</code> created from parsing the <code>lexicalRepresentation</code>.
215      *
216      * @throws IllegalArgumentException If <code>lexicalRepresentation</code> is not a valid representation of a <code>Duration</code>.
217      * @throws UnsupportedOperationException If implementation cannot support requested values.
218      * @throws NullPointerException if <code>lexicalRepresentation</code> is <code>null</code>.
219      */
220     public abstract Duration newDuration(final String lexicalRepresentation);
221 
222     /**
223      * <p>Obtain a new instance of a <code>Duration</code>
224      * specifying the <code>Duration</code> as milliseconds.</p>
225      *
226      * <p>XML Schema Part 2: Datatypes, 3.2.6 duration, defines <code>duration</code> as:</p>
227      * <blockquote>
228      * duration represents a duration of time.
229      * The value space of duration is a six-dimensional space where the coordinates designate the
230      * Gregorian year, month, day, hour, minute, and second components defined in Section 5.5.3.2 of [ISO 8601], respectively.
231      * These components are ordered in their significance by their order of appearance i.e. as
232      * year, month, day, hour, minute, and second.
233      * </blockquote>
234      * <p>All six values are set by computing their values from the specified milliseconds
235      * and are available using the <code>get</code> methods of  the created {@link Duration}.
236      * The values conform to and are defined by:</p>
237      * <ul>
238      *   <li>ISO 8601:2000(E) Section 5.5.3.2 Alternative format</li>
239      *   <li><a href="http://www.w3.org/TR/xmlschema-2/#isoformats">
240      *     W3C XML Schema 1.0 Part 2, Appendix D, ISO 8601 Date and Time Formats</a>
241      *   </li>
242      *   <li>{@link XMLGregorianCalendar}  Date/Time Datatype Field Mapping Between XML Schema 1.0 and Java Representation</li>
243      * </ul>
244      *
245      * <p>The default start instance is defined by {@link GregorianCalendar}'s use of the start of the epoch: i.e.,
246      * {@link java.util.Calendar#YEAR} = 1970,
247      * {@link java.util.Calendar#MONTH} = {@link java.util.Calendar#JANUARY},
248      * {@link java.util.Calendar#DATE} = 1, etc.
249      * This is important as there are variations in the Gregorian Calendar,
250      * e.g. leap years have different days in the month = {@link java.util.Calendar#FEBRUARY}
251      * so the result of {@link Duration#getMonths()} and {@link Duration#getDays()} can be influenced.</p>
252      *
253      * @param durationInMilliSeconds Duration in milliseconds to create.
254      *
255      * @return New <code>Duration</code> representing <code>durationInMilliSeconds</code>.
256      */
257     public abstract Duration newDuration(final long durationInMilliSeconds);
258 
259     /**
260      * <p>Obtain a new instance of a <code>Duration</code>
261      * specifying the <code>Duration</code> as isPositive, years, months, days, hours, minutes, seconds.</p>
262      *
263      * <p>The XML Schema specification states that values can be of an arbitrary size.
264      * Implementations may chose not to or be incapable of supporting arbitrarily large and/or small values.
265      * An {@link UnsupportedOperationException} will be thrown with a message indicating implementation limits
266      * if implementation capacities are exceeded.</p>
267      *
268      * <p>A <code>null</code> value indicates that field is not set.</p>
269      *
270      * @param isPositive Set to <code>false</code> to create a negative duration. When the length
271      *   of the duration is zero, this parameter will be ignored.
272      * @param years of this <code>Duration</code>
273      * @param months of this <code>Duration</code>
274      * @param days of this <code>Duration</code>
275      * @param hours of this <code>Duration</code>
276      * @param minutes of this <code>Duration</code>
277      * @param seconds of this <code>Duration</code>
278      *
279      * @return New <code>Duration</code> created from the specified values.
280      *
281      * @throws IllegalArgumentException If the values are not a valid representation of a
282      * <code>Duration</code>: if all the fields (years, months, ...) are null or
283      * if any of the fields is negative.
284      * @throws UnsupportedOperationException If implementation cannot support requested values.
285      */
286     public abstract Duration newDuration(
287             final boolean isPositive,
288             final BigInteger years,
289             final BigInteger months,
290             final BigInteger days,
291             final BigInteger hours,
292             final BigInteger minutes,
293             final BigDecimal seconds);
294 
295     /**
296      * <p>Obtain a new instance of a <code>Duration</code>
297      * specifying the <code>Duration</code> as isPositive, years, months, days, hours, minutes, seconds.</p>
298      *
299      * <p>A {@link DatatypeConstants#FIELD_UNDEFINED} value indicates that field is not set.</p>
300      *
301      * @param isPositive Set to <code>false</code> to create a negative duration. When the length
302      *   of the duration is zero, this parameter will be ignored.
303      * @param years of this <code>Duration</code>
304      * @param months of this <code>Duration</code>
305      * @param days of this <code>Duration</code>
306      * @param hours of this <code>Duration</code>
307      * @param minutes of this <code>Duration</code>
308      * @param seconds of this <code>Duration</code>
309      *
310      * @return New <code>Duration</code> created from the specified values.
311      *
312      * @throws IllegalArgumentException If the values are not a valid representation of a
313      * <code>Duration</code>: if any of the fields is negative.
314      *
315      * @see #newDuration(
316      *   boolean isPositive,
317      *   BigInteger years,
318      *   BigInteger months,
319      *   BigInteger days,
320      *   BigInteger hours,
321      *   BigInteger minutes,
322      *   BigDecimal seconds)
323      */
324     public Duration newDuration(
325             final boolean isPositive,
326             final int years,
327             final int months,
328             final int days,
329             final int hours,
330             final int minutes,
331             final int seconds) {
332 
333             // years may not be set
334             BigInteger realYears = (years != DatatypeConstants.FIELD_UNDEFINED) ? BigInteger.valueOf((long) years) : null;
335 
336             // months may not be set
337             BigInteger realMonths = (months != DatatypeConstants.FIELD_UNDEFINED) ? BigInteger.valueOf((long) months) : null;
338 
339             // days may not be set
340             BigInteger realDays = (days != DatatypeConstants.FIELD_UNDEFINED) ? BigInteger.valueOf((long) days) : null;
341 
342             // hours may not be set
343             BigInteger realHours = (hours != DatatypeConstants.FIELD_UNDEFINED) ? BigInteger.valueOf((long) hours) : null;
344 
345             // minutes may not be set
346             BigInteger realMinutes = (minutes != DatatypeConstants.FIELD_UNDEFINED) ? BigInteger.valueOf((long) minutes) : null;
347 
348             // seconds may not be set
349             BigDecimal realSeconds = (seconds != DatatypeConstants.FIELD_UNDEFINED) ? BigDecimal.valueOf((long) seconds) : null;
350 
351                     return newDuration(
352                             isPositive,
353                             realYears,
354                             realMonths,
355                             realDays,
356                             realHours,
357                             realMinutes,
358                             realSeconds
359                     );
360             }
361 
362     /**
363      * <p>Create a <code>Duration</code> of type <code>xdt:dayTimeDuration</code> by parsing its <code>String</code> representation,
364      * "<em>PnDTnHnMnS</em>", <a href="http://www.w3.org/TR/xpath-datamodel#dayTimeDuration">
365      *   XQuery 1.0 and XPath 2.0 Data Model, xdt:dayTimeDuration</a>.</p>
366      *
367      * <p>The datatype <code>xdt:dayTimeDuration</code> is a subtype of <code>xs:duration</code>
368      * whose lexical representation contains only day, hour, minute, and second components.
369      * This datatype resides in the namespace <code>http://www.w3.org/2003/11/xpath-datatypes</code>.</p>;
370      *
371      * <p>All four values are set and available from the created {@link Duration}</p>
372      *
373      * <p>The XML Schema specification states that values can be of an arbitrary size.
374      * Implementations may chose not to or be incapable of supporting arbitrarily large and/or small values.
375      * An {@link UnsupportedOperationException} will be thrown with a message indicating implementation limits
376      * if implementation capacities are exceeded.</p>
377      *
378      * @param lexicalRepresentation Lexical representation of a duration.
379      *
380      * @return New <code>Duration</code> created using the specified <code>lexicalRepresentation</code>.
381      *
382      * @throws IllegalArgumentException If <code>lexicalRepresentation</code> is not a valid representation of a <code>Duration</code> expressed only in terms of days and time.
383      * @throws UnsupportedOperationException If implementation cannot support requested values.
384      * @throws NullPointerException If <code>lexicalRepresentation</code> is <code>null</code>.
385      */
386     public Duration newDurationDayTime(final String lexicalRepresentation) {
387         // lexicalRepresentation must be non-null
388         if (lexicalRepresentation == null) {
389             throw new NullPointerException(
390                 "Trying to create an xdt:dayTimeDuration with an invalid"
391                 + " lexical representation of \"null\"");
392         }
393 
394         // test lexicalRepresentation against spec regex
395         Matcher matcher = XDTSCHEMA_DTD.matcher(lexicalRepresentation);
396         if (!matcher.matches()) {
397             throw new IllegalArgumentException(
398                 "Trying to create an xdt:dayTimeDuration with an invalid"
399                 + " lexical representation of \"" + lexicalRepresentation
400                 + "\", data model requires years and months only.");
401         }
402 
403         return newDuration(lexicalRepresentation);
404     }
405 
406     /**
407      * <p>Create a <code>Duration</code> of type <code>xdt:dayTimeDuration</code> using the specified milliseconds as defined in
408      * <a href="http://www.w3.org/TR/xpath-datamodel#dayTimeDuration">
409      *   XQuery 1.0 and XPath 2.0 Data Model, xdt:dayTimeDuration</a>.</p>
410      *
411      * <p>The datatype <code>xdt:dayTimeDuration</code> is a subtype of <code>xs:duration</code>
412      * whose lexical representation contains only day, hour, minute, and second components.
413      * This datatype resides in the namespace <code>http://www.w3.org/2003/11/xpath-datatypes</code>.</p>;
414      *
415      * <p>All four values are set by computing their values from the specified milliseconds
416      * and are available using the <code>get</code> methods of  the created {@link Duration}.
417      * The values conform to and are defined by:</p>
418      * <ul>
419      *   <li>ISO 8601:2000(E) Section 5.5.3.2 Alternative format</li>
420      *   <li><a href="http://www.w3.org/TR/xmlschema-2/#isoformats">
421      *     W3C XML Schema 1.0 Part 2, Appendix D, ISO 8601 Date and Time Formats</a>
422      *   </li>
423      *   <li>{@link XMLGregorianCalendar}  Date/Time Datatype Field Mapping Between XML Schema 1.0 and Java Representation</li>
424      * </ul>
425      *
426      * <p>The default start instance is defined by {@link GregorianCalendar}'s use of the start of the epoch: i.e.,
427      * {@link java.util.Calendar#YEAR} = 1970,
428      * {@link java.util.Calendar#MONTH} = {@link java.util.Calendar#JANUARY},
429      * {@link java.util.Calendar#DATE} = 1, etc.
430      * This is important as there are variations in the Gregorian Calendar,
431      * e.g. leap years have different days in the month = {@link java.util.Calendar#FEBRUARY}
432      * so the result of {@link Duration#getDays()} can be influenced.</p>
433      *
434      * <p>Any remaining milliseconds after determining the day, hour, minute and second are discarded.</p>
435      *
436      * @param durationInMilliseconds Milliseconds of <code>Duration</code> to create.
437      *
438      * @return New <code>Duration</code> created with the specified <code>durationInMilliseconds</code>.
439      *
440      * @see <a href="http://www.w3.org/TR/xpath-datamodel#dayTimeDuration">
441      *   XQuery 1.0 and XPath 2.0 Data Model, xdt:dayTimeDuration</a>
442      */
443     public Duration newDurationDayTime(final long durationInMilliseconds) {
444 
445             return newDuration(durationInMilliseconds);
446     }
447 
448     /**
449      * <p>Create a <code>Duration</code> of type <code>xdt:dayTimeDuration</code> using the specified
450      * <code>day</code>, <code>hour</code>, <code>minute</code> and <code>second</code> as defined in
451      * <a href="http://www.w3.org/TR/xpath-datamodel#dayTimeDuration">
452      *   XQuery 1.0 and XPath 2.0 Data Model, xdt:dayTimeDuration</a>.</p>
453      *
454      * <p>The datatype <code>xdt:dayTimeDuration</code> is a subtype of <code>xs:duration</code>
455      * whose lexical representation contains only day, hour, minute, and second components.
456      * This datatype resides in the namespace <code>http://www.w3.org/2003/11/xpath-datatypes</code>.</p>;
457      *
458      * <p>The XML Schema specification states that values can be of an arbitrary size.
459      * Implementations may chose not to or be incapable of supporting arbitrarily large and/or small values.
460      * An {@link UnsupportedOperationException} will be thrown with a message indicating implementation limits
461      * if implementation capacities are exceeded.</p>
462      *
463      * <p>A <code>null</code> value indicates that field is not set.</p>
464      *
465      * @param isPositive Set to <code>false</code> to create a negative duration. When the length
466      *   of the duration is zero, this parameter will be ignored.
467      * @param day Day of <code>Duration</code>.
468      * @param hour Hour of <code>Duration</code>.
469      * @param minute Minute of <code>Duration</code>.
470      * @param second Second of <code>Duration</code>.
471      *
472      * @return New <code>Duration</code> created with the specified <code>day</code>, <code>hour</code>, <code>minute</code>
473      * and <code>second</code>.
474      *
475      * @throws IllegalArgumentException If the values are not a valid representation of a
476      * <code>Duration</code>: if all the fields (day, hour, ...) are null or
477      * if any of the fields is negative.
478      * @throws UnsupportedOperationException If implementation cannot support requested values.
479      */
480     public Duration newDurationDayTime(
481             final boolean isPositive,
482             final BigInteger day,
483             final BigInteger hour,
484             final BigInteger minute,
485             final BigInteger second) {
486 
487             return newDuration(
488                     isPositive,
489                     null,  // years
490                     null, // months
491                     day,
492                     hour,
493                     minute,
494                     (second != null)? new BigDecimal(second):null
495             );
496     }
497 
498     /**
499      * <p>Create a <code>Duration</code> of type <code>xdt:dayTimeDuration</code> using the specified
500      * <code>day</code>, <code>hour</code>, <code>minute</code> and <code>second</code> as defined in
501      * <a href="http://www.w3.org/TR/xpath-datamodel#dayTimeDuration">
502      *   XQuery 1.0 and XPath 2.0 Data Model, xdt:dayTimeDuration</a>.</p>
503      *
504      * <p>The datatype <code>xdt:dayTimeDuration</code> is a subtype of <code>xs:duration</code>
505      * whose lexical representation contains only day, hour, minute, and second components.
506      * This datatype resides in the namespace <code>http://www.w3.org/2003/11/xpath-datatypes</code>.</p>;
507      *
508      * <p>A {@link DatatypeConstants#FIELD_UNDEFINED} value indicates that field is not set.</p>
509      *
510      * @param isPositive Set to <code>false</code> to create a negative duration. When the length
511      *   of the duration is zero, this parameter will be ignored.
512      * @param day Day of <code>Duration</code>.
513      * @param hour Hour of <code>Duration</code>.
514      * @param minute Minute of <code>Duration</code>.
515      * @param second Second of <code>Duration</code>.
516      *
517      * @return New <code>Duration</code> created with the specified <code>day</code>, <code>hour</code>, <code>minute</code>
518      * and <code>second</code>.
519      *
520      * @throws IllegalArgumentException If the values are not a valid representation of a
521      * <code>Duration</code>: if any of the fields (day, hour, ...) is negative.
522      */
523     public Duration newDurationDayTime(
524             final boolean isPositive,
525             final int day,
526             final int hour,
527             final int minute,
528             final int second) {
529 
530                     return newDurationDayTime(
531                             isPositive,
532                             BigInteger.valueOf((long) day),
533                             BigInteger.valueOf((long) hour),
534                             BigInteger.valueOf((long) minute),
535                             BigInteger.valueOf((long) second)
536                             );
537             }
538 
539     /**
540      * <p>Create a <code>Duration</code> of type <code>xdt:yearMonthDuration</code> by parsing its <code>String</code> representation,
541      * "<em>PnYnM</em>", <a href="http://www.w3.org/TR/xpath-datamodel#yearMonthDuration">
542      *   XQuery 1.0 and XPath 2.0 Data Model, xdt:yearMonthDuration</a>.</p>
543      *
544      * <p>The datatype <code>xdt:yearMonthDuration</code> is a subtype of <code>xs:duration</code>
545      * whose lexical representation contains only year and month components.
546      * This datatype resides in the namespace {@link javax.xml.XMLConstants#W3C_XPATH_DATATYPE_NS_URI}.</p>
547      *
548      * <p>Both values are set and available from the created {@link Duration}</p>
549      *
550      * <p>The XML Schema specification states that values can be of an arbitrary size.
551      * Implementations may chose not to or be incapable of supporting arbitrarily large and/or small values.
552      * An {@link UnsupportedOperationException} will be thrown with a message indicating implementation limits
553      * if implementation capacities are exceeded.</p>
554      *
555      * @param lexicalRepresentation Lexical representation of a duration.
556      *
557      * @return New <code>Duration</code> created using the specified <code>lexicalRepresentation</code>.
558      *
559      * @throws IllegalArgumentException If <code>lexicalRepresentation</code> is not a valid representation of a <code>Duration</code> expressed only in terms of years and months.
560      * @throws UnsupportedOperationException If implementation cannot support requested values.
561      * @throws NullPointerException If <code>lexicalRepresentation</code> is <code>null</code>.
562      */
563     public Duration newDurationYearMonth(
564             final String lexicalRepresentation) {
565 
566         // lexicalRepresentation must be non-null
567         if (lexicalRepresentation == null) {
568             throw new NullPointerException(
569                     "Trying to create an xdt:yearMonthDuration with an invalid"
570                     + " lexical representation of \"null\"");
571         }
572 
573         // test lexicalRepresentation against spec regex
574         Matcher matcher = XDTSCHEMA_YMD.matcher(lexicalRepresentation);
575         if (!matcher.matches()) {
576             throw new IllegalArgumentException(
577                     "Trying to create an xdt:yearMonthDuration with an invalid"
578                     + " lexical representation of \"" + lexicalRepresentation
579                     + "\", data model requires days and times only.");
580         }
581 
582         return newDuration(lexicalRepresentation);
583     }
584 
585     /**
586      * <p>Create a <code>Duration</code> of type <code>xdt:yearMonthDuration</code> using the specified milliseconds as defined in
587      * <a href="http://www.w3.org/TR/xpath-datamodel#yearMonthDuration">
588      *   XQuery 1.0 and XPath 2.0 Data Model, xdt:yearMonthDuration</a>.</p>
589      *
590      * <p>The datatype <code>xdt:yearMonthDuration</code> is a subtype of <code>xs:duration</code>
591      * whose lexical representation contains only year and month components.
592      * This datatype resides in the namespace {@link javax.xml.XMLConstants#W3C_XPATH_DATATYPE_NS_URI}.</p>
593      *
594      * <p>Both values are set by computing their values from the specified milliseconds
595      * and are available using the <code>get</code> methods of  the created {@link Duration}.
596      * The values conform to and are defined by:</p>
597      * <ul>
598      *   <li>ISO 8601:2000(E) Section 5.5.3.2 Alternative format</li>
599      *   <li><a href="http://www.w3.org/TR/xmlschema-2/#isoformats">
600      *     W3C XML Schema 1.0 Part 2, Appendix D, ISO 8601 Date and Time Formats</a>
601      *   </li>
602      *   <li>{@link XMLGregorianCalendar}  Date/Time Datatype Field Mapping Between XML Schema 1.0 and Java Representation</li>
603      * </ul>
604      *
605      * <p>The default start instance is defined by {@link GregorianCalendar}'s use of the start of the epoch: i.e.,
606      * {@link java.util.Calendar#YEAR} = 1970,
607      * {@link java.util.Calendar#MONTH} = {@link java.util.Calendar#JANUARY},
608      * {@link java.util.Calendar#DATE} = 1, etc.
609      * This is important as there are variations in the Gregorian Calendar,
610      * e.g. leap years have different days in the month = {@link java.util.Calendar#FEBRUARY}
611      * so the result of {@link Duration#getMonths()} can be influenced.</p>
612      *
613      * <p>Any remaining milliseconds after determining the year and month are discarded.</p>
614      *
615      * @param durationInMilliseconds Milliseconds of <code>Duration</code> to create.
616      *
617      * @return New <code>Duration</code> created using the specified <code>durationInMilliseconds</code>.
618      */
619     public Duration newDurationYearMonth(
620             final long durationInMilliseconds) {
621 
622         // create a Duration that only has sign, year & month
623         // Duration is immutable, so need to create a new Duration
624         // implementations may override this method in a more efficient way
625         Duration fullDuration = newDuration(durationInMilliseconds);
626         boolean isPositive = (fullDuration.getSign() == -1) ? false : true;
627         BigInteger years =
628             (BigInteger) fullDuration.getField(DatatypeConstants.YEARS);
629         if (years == null) { years = BigInteger.ZERO; }
630         BigInteger months =
631             (BigInteger) fullDuration.getField(DatatypeConstants.MONTHS);
632         if (months == null) { months = BigInteger.ZERO; }
633 
634         return newDurationYearMonth(isPositive, years, months);
635     }
636 
637     /**
638      * <p>Create a <code>Duration</code> of type <code>xdt:yearMonthDuration</code> using the specified
639      * <code>year</code> and <code>month</code> as defined in
640      * <a href="http://www.w3.org/TR/xpath-datamodel#yearMonthDuration">
641      *   XQuery 1.0 and XPath 2.0 Data Model, xdt:yearMonthDuration</a>.</p>
642      *
643      * <p>The XML Schema specification states that values can be of an arbitrary size.
644      * Implementations may chose not to or be incapable of supporting arbitrarily large and/or small values.
645      * An {@link UnsupportedOperationException} will be thrown with a message indicating implementation limits
646      * if implementation capacities are exceeded.</p>
647      *
648      * <p>A <code>null</code> value indicates that field is not set.</p>
649      *
650      * @param isPositive Set to <code>false</code> to create a negative duration. When the length
651      *   of the duration is zero, this parameter will be ignored.
652      * @param year Year of <code>Duration</code>.
653      * @param month Month of <code>Duration</code>.
654      *
655      * @return New <code>Duration</code> created using the specified <code>year</code> and <code>month</code>.
656      *
657      * @throws IllegalArgumentException If the values are not a valid representation of a
658      * <code>Duration</code>: if all of the fields (year, month) are null or
659      * if any of the fields is negative.
660      * @throws UnsupportedOperationException If implementation cannot support requested values.
661      */
662     public Duration newDurationYearMonth(
663             final boolean isPositive,
664             final BigInteger year,
665             final BigInteger month) {
666 
667             return newDuration(
668                     isPositive,
669                     year,
670                     month,
671                     null, // days
672                     null, // hours
673                     null, // minutes
674                     null  // seconds
675             );
676     }
677 
678     /**
679      * <p>Create a <code>Duration</code> of type <code>xdt:yearMonthDuration</code> using the specified
680      * <code>year</code> and <code>month</code> as defined in
681      * <a href="http://www.w3.org/TR/xpath-datamodel#yearMonthDuration">
682      *   XQuery 1.0 and XPath 2.0 Data Model, xdt:yearMonthDuration</a>.</p>
683      *
684      * <p>A {@link DatatypeConstants#FIELD_UNDEFINED} value indicates that field is not set.</p>
685      *
686      * @param isPositive Set to <code>false</code> to create a negative duration. When the length
687      *   of the duration is zero, this parameter will be ignored.
688      * @param year Year of <code>Duration</code>.
689      * @param month Month of <code>Duration</code>.
690      *
691      * @return New <code>Duration</code> created using the specified <code>year</code> and <code>month</code>.
692      *
693      * @throws IllegalArgumentException If the values are not a valid representation of a
694      * <code>Duration</code>: if any of the fields (year, month) is negative.
695      */
696     public Duration newDurationYearMonth(
697             final boolean isPositive,
698             final int year,
699             final int month) {
700 
701             return newDurationYearMonth(
702                     isPositive,
703                     BigInteger.valueOf((long) year),
704                     BigInteger.valueOf((long) month));
705             }
706 
707     /**
708      * <p>Create a new instance of an <code>XMLGregorianCalendar</code>.</p>
709      *
710      * <p>All date/time datatype fields set to {@link DatatypeConstants#FIELD_UNDEFINED} or null.</p>
711      *
712      * @return New <code>XMLGregorianCalendar</code> with all date/time datatype fields set to
713      *   {@link DatatypeConstants#FIELD_UNDEFINED} or null.
714      */
715     public abstract XMLGregorianCalendar newXMLGregorianCalendar();
716 
717     /**
718      * <p>Create a new XMLGregorianCalendar by parsing the String as a lexical representation.</p>
719      *
720      * <p>Parsing the lexical string representation is defined in
721      * <a href="http://www.w3.org/TR/xmlschema-2/#dateTime-order">XML Schema 1.0 Part 2, Section 3.2.[7-14].1,
722      * <em>Lexical Representation</em>.</a></p>
723      *
724      * <p>The string representation may not have any leading and trailing whitespaces.</p>
725      *
726      * <p>The parsing is done field by field so that
727      * the following holds for any lexically correct String x:</p>
728      * <pre>
729      * newXMLGregorianCalendar(x).toXMLFormat().equals(x)
730      * </pre>
731      * <p>Except for the noted lexical/canonical representation mismatches
732      * listed in <a href="http://www.w3.org/2001/05/xmlschema-errata#e2-45">
733      * XML Schema 1.0 errata, Section 3.2.7.2</a>.</p>
734      *
735      * @param lexicalRepresentation Lexical representation of one the eight XML Schema date/time datatypes.
736      *
737      * @return <code>XMLGregorianCalendar</code> created from the <code>lexicalRepresentation</code>.
738      *
739      * @throws IllegalArgumentException If the <code>lexicalRepresentation</code> is not a valid <code>XMLGregorianCalendar</code>.
740      * @throws NullPointerException If <code>lexicalRepresentation</code> is <code>null</code>.
741      */
742     public abstract XMLGregorianCalendar newXMLGregorianCalendar(final String lexicalRepresentation);
743 
744     /**
745      * <p>Create an <code>XMLGregorianCalendar</code> from a {@link GregorianCalendar}.</p>
746      *
747      * <table border="2" rules="all" cellpadding="2">
748      *   <thead>
749      *     <tr>
750      *       <th align="center" colspan="2">
751      *          Field by Field Conversion from
752      *          {@link GregorianCalendar} to an {@link XMLGregorianCalendar}
753      *       </th>
754      *     </tr>
755      *     <tr>
756      *        <th><code>java.util.GregorianCalendar</code> field</th>
757      *        <th><code>javax.xml.datatype.XMLGregorianCalendar</code> field</th>
758      *     </tr>
759      *   </thead>
760      *   <tbody>
761      *     <tr>
762      *       <td><code>ERA == GregorianCalendar.BC ? -YEAR : YEAR</code></td>
763      *       <td>{@link XMLGregorianCalendar#setYear(int year)}</td>
764      *     </tr>
765      *     <tr>
766      *       <td><code>MONTH + 1</code></td>
767      *       <td>{@link XMLGregorianCalendar#setMonth(int month)}</td>
768      *     </tr>
769      *     <tr>
770      *       <td><code>DAY_OF_MONTH</code></td>
771      *       <td>{@link XMLGregorianCalendar#setDay(int day)}</td>
772      *     </tr>
773      *     <tr>
774      *       <td><code>HOUR_OF_DAY, MINUTE, SECOND, MILLISECOND</code></td>
775      *       <td>{@link XMLGregorianCalendar#setTime(int hour, int minute, int second, BigDecimal fractional)}</td>
776      *     </tr>
777      *     <tr>
778      *       <td>
779      *         <code>(ZONE_OFFSET + DST_OFFSET) / (60*1000)</code><br/>
780      *         <em>(in minutes)</em>
781      *       </td>
782      *       <td>{@link XMLGregorianCalendar#setTimezone(int offset)}<sup><em>*</em></sup>
783      *       </td>
784      *     </tr>
785      *   </tbody>
786      * </table>
787      * <p><em>*</em>conversion loss of information. It is not possible to represent
788      * a <code>java.util.GregorianCalendar</code> daylight savings timezone id in the
789      * XML Schema 1.0 date/time datatype representation.</p>
790      *
791      * <p>To compute the return value's <code>TimeZone</code> field,
792      * <ul>
793      * <li>when <code>this.getTimezone() != FIELD_UNDEFINED</code>,
794      * create a <code>java.util.TimeZone</code> with a custom timezone id
795      * using the <code>this.getTimezone()</code>.</li>
796      * <li>else use the <code>GregorianCalendar</code> default timezone value
797      * for the host is defined as specified by
798      * <code>java.util.TimeZone.getDefault()</code>.</li></p>
799      *
800      * @param cal <code>java.util.GregorianCalendar</code> used to create <code>XMLGregorianCalendar</code>
801      *
802      * @return <code>XMLGregorianCalendar</code> created from <code>java.util.GregorianCalendar</code>
803      *
804      * @throws NullPointerException If <code>cal</code> is <code>null</code>.
805      */
806     public abstract XMLGregorianCalendar newXMLGregorianCalendar(final GregorianCalendar cal);
807 
808     /**
809      * <p>Constructor allowing for complete value spaces allowed by
810      * W3C XML Schema 1.0 recommendation for xsd:dateTime and related
811      * builtin datatypes. Note that <code>year</code> parameter supports
812      * arbitrarily large numbers and fractionalSecond has infinite
813      * precision.</p>
814      *
815      * <p>A <code>null</code> value indicates that field is not set.</p>
816      *
817      * @param year of <code>XMLGregorianCalendar</code> to be created.
818      * @param month of <code>XMLGregorianCalendar</code> to be created.
819      * @param day of <code>XMLGregorianCalendar</code> to be created.
820      * @param hour of <code>XMLGregorianCalendar</code> to be created.
821      * @param minute of <code>XMLGregorianCalendar</code> to be created.
822      * @param second of <code>XMLGregorianCalendar</code> to be created.
823      * @param fractionalSecond of <code>XMLGregorianCalendar</code> to be created.
824      * @param timezone of <code>XMLGregorianCalendar</code> to be created.
825      *
826      * @return <code>XMLGregorianCalendar</code> created from specified values.
827      *
828      * @throws IllegalArgumentException If any individual parameter's value is outside the maximum value constraint for the field
829      *   as determined by the Date/Time Data Mapping table in {@link XMLGregorianCalendar}
830      *   or if the composite values constitute an invalid <code>XMLGregorianCalendar</code> instance
831      *   as determined by {@link XMLGregorianCalendar#isValid()}.
832      */
833     public abstract XMLGregorianCalendar newXMLGregorianCalendar(
834             final BigInteger year,
835             final int month,
836             final int day,
837             final int hour,
838             final int minute,
839             final int second,
840             final BigDecimal fractionalSecond,
841             final int timezone);
842 
843     /**
844      * <p>Constructor of value spaces that a
845      * <code>java.util.GregorianCalendar</code> instance would need to convert to an
846      * <code>XMLGregorianCalendar</code> instance.</p>
847      *
848      * <p><code>XMLGregorianCalendar eon</code> and
849      * <code>fractionalSecond</code> are set to <code>null</code></p>
850      *
851      * <p>A {@link DatatypeConstants#FIELD_UNDEFINED} value indicates that field is not set.</p>
852      *
853      * @param year of <code>XMLGregorianCalendar</code> to be created.
854      * @param month of <code>XMLGregorianCalendar</code> to be created.
855      * @param day of <code>XMLGregorianCalendar</code> to be created.
856      * @param hour of <code>XMLGregorianCalendar</code> to be created.
857      * @param minute of <code>XMLGregorianCalendar</code> to be created.
858      * @param second of <code>XMLGregorianCalendar</code> to be created.
859      * @param millisecond of <code>XMLGregorianCalendar</code> to be created.
860      * @param timezone of <code>XMLGregorianCalendar</code> to be created.
861      *
862      * @return <code>XMLGregorianCalendar</code> created from specified values.
863      *
864      * @throws IllegalArgumentException If any individual parameter's value is outside the maximum value constraint for the field
865      *   as determined by the Date/Time Data Mapping table in {@link XMLGregorianCalendar}
866      *   or if the composite values constitute an invalid <code>XMLGregorianCalendar</code> instance
867      *   as determined by {@link XMLGregorianCalendar#isValid()}.
868      */
869     public XMLGregorianCalendar newXMLGregorianCalendar(
870             final int year,
871             final int month,
872             final int day,
873             final int hour,
874             final int minute,
875             final int second,
876             final int millisecond,
877             final int timezone) {
878 
879             // year may be undefined
880             BigInteger realYear = (year != DatatypeConstants.FIELD_UNDEFINED) ? BigInteger.valueOf((long) year) : null;
881 
882             // millisecond may be undefined
883             // millisecond must be >= 0 millisecond <= 1000
884             BigDecimal realMillisecond = null; // undefined value
885             if (millisecond != DatatypeConstants.FIELD_UNDEFINED) {
886                     if (millisecond < 0 || millisecond > 1000) {
887                             throw new IllegalArgumentException(
888                                                     "javax.xml.datatype.DatatypeFactory#newXMLGregorianCalendar("
889                                                     + "int year, int month, int day, int hour, int minute, int second, int millisecond, int timezone)"
890                                                     + "with invalid millisecond: " + millisecond
891                                                     );
892                     }
893 
894                     realMillisecond = BigDecimal.valueOf((long) millisecond).movePointLeft(3);
895             }
896 
897             return newXMLGregorianCalendar(
898                     realYear,
899                     month,
900                     day,
901                     hour,
902                     minute,
903                     second,
904                     realMillisecond,
905                     timezone
906             );
907     }
908 
909     /**
910      * <p>Create a Java representation of XML Schema builtin datatype <code>date</code> or <code>g*</code>.</p>
911      *
912      * <p>For example, an instance of <code>gYear</code> can be created invoking this factory
913      * with <code>month</code> and <code>day</code> parameters set to
914      * {@link DatatypeConstants#FIELD_UNDEFINED}.</p>
915      *
916      * <p>A {@link DatatypeConstants#FIELD_UNDEFINED} value indicates that field is not set.</p>
917      *
918      * @param year of <code>XMLGregorianCalendar</code> to be created.
919      * @param month of <code>XMLGregorianCalendar</code> to be created.
920      * @param day of <code>XMLGregorianCalendar</code> to be created.
921      * @param timezone offset in minutes. {@link DatatypeConstants#FIELD_UNDEFINED} indicates optional field is not set.
922      *
923      * @return <code>XMLGregorianCalendar</code> created from parameter values.
924      *
925      * @see DatatypeConstants#FIELD_UNDEFINED
926      *
927      * @throws IllegalArgumentException If any individual parameter's value is outside the maximum value constraint for the field
928      *   as determined by the Date/Time Data Mapping table in {@link XMLGregorianCalendar}
929      *   or if the composite values constitute an invalid <code>XMLGregorianCalendar</code> instance
930      *   as determined by {@link XMLGregorianCalendar#isValid()}.
931      */
932     public XMLGregorianCalendar newXMLGregorianCalendarDate(
933             final int year,
934             final int month,
935             final int day,
936             final int timezone) {
937 
938             return newXMLGregorianCalendar(
939                     year,
940                     month,
941                     day,
942                     DatatypeConstants.FIELD_UNDEFINED, // hour
943                     DatatypeConstants.FIELD_UNDEFINED, // minute
944                     DatatypeConstants.FIELD_UNDEFINED, // second
945                     DatatypeConstants.FIELD_UNDEFINED, // millisecond
946                     timezone);
947             }
948 
949     /**
950      * <p>Create a Java instance of XML Schema builtin datatype <code>time</code>.</p>
951      *
952      * <p>A {@link DatatypeConstants#FIELD_UNDEFINED} value indicates that field is not set.</p>
953      *
954      * @param hours number of hours
955      * @param minutes number of minutes
956      * @param seconds number of seconds
957      * @param timezone offset in minutes. {@link DatatypeConstants#FIELD_UNDEFINED} indicates optional field is not set.
958      *
959      * @return <code>XMLGregorianCalendar</code> created from parameter values.
960      *
961      * @throws IllegalArgumentException If any individual parameter's value is outside the maximum value constraint for the field
962      *   as determined by the Date/Time Data Mapping table in {@link XMLGregorianCalendar}
963      *   or if the composite values constitute an invalid <code>XMLGregorianCalendar</code> instance
964      *   as determined by {@link XMLGregorianCalendar#isValid()}.
965      *
966      * @see DatatypeConstants#FIELD_UNDEFINED
967      */
968     public XMLGregorianCalendar newXMLGregorianCalendarTime(
969             final int hours,
970             final int minutes,
971             final int seconds,
972             final int timezone) {
973 
974             return newXMLGregorianCalendar(
975                     DatatypeConstants.FIELD_UNDEFINED, // Year
976                     DatatypeConstants.FIELD_UNDEFINED, // Month
977                     DatatypeConstants.FIELD_UNDEFINED, // Day
978                     hours,
979                     minutes,
980                     seconds,
981                     DatatypeConstants.FIELD_UNDEFINED, //Millisecond
982                     timezone);
983     }
984 
985     /**
986      * <p>Create a Java instance of XML Schema builtin datatype time.</p>
987      *
988      * <p>A <code>null</code> value indicates that field is not set.</p>
989      * <p>A {@link DatatypeConstants#FIELD_UNDEFINED} value indicates that field is not set.</p>
990      *
991      * @param hours number of hours
992      * @param minutes number of minutes
993      * @param seconds number of seconds
994      * @param fractionalSecond value of <code>null</code> indicates that this optional field is not set.
995      * @param timezone offset in minutes. {@link DatatypeConstants#FIELD_UNDEFINED} indicates optional field is not set.
996      *
997      * @return <code>XMLGregorianCalendar</code> created from parameter values.
998      *
999      * @see DatatypeConstants#FIELD_UNDEFINED
1000      *
1001      * @throws IllegalArgumentException If any individual parameter's value is outside the maximum value constraint for the field
1002      *   as determined by the Date/Time Data Mapping table in {@link XMLGregorianCalendar}
1003      *   or if the composite values constitute an invalid <code>XMLGregorianCalendar</code> instance
1004      *   as determined by {@link XMLGregorianCalendar#isValid()}.
1005      */
1006     public XMLGregorianCalendar newXMLGregorianCalendarTime(
1007             final int hours,
1008             final int minutes,
1009             final int seconds,
1010             final BigDecimal fractionalSecond,
1011             final int timezone) {
1012 
1013             return newXMLGregorianCalendar(
1014                     null, // year
1015                     DatatypeConstants.FIELD_UNDEFINED, // month
1016                     DatatypeConstants.FIELD_UNDEFINED, // day
1017                     hours,
1018                     minutes,
1019                     seconds,
1020                     fractionalSecond,
1021                     timezone);
1022             }
1023 
1024     /**
1025      * <p>Create a Java instance of XML Schema builtin datatype time.</p>
1026      *
1027      * <p>A {@link DatatypeConstants#FIELD_UNDEFINED} value indicates that field is not set.</p>
1028      *
1029      * @param hours number of hours
1030      * @param minutes number of minutes
1031      * @param seconds number of seconds
1032      * @param milliseconds number of milliseconds
1033      * @param timezone offset in minutes. {@link DatatypeConstants#FIELD_UNDEFINED} indicates optional field is not set.
1034      *
1035      * @return <code>XMLGregorianCalendar</code> created from parameter values.
1036      *
1037      * @see DatatypeConstants#FIELD_UNDEFINED
1038      *
1039      * @throws IllegalArgumentException If any individual parameter's value is outside the maximum value constraint for the field
1040      *   as determined by the Date/Time Data Mapping table in {@link XMLGregorianCalendar}
1041      *   or if the composite values constitute an invalid <code>XMLGregorianCalendar</code> instance
1042      *   as determined by {@link XMLGregorianCalendar#isValid()}.
1043      */
1044     public XMLGregorianCalendar newXMLGregorianCalendarTime(
1045             final int hours,
1046             final int minutes,
1047             final int seconds,
1048             final int milliseconds,
1049             final int timezone) {
1050 
1051             // millisecond may be undefined
1052             // millisecond must be >= 0 millisecond <= 1000
1053             BigDecimal realMilliseconds = null; // undefined value
1054             if (milliseconds != DatatypeConstants.FIELD_UNDEFINED) {
1055                     if (milliseconds < 0 || milliseconds > 1000) {
1056                             throw new IllegalArgumentException(
1057                                                     "javax.xml.datatype.DatatypeFactory#newXMLGregorianCalendarTime("
1058                                                     + "int hours, int minutes, int seconds, int milliseconds, int timezone)"
1059                                                     + "with invalid milliseconds: " + milliseconds
1060                                                     );
1061                     }
1062 
1063                     realMilliseconds = BigDecimal.valueOf((long) milliseconds).movePointLeft(3);
1064             }
1065 
1066             return newXMLGregorianCalendarTime(
1067                     hours,
1068                     minutes,
1069                     seconds,
1070                     realMilliseconds,
1071                     timezone
1072             );
1073     }
1074 }