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