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