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