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