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