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