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