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