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