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