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