--- old/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/datatype/DurationImpl.java Tue Feb 18 09:40:13 2014 +++ new/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/datatype/DurationImpl.java Tue Feb 18 09:40:13 2014 @@ -3,14 +3,15 @@ * DO NOT REMOVE OR ALTER! */ /* - * Copyright 2005 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -39,20 +40,20 @@ /** *
Immutable representation of a time span as defined in * the W3C XML Schema 1.0 specification.
- * + * *A Duration object represents a period of Gregorian time, * which consists of six fields (years, months, days, hours, * minutes, and seconds) plus a sign (+/-) field.
- * + * *The first five fields have non-negative (>=0) integers or null * (which represents that the field is not set), * and the seconds field has a non-negative decimal or null. - * A negative sign indicates a negative duration.
- * + * A negative sign indicates a negative duration. + * *This class provides a number of methods that make it easy * to use for the duration datatype of XML Schema 1.0 with * the errata.
- * + * *Duration objects only have partial order, where two values A and B * maybe either:
@@ -65,12 +66,12 @@ *For example, 30 days cannot be meaningfully compared to one month. * The {@link #compare(Duration)} method implements this * relationship.
- * + * *See the {@link #isLongerThan(Duration)} method for details about * the order relationship among {@link Duration} objects.
- * - * - * + * + * + * *This class provides a set of basic arithmetic operations, such * as addition, subtraction and multiplication. @@ -78,16 +79,16 @@ * fail for some combinations of operations. For example, you cannot * subtract 15 days from 1 month. See the javadoc of those methods * for detailed conditions where this could happen.
- * + * *Also, division of a duration by a number is not provided because * the {@link Duration} class can only deal with finite precision - * decimal numbers. For example, one cannot represent 1 sec divided by 3.
- * + * decimal numbers. For example, one cannot represent 1 sec divided by 3. + * *However, you could substitute a division by 3 with multiplying * by numbers such as 0.3 or 0.333.
* * - * + * ** Because some operations of {@link Duration} rely on {@link Calendar} @@ -94,8 +95,8 @@ * even though {@link Duration} can hold very large or very small values, * some of the methods may not work correctly on such {@link Duration}s. * The impacted methods document their dependency on {@link Calendar}. - * - * + * + * * @author Kohsuke Kawaguchi * @author Joseph Fialli * @version $Revision: 1.8 $, $Date: 2010/05/19 23:20:06 $ @@ -103,27 +104,23 @@ * @see XMLGregorianCalendar#add(Duration) */ class DurationImpl - extends Duration - implements Serializable { + extends Duration + implements Serializable { + /** - *
Number of Fields.
- */ - private static final int FIELD_NUM = 6; - - /** *Internal array of value Fields.
*/ - private static final DatatypeConstants.Field[] FIELDS = new DatatypeConstants.Field[]{ - DatatypeConstants.YEARS, - DatatypeConstants.MONTHS, - DatatypeConstants.DAYS, - DatatypeConstants.HOURS, - DatatypeConstants.MINUTES, - DatatypeConstants.SECONDS - }; + private static final DatatypeConstants.Field[] FIELDS = new DatatypeConstants.Field[]{ + DatatypeConstants.YEARS, + DatatypeConstants.MONTHS, + DatatypeConstants.DAYS, + DatatypeConstants.HOURS, + DatatypeConstants.MINUTES, + DatatypeConstants.SECONDS + }; - /** + /** *Internal array of value Field ids.
*/ private static final int[] FIELD_IDS = { @@ -141,9 +138,9 @@ private static final TimeZone GMT = TimeZone.getTimeZone("GMT"); /** - *BigDecimal value of 0.
- */ - private static final BigDecimal ZERO = BigDecimal.valueOf((long) 0); + *BigDecimal value of 0.
+ */ + private static final BigDecimal ZERO = BigDecimal.valueOf(0); /** *Indicates the sign. -1, 0 or 1 if the duration is negative, @@ -186,48 +183,48 @@ */ protected BigDecimal seconds; - /** - * Returns the sign of this duration in -1,0, or 1. - * - * @return - * -1 if this duration is negative, 0 if the duration is zero, - * and 1 if the duration is postive. - */ - public int getSign() { + /** + * Returns the sign of this duration in -1,0, or 1. + * + * @return + * -1 if this duration is negative, 0 if the duration is zero, + * and 1 if the duration is postive. + */ + public int getSign() { - return signum; - } + return signum; + } - /** - * TODO: Javadoc - * @param isPositive Sign. - * - * @return 1 if positive, else -1. - */ + /** + * TODO: Javadoc + * @param isPositive Sign. + * + * @return 1 if positive, else -1. + */ protected int calcSignum(boolean isPositive) { if ((years == null || years.signum() == 0) - && (months == null || months.signum() == 0) - && (days == null || days.signum() == 0) - && (hours == null || hours.signum() == 0) - && (minutes == null || minutes.signum() == 0) - && (seconds == null || seconds.signum() == 0)) { + && (months == null || months.signum() == 0) + && (days == null || days.signum() == 0) + && (hours == null || hours.signum() == 0) + && (minutes == null || minutes.signum() == 0) + && (seconds == null || seconds.signum() == 0)) { return 0; - } + } - if (isPositive) { - return 1; - } else { - return -1; - } - + if (isPositive) { + return 1; + } + else { + return -1; + } } - + /** *
Constructs a new Duration object by specifying each field individually.
- * + * *All the parameters are optional as long as at least one field is present. * If specified, parameters have to be zero or positive.
- * + * * @param isPositive Set tofalse
to create a negative duration. When the length
* of the duration is zero, this parameter will be ignored.
* @param years of this Duration
@@ -236,7 +233,7 @@
* @param hours of this Duration
* @param minutes of this Duration
* @param seconds of this Duration
- *
+ *
* @throws IllegalArgumentException
* If years, months, days, hours, minutes and
* seconds parameters are all null
. Or if any
@@ -250,7 +247,7 @@
BigInteger hours,
BigInteger minutes,
BigDecimal seconds) {
-
+
this.years = years;
this.months = months;
this.days = days;
@@ -279,48 +276,48 @@
testNonNegative(minutes, DatatypeConstants.MINUTES);
testNonNegative(seconds, DatatypeConstants.SECONDS);
}
-
+
/**
* Makes sure that the given number is non-negative. If it is not, * throw {@link IllegalArgumentException}.
- * + * * @param n Number to test. * @param f Field to test. */ protected static void testNonNegative(BigInteger n, DatatypeConstants.Field f) { if (n != null && n.signum() < 0) { - throw new IllegalArgumentException( + throw new IllegalArgumentException( DatatypeMessageFormatter.formatMessage(null, "NegativeField", new Object[]{f.toString()}) ); } } - + /** *Makes sure that the given number is non-negative. If it is not, * throw {@link IllegalArgumentException}.
- * + * * @param n Number to test. * @param f Field to test. */ protected static void testNonNegative(BigDecimal n, DatatypeConstants.Field f) { if (n != null && n.signum() < 0) { - + throw new IllegalArgumentException( - DatatypeMessageFormatter.formatMessage(null, "NegativeField", new Object[]{f.toString()}) + DatatypeMessageFormatter.formatMessage(null, "NegativeField", new Object[]{f.toString()}) ); } } - + /** *Constructs a new Duration object by specifying each field * individually.
- * + * *This method is functionally equivalent to * invoking another constructor by wrapping * all non-zero parameters into {@link BigInteger} and {@link BigDecimal}. * Zero value of int parameter is equivalent of null value of - * the corresponding field.
- * + * the corresponding field. + * * @see #DurationImpl(boolean, BigInteger, BigInteger, BigInteger, BigInteger, * BigInteger, BigDecimal) */ @@ -342,28 +339,28 @@ seconds != DatatypeConstants.FIELD_UNDEFINED ? new BigDecimal(String.valueOf(seconds)) : null); } - /** - * TODO: Javadoc - * - * @param i int to convert to BigInteger. - * - * @return BigInteger representation of int. - */ + /** + * TODO: Javadoc + * + * @param i int to convert to BigInteger. + * + * @return BigInteger representation of int. + */ protected static BigInteger wrap(final int i) { - // field may not be set - if (i == DatatypeConstants.FIELD_UNDEFINED) { - return null; - } - - // int -> BigInteger - return new BigInteger(String.valueOf(i)); + // field may not be set + if (i == DatatypeConstants.FIELD_UNDEFINED) { + return null; + } + + // int -> BigInteger + return BigInteger.valueOf(i); } - + /** *Constructs a new Duration object by specifying the duration * in milliseconds.
- * + * * @param durationInMilliSeconds * The length of the duration in milliseconds. */ @@ -373,7 +370,8 @@ if (l > 0) { signum = 1; - } else if (l < 0) { + } + else if (l < 0) { signum = -1; if (l == 0x8000000000000000L) { // negating 0x8000000000000000L causes an overflow @@ -380,7 +378,8 @@ l++; } l *= -1; - } else { + } + else { signum = 0; } @@ -418,27 +417,27 @@ + gregorianCalendar.get(Calendar.MILLISECOND); this.seconds = BigDecimal.valueOf(int2long, 3); } - + /** * Constructs a new Duration object by * parsing its string representation * "PnYnMnDTnHnMnS" as defined in XML Schema 1.0 section 3.2.6.1. - * + * ** The string representation may not have any leading * and trailing whitespaces. - * + * *
* For example, this method parses strings like * "P1D" (1 day), "-PT100S" (-100 sec.), "P1DT12H" (1 days and 12 hours). - * + * *
- * The parsing is done field by field so that + * The parsing is done field by field so that * the following holds for any lexically correct string x: *
* new Duration(x).toString().equals(x) *- * + * * Returns a non-null valid duration object that holds the value * indicated by the lexicalRepresentation parameter. * @@ -454,6 +453,10 @@ throws IllegalArgumentException { // only if I could use the JDK1.4 regular expression .... + if (lexicalRepresentation == null) { + throw new NullPointerException(); + } + final String s = lexicalRepresentation; boolean positive; int[] idx = new int[1]; @@ -460,15 +463,12 @@ int length = s.length(); boolean timeRequired = false; - if (lexicalRepresentation == null) { - throw new NullPointerException(); - } - idx[0] = 0; if (length != idx[0] && s.charAt(idx[0]) == '-') { idx[0]++; positive = false; - } else { + } + else { positive = true; } @@ -484,8 +484,8 @@ String[] dateParts = new String[3]; int[] datePartsIndex = new int[3]; while (length != idx[0] - && isDigit(s.charAt(idx[0])) - && dateLen < 3) { + && isDigit(s.charAt(idx[0])) + && dateLen < 3) { datePartsIndex[dateLen] = idx[0]; dateParts[dateLen++] = parsePiece(s, idx); } @@ -493,7 +493,8 @@ if (length != idx[0]) { if (s.charAt(idx[0]++) == 'T') { timeRequired = true; - } else { + } + else { throw new IllegalArgumentException(s); // ,idx[0]-1); } } @@ -502,8 +503,8 @@ String[] timeParts = new String[3]; int[] timePartsIndex = new int[3]; while (length != idx[0] - && isDigitOrPeriod(s.charAt(idx[0])) - && timeLen < 3) { + && isDigitOrPeriod(s.charAt(idx[0])) + && timeLen < 3) { timePartsIndex[timeLen] = idx[0]; timeParts[timeLen++] = parsePiece(s, idx); } @@ -533,38 +534,38 @@ seconds = parseBigDecimal(s, timeParts[2], timePartsIndex[2]); signum = calcSignum(positive); } - - + + /** * TODO: Javadoc - * + * * @param ch char to test. - * + * * @return true if ch is a digit, else false. */ private static boolean isDigit(char ch) { return '0' <= ch && ch <= '9'; } - + /** * TODO: Javadoc - * + * * @param ch to test. - * + * * @return true if ch is a digit or a period, else false. */ private static boolean isDigitOrPeriod(char ch) { return isDigit(ch) || ch == '.'; } - + /** * TODO: Javadoc - * + * * @param whole String to parse. * @param idx TODO: ??? - * + * * @return Result of parsing. - * + * * @throws IllegalArgumentException If whole cannot be parsed. */ private static String parsePiece(String whole, int[] idx) @@ -582,16 +583,16 @@ return whole.substring(start, idx[0]); } - + /** * TODO: Javadoc. - * + * * @param whole TODO: ??? * @param parts TODO: ??? * @param partsIndex TODO: ??? * @param len TODO: ??? * @param tokens TODO: ??? - * + * * @throws IllegalArgumentException TODO: ??? */ private static void organizeParts( @@ -604,6 +605,9 @@ int idx = tokens.length(); for (int i = len - 1; i >= 0; i--) { + if (parts[i] == null) { + throw new IllegalArgumentException(whole); + } int nidx = tokens.lastIndexOf( parts[i].charAt(parts[i].length() - 1), @@ -624,16 +628,16 @@ parts[idx] = null; } } - + /** * TODO: Javadoc - * + * * @param whole TODO: ???. * @param part TODO: ???. * @param index TODO: ???. - * + * * @return TODO: ???. - * + * * @throws IllegalArgumentException TODO: ???. */ private static BigInteger parseBigInteger( @@ -651,16 +655,16 @@ // throw new ParseException( whole, index ); // } } - + /** * TODO: Javadoc. - * + * * @param whole TODO: ???. * @param part TODO: ???. * @param index TODO: ???. - * + * * @return TODO: ???. - * + * * @throws IllegalArgumentException TODO: ???. */ private static BigDecimal parseBigDecimal( @@ -679,7 +683,7 @@ // throw new ParseException( whole, index ); // } } - + /** *
Four constants defined for the comparison of durations.
*/ @@ -689,213 +693,212 @@ XMLGregorianCalendarImpl.parse("1903-03-01T00:00:00Z"), XMLGregorianCalendarImpl.parse("1903-07-01T00:00:00Z") }; - - /** - *Partial order relation comparison with this Duration
instance.
Comparison result must be in accordance with - * W3C XML Schema 1.0 Part 2, Section 3.2.7.6.2, - * Order relation on duration.
- * - *Return:
- *Duration
is shorter than duration
parameterDuration
is equal to duration
parameterDuration
is longer than duration
parameterthis
Duration
and duration
parameter as
- * {@link DatatypeConstants#LESSER}, {@link DatatypeConstants#EQUAL}, {@link DatatypeConstants#GREATER}
- * or {@link DatatypeConstants#INDETERMINATE}.
- *
- * @throws UnsupportedOperationException If the underlying implementation
- * cannot reasonably process the request, e.g. W3C XML Schema allows for
- * arbitrarily large/small/precise values, the request may be beyond the
- * implementations capability.
- * @throws NullPointerException if duration
is null
.
- *
- * @see #isShorterThan(Duration)
- * @see #isLongerThan(Duration)
- */
+
+ /**
+ * Partial order relation comparison with this Duration
instance.
Comparison result must be in accordance with + * W3C XML Schema 1.0 Part 2, Section 3.2.7.6.2, + * Order relation on duration.
+ * + *Return:
+ *Duration
is shorter than duration
parameterDuration
is equal to duration
parameterDuration
is longer than duration
parameterthis
Duration
and duration
parameter as
+ * {@link DatatypeConstants#LESSER}, {@link DatatypeConstants#EQUAL}, {@link DatatypeConstants#GREATER}
+ * or {@link DatatypeConstants#INDETERMINATE}.
+ *
+ * @throws UnsupportedOperationException If the underlying implementation
+ * cannot reasonably process the request, e.g. W3C XML Schema allows for
+ * arbitrarily large/small/precise values, the request may be beyond the
+ * implementations capability.
+ * @throws NullPointerException if duration
is null
.
+ *
+ * @see #isShorterThan(Duration)
+ * @see #isLongerThan(Duration)
+ */
public int compare(Duration rhs) {
+
+ BigInteger maxintAsBigInteger = BigInteger.valueOf(Integer.MAX_VALUE);
- BigInteger maxintAsBigInteger = BigInteger.valueOf((long) Integer.MAX_VALUE);
- BigInteger minintAsBigInteger = BigInteger.valueOf((long) Integer.MIN_VALUE);
-
- // check for fields that are too large in this Duration
- if (years != null && years.compareTo(maxintAsBigInteger) == 1) {
+ // check for fields that are too large in this Duration
+ if (years != null && years.compareTo(maxintAsBigInteger) == 1) {
throw new UnsupportedOperationException(
- DatatypeMessageFormatter.formatMessage(null, "TooLarge",
+ DatatypeMessageFormatter.formatMessage(null, "TooLarge",
new Object[]{this.getClass().getName() + "#compare(Duration duration)" + DatatypeConstants.YEARS.toString(), years.toString()})
- //this.getClass().getName() + "#compare(Duration duration)"
- //+ " years too large to be supported by this implementation "
- //+ years.toString()
- );
- }
- if (months != null && months.compareTo(maxintAsBigInteger) == 1) {
- throw new UnsupportedOperationException(
- DatatypeMessageFormatter.formatMessage(null, "TooLarge",
+ //this.getClass().getName() + "#compare(Duration duration)"
+ //+ " years too large to be supported by this implementation "
+ //+ years.toString()
+ );
+ }
+ if (months != null && months.compareTo(maxintAsBigInteger) == 1) {
+ throw new UnsupportedOperationException(
+ DatatypeMessageFormatter.formatMessage(null, "TooLarge",
new Object[]{this.getClass().getName() + "#compare(Duration duration)" + DatatypeConstants.MONTHS.toString(), months.toString()})
-
- //this.getClass().getName() + "#compare(Duration duration)"
- //+ " months too large to be supported by this implementation "
- //+ months.toString()
- );
- }
- if (days != null && days.compareTo(maxintAsBigInteger) == 1) {
- throw new UnsupportedOperationException(
- DatatypeMessageFormatter.formatMessage(null, "TooLarge",
+
+ //this.getClass().getName() + "#compare(Duration duration)"
+ //+ " months too large to be supported by this implementation "
+ //+ months.toString()
+ );
+ }
+ if (days != null && days.compareTo(maxintAsBigInteger) == 1) {
+ throw new UnsupportedOperationException(
+ DatatypeMessageFormatter.formatMessage(null, "TooLarge",
new Object[]{this.getClass().getName() + "#compare(Duration duration)" + DatatypeConstants.DAYS.toString(), days.toString()})
-
- //this.getClass().getName() + "#compare(Duration duration)"
- //+ " days too large to be supported by this implementation "
- //+ days.toString()
- );
- }
- if (hours != null && hours.compareTo(maxintAsBigInteger) == 1) {
- throw new UnsupportedOperationException(
- DatatypeMessageFormatter.formatMessage(null, "TooLarge",
+
+ //this.getClass().getName() + "#compare(Duration duration)"
+ //+ " days too large to be supported by this implementation "
+ //+ days.toString()
+ );
+ }
+ if (hours != null && hours.compareTo(maxintAsBigInteger) == 1) {
+ throw new UnsupportedOperationException(
+ DatatypeMessageFormatter.formatMessage(null, "TooLarge",
new Object[]{this.getClass().getName() + "#compare(Duration duration)" + DatatypeConstants.HOURS.toString(), hours.toString()})
-
- //this.getClass().getName() + "#compare(Duration duration)"
- //+ " hours too large to be supported by this implementation "
- //+ hours.toString()
- );
- }
- if (minutes != null && minutes.compareTo(maxintAsBigInteger) == 1) {
- throw new UnsupportedOperationException(
- DatatypeMessageFormatter.formatMessage(null, "TooLarge",
+
+ //this.getClass().getName() + "#compare(Duration duration)"
+ //+ " hours too large to be supported by this implementation "
+ //+ hours.toString()
+ );
+ }
+ if (minutes != null && minutes.compareTo(maxintAsBigInteger) == 1) {
+ throw new UnsupportedOperationException(
+ DatatypeMessageFormatter.formatMessage(null, "TooLarge",
new Object[]{this.getClass().getName() + "#compare(Duration duration)" + DatatypeConstants.MINUTES.toString(), minutes.toString()})
-
- //this.getClass().getName() + "#compare(Duration duration)"
- //+ " minutes too large to be supported by this implementation "
- //+ minutes.toString()
- );
- }
- if (seconds != null && seconds.toBigInteger().compareTo(maxintAsBigInteger) == 1) {
- throw new UnsupportedOperationException(
- DatatypeMessageFormatter.formatMessage(null, "TooLarge",
- new Object[]{this.getClass().getName() + "#compare(Duration duration)" + DatatypeConstants.SECONDS.toString(), seconds.toString()})
-
- //this.getClass().getName() + "#compare(Duration duration)"
- //+ " seconds too large to be supported by this implementation "
- //+ seconds.toString()
- );
- }
-
- // check for fields that are too large in rhs Duration
- BigInteger rhsYears = (BigInteger) rhs.getField(DatatypeConstants.YEARS);
- if (rhsYears != null && rhsYears.compareTo(maxintAsBigInteger) == 1) {
- throw new UnsupportedOperationException(
- DatatypeMessageFormatter.formatMessage(null, "TooLarge",
+
+ //this.getClass().getName() + "#compare(Duration duration)"
+ //+ " minutes too large to be supported by this implementation "
+ //+ minutes.toString()
+ );
+ }
+ if (seconds != null && seconds.toBigInteger().compareTo(maxintAsBigInteger) == 1) {
+ throw new UnsupportedOperationException(
+ DatatypeMessageFormatter.formatMessage(null, "TooLarge",
+ new Object[]{this.getClass().getName() + "#compare(Duration duration)" + DatatypeConstants.SECONDS.toString(), toString(seconds)})
+
+ //this.getClass().getName() + "#compare(Duration duration)"
+ //+ " seconds too large to be supported by this implementation "
+ //+ seconds.toString()
+ );
+ }
+
+ // check for fields that are too large in rhs Duration
+ BigInteger rhsYears = (BigInteger) rhs.getField(DatatypeConstants.YEARS);
+ if (rhsYears != null && rhsYears.compareTo(maxintAsBigInteger) == 1) {
+ throw new UnsupportedOperationException(
+ DatatypeMessageFormatter.formatMessage(null, "TooLarge",
new Object[]{this.getClass().getName() + "#compare(Duration duration)" + DatatypeConstants.YEARS.toString(), rhsYears.toString()})
-
- //this.getClass().getName() + "#compare(Duration duration)"
- //+ " years too large to be supported by this implementation "
- //+ rhsYears.toString()
- );
- }
- BigInteger rhsMonths = (BigInteger) rhs.getField(DatatypeConstants.MONTHS);
- if (rhsMonths != null && rhsMonths.compareTo(maxintAsBigInteger) == 1) {
- throw new UnsupportedOperationException(
- DatatypeMessageFormatter.formatMessage(null, "TooLarge",
+
+ //this.getClass().getName() + "#compare(Duration duration)"
+ //+ " years too large to be supported by this implementation "
+ //+ rhsYears.toString()
+ );
+ }
+ BigInteger rhsMonths = (BigInteger) rhs.getField(DatatypeConstants.MONTHS);
+ if (rhsMonths != null && rhsMonths.compareTo(maxintAsBigInteger) == 1) {
+ throw new UnsupportedOperationException(
+ DatatypeMessageFormatter.formatMessage(null, "TooLarge",
new Object[]{this.getClass().getName() + "#compare(Duration duration)" + DatatypeConstants.MONTHS.toString(), rhsMonths.toString()})
-
- //this.getClass().getName() + "#compare(Duration duration)"
- //+ " months too large to be supported by this implementation "
- //+ rhsMonths.toString()
- );
- }
- BigInteger rhsDays = (BigInteger) rhs.getField(DatatypeConstants.DAYS);
- if (rhsDays != null && rhsDays.compareTo(maxintAsBigInteger) == 1) {
- throw new UnsupportedOperationException(
- DatatypeMessageFormatter.formatMessage(null, "TooLarge",
+
+ //this.getClass().getName() + "#compare(Duration duration)"
+ //+ " months too large to be supported by this implementation "
+ //+ rhsMonths.toString()
+ );
+ }
+ BigInteger rhsDays = (BigInteger) rhs.getField(DatatypeConstants.DAYS);
+ if (rhsDays != null && rhsDays.compareTo(maxintAsBigInteger) == 1) {
+ throw new UnsupportedOperationException(
+ DatatypeMessageFormatter.formatMessage(null, "TooLarge",
new Object[]{this.getClass().getName() + "#compare(Duration duration)" + DatatypeConstants.DAYS.toString(), rhsDays.toString()})
-
- //this.getClass().getName() + "#compare(Duration duration)"
- //+ " days too large to be supported by this implementation "
- //+ rhsDays.toString()
- );
- }
- BigInteger rhsHours = (BigInteger) rhs.getField(DatatypeConstants.HOURS);
- if (rhsHours != null && rhsHours.compareTo(maxintAsBigInteger) == 1) {
- throw new UnsupportedOperationException(
- DatatypeMessageFormatter.formatMessage(null, "TooLarge",
+
+ //this.getClass().getName() + "#compare(Duration duration)"
+ //+ " days too large to be supported by this implementation "
+ //+ rhsDays.toString()
+ );
+ }
+ BigInteger rhsHours = (BigInteger) rhs.getField(DatatypeConstants.HOURS);
+ if (rhsHours != null && rhsHours.compareTo(maxintAsBigInteger) == 1) {
+ throw new UnsupportedOperationException(
+ DatatypeMessageFormatter.formatMessage(null, "TooLarge",
new Object[]{this.getClass().getName() + "#compare(Duration duration)" + DatatypeConstants.HOURS.toString(), rhsHours.toString()})
-
- //this.getClass().getName() + "#compare(Duration duration)"
- //+ " hours too large to be supported by this implementation "
- //+ rhsHours.toString()
- );
- }
- BigInteger rhsMinutes = (BigInteger) rhs.getField(DatatypeConstants.MINUTES);
- if (rhsMinutes != null && rhsMinutes.compareTo(maxintAsBigInteger) == 1) {
- throw new UnsupportedOperationException(
- DatatypeMessageFormatter.formatMessage(null, "TooLarge",
+
+ //this.getClass().getName() + "#compare(Duration duration)"
+ //+ " hours too large to be supported by this implementation "
+ //+ rhsHours.toString()
+ );
+ }
+ BigInteger rhsMinutes = (BigInteger) rhs.getField(DatatypeConstants.MINUTES);
+ if (rhsMinutes != null && rhsMinutes.compareTo(maxintAsBigInteger) == 1) {
+ throw new UnsupportedOperationException(
+ DatatypeMessageFormatter.formatMessage(null, "TooLarge",
new Object[]{this.getClass().getName() + "#compare(Duration duration)" + DatatypeConstants.MINUTES.toString(), rhsMinutes.toString()})
-
- //this.getClass().getName() + "#compare(Duration duration)"
- //+ " minutes too large to be supported by this implementation "
- //+ rhsMinutes.toString()
- );
- }
- BigDecimal rhsSecondsAsBigDecimal = (BigDecimal) rhs.getField(DatatypeConstants.SECONDS);
- BigInteger rhsSeconds = null;
+
+ //this.getClass().getName() + "#compare(Duration duration)"
+ //+ " minutes too large to be supported by this implementation "
+ //+ rhsMinutes.toString()
+ );
+ }
+ BigDecimal rhsSecondsAsBigDecimal = (BigDecimal) rhs.getField(DatatypeConstants.SECONDS);
+ BigInteger rhsSeconds = null;
if ( rhsSecondsAsBigDecimal != null ) {
rhsSeconds = rhsSecondsAsBigDecimal.toBigInteger();
}
- if (rhsSeconds != null && rhsSeconds.compareTo(maxintAsBigInteger) == 1) {
- throw new UnsupportedOperationException(
- DatatypeMessageFormatter.formatMessage(null, "TooLarge",
+ if (rhsSeconds != null && rhsSeconds.compareTo(maxintAsBigInteger) == 1) {
+ throw new UnsupportedOperationException(
+ DatatypeMessageFormatter.formatMessage(null, "TooLarge",
new Object[]{this.getClass().getName() + "#compare(Duration duration)" + DatatypeConstants.SECONDS.toString(), rhsSeconds.toString()})
+
+ //this.getClass().getName() + "#compare(Duration duration)"
+ //+ " seconds too large to be supported by this implementation "
+ //+ rhsSeconds.toString()
+ );
+ }
- //this.getClass().getName() + "#compare(Duration duration)"
- //+ " seconds too large to be supported by this implementation "
- //+ rhsSeconds.toString()
- );
- }
+ // turn this Duration into a GregorianCalendar
+ GregorianCalendar lhsCalendar = new GregorianCalendar(
+ 1970,
+ 1,
+ 1,
+ 0,
+ 0,
+ 0);
+ lhsCalendar.add(GregorianCalendar.YEAR, getYears() * getSign());
+ lhsCalendar.add(GregorianCalendar.MONTH, getMonths() * getSign());
+ lhsCalendar.add(GregorianCalendar.DAY_OF_YEAR, getDays() * getSign());
+ lhsCalendar.add(GregorianCalendar.HOUR_OF_DAY, getHours() * getSign());
+ lhsCalendar.add(GregorianCalendar.MINUTE, getMinutes() * getSign());
+ lhsCalendar.add(GregorianCalendar.SECOND, getSeconds() * getSign());
+
+ // turn compare Duration into a GregorianCalendar
+ GregorianCalendar rhsCalendar = new GregorianCalendar(
+ 1970,
+ 1,
+ 1,
+ 0,
+ 0,
+ 0);
+ rhsCalendar.add(GregorianCalendar.YEAR, rhs.getYears() * rhs.getSign());
+ rhsCalendar.add(GregorianCalendar.MONTH, rhs.getMonths() * rhs.getSign());
+ rhsCalendar.add(GregorianCalendar.DAY_OF_YEAR, rhs.getDays() * rhs.getSign());
+ rhsCalendar.add(GregorianCalendar.HOUR_OF_DAY, rhs.getHours() * rhs.getSign());
+ rhsCalendar.add(GregorianCalendar.MINUTE, rhs.getMinutes() * rhs.getSign());
+ rhsCalendar.add(GregorianCalendar.SECOND, rhs.getSeconds() * rhs.getSign());
+
+
+ if (lhsCalendar.equals(rhsCalendar)) {
+ return DatatypeConstants.EQUAL;
+ }
- // turn this Duration into a GregorianCalendar
- GregorianCalendar lhsCalendar = new GregorianCalendar(
- 1970,
- 1,
- 1,
- 0,
- 0,
- 0);
- lhsCalendar.add(GregorianCalendar.YEAR, getYears() * getSign());
- lhsCalendar.add(GregorianCalendar.MONTH, getMonths() * getSign());
- lhsCalendar.add(GregorianCalendar.DAY_OF_YEAR, getDays() * getSign());
- lhsCalendar.add(GregorianCalendar.HOUR_OF_DAY, getHours() * getSign());
- lhsCalendar.add(GregorianCalendar.MINUTE, getMinutes() * getSign());
- lhsCalendar.add(GregorianCalendar.SECOND, getSeconds() * getSign());
-
- // turn compare Duration into a GregorianCalendar
- GregorianCalendar rhsCalendar = new GregorianCalendar(
- 1970,
- 1,
- 1,
- 0,
- 0,
- 0);
- rhsCalendar.add(GregorianCalendar.YEAR, rhs.getYears() * rhs.getSign());
- rhsCalendar.add(GregorianCalendar.MONTH, rhs.getMonths() * rhs.getSign());
- rhsCalendar.add(GregorianCalendar.DAY_OF_YEAR, rhs.getDays() * rhs.getSign());
- rhsCalendar.add(GregorianCalendar.HOUR_OF_DAY, rhs.getHours() * rhs.getSign());
- rhsCalendar.add(GregorianCalendar.MINUTE, rhs.getMinutes() * rhs.getSign());
- rhsCalendar.add(GregorianCalendar.SECOND, rhs.getSeconds() * rhs.getSign());
-
-
- if (lhsCalendar.equals(rhsCalendar)) {
- return DatatypeConstants.EQUAL;
- }
-
- return compareDates(this, rhs);
+ return compareDates(this, rhs);
}
-
+
/**
* Compares 2 given durations. (refer to W3C Schema Datatypes "3.2.6 duration")
*
@@ -909,13 +912,13 @@
* return GREATER_THAN if date1 is greater than OR equal to date2
*/
private int compareDates(Duration duration1, Duration duration2) {
-
- int resultA = DatatypeConstants.INDETERMINATE;
+
+ int resultA = DatatypeConstants.INDETERMINATE;
int resultB = DatatypeConstants.INDETERMINATE;
-
+
XMLGregorianCalendar tempA = (XMLGregorianCalendar)TEST_POINTS[0].clone();
XMLGregorianCalendar tempB = (XMLGregorianCalendar)TEST_POINTS[0].clone();
-
+
//long comparison algorithm is required
tempA.add(duration1);
tempB.add(duration2);
@@ -926,7 +929,7 @@
tempA = (XMLGregorianCalendar)TEST_POINTS[1].clone();
tempB = (XMLGregorianCalendar)TEST_POINTS[1].clone();
-
+
tempA.add(duration1);
tempB.add(duration2);
resultB = tempA.compare(tempB);
@@ -937,7 +940,7 @@
tempA = (XMLGregorianCalendar)TEST_POINTS[2].clone();
tempB = (XMLGregorianCalendar)TEST_POINTS[2].clone();
-
+
tempA.add(duration1);
tempB.add(duration2);
resultB = tempA.compare(tempB);
@@ -948,7 +951,7 @@
tempA = (XMLGregorianCalendar)TEST_POINTS[3].clone();
tempB = (XMLGregorianCalendar)TEST_POINTS[3].clone();
-
+
tempA.add(duration1);
tempB.add(duration2);
resultB = tempA.compare(tempB);
@@ -957,9 +960,9 @@
return resultA;
}
- private int compareResults(int resultA, int resultB){
+ private int compareResults(int resultA, int resultB) {
- if ( resultB == DatatypeConstants.INDETERMINATE ) {
+ if ( resultB == DatatypeConstants.INDETERMINATE ) {
return DatatypeConstants.INDETERMINATE;
}
else if ( resultA!=resultB) {
@@ -967,11 +970,11 @@
}
return resultA;
}
-
+
/**
* Returns a hash code consistent with the definition of the equals method.
- *
- * @see Object#hashCode()
+ *
+ * @see Object#hashCode()
*/
public int hashCode() {
// component wise hash is not correct because 1day = 24hours
@@ -979,23 +982,23 @@
this.addTo(cal);
return (int) getCalendarTimeInMillis(cal);
}
-
+
/**
* Returns a string representation of this duration object.
- *
+ *
* * The result is formatter according to the XML Schema 1.0 * spec and can be always parsed back later into the * equivalent duration object by * the {@link #DurationImpl(String)} constructor. - * + * *
* Formally, the following holds for any {@link Duration} - * object x. + * object x. *
* new Duration(x.toString()).equals(x) *- * + * * @return * Always return a non-null valid String object. */ @@ -1005,42 +1008,42 @@ buf.append('-'); } buf.append('P'); - + if (years != null) { - buf.append(years + "Y"); + buf.append(years).append('Y'); } if (months != null) { - buf.append(months + "M"); + buf.append(months).append('M'); } if (days != null) { - buf.append(days + "D"); + buf.append(days).append('D'); } if (hours != null || minutes != null || seconds != null) { buf.append('T'); if (hours != null) { - buf.append(hours + "H"); + buf.append(hours).append('H'); } if (minutes != null) { - buf.append(minutes + "M"); + buf.append(minutes).append('M'); } if (seconds != null) { - buf.append(toString(seconds) + "S"); + buf.append(toString(seconds)).append('S'); } } - + return buf.toString(); } /** *
Turns {@link BigDecimal} to a string representation.
- * + * *Due to a behavior change in the {@link BigDecimal#toString()} * method in JDK1.5, this had to be implemented here.
- * + * * @param bdBigDecimal
to format as a String
- *
- * @return String
representation of BigDecimal
+ *
+ * @return String
representation of BigDecimal
*/
private String toString(BigDecimal bd) {
String intString = bd.unscaledValue().toString();
@@ -1055,10 +1058,12 @@
int insertionPoint = intString.length() - scale;
if (insertionPoint == 0) { /* Point goes right before intVal */
return "0." + intString;
- } else if (insertionPoint > 0) { /* Point goes inside intVal */
+ }
+ else if (insertionPoint > 0) { /* Point goes inside intVal */
buf = new StringBuffer(intString);
buf.insert(insertionPoint, '.');
- } else { /* We must insert zeros between point and intVal */
+ }
+ else { /* We must insert zeros between point and intVal */
buf = new StringBuffer(3 - insertionPoint + intString.length());
buf.append("0.");
for (int i = 0; i < -insertionPoint; i++) {
@@ -1071,70 +1076,70 @@
/**
* Checks if a field is set.
- *
+ *
* A field of a duration object may or may not be present.
* This method can be used to test if a field is present.
- *
+ *
* @param field
* one of the six Field constants (YEARS,MONTHS,DAYS,HOURS,
* MINUTES, or SECONDS.)
* @return
* true if the field is present. false if not.
- *
+ *
* @throws NullPointerException
* If the field parameter is null.
*/
public boolean isSet(DatatypeConstants.Field field) {
-
- if (field == null) {
+
+ if (field == null) {
String methodName = "javax.xml.datatype.Duration" + "#isSet(DatatypeConstants.Field field)" ;
- throw new NullPointerException(
+ throw new NullPointerException(
//"cannot be called with field == null"
- DatatypeMessageFormatter.formatMessage(null, "FieldCannotBeNull", new Object[]{methodName})
- );
- }
+ DatatypeMessageFormatter.formatMessage(null, "FieldCannotBeNull", new Object[]{methodName})
+ );
+ }
+
+ if (field == DatatypeConstants.YEARS) {
+ return years != null;
+ }
- if (field == DatatypeConstants.YEARS) {
- return years != null;
- }
+ if (field == DatatypeConstants.MONTHS) {
+ return months != null;
+ }
- if (field == DatatypeConstants.MONTHS) {
- return months != null;
- }
+ if (field == DatatypeConstants.DAYS) {
+ return days != null;
+ }
- if (field == DatatypeConstants.DAYS) {
- return days != null;
- }
+ if (field == DatatypeConstants.HOURS) {
+ return hours != null;
+ }
- if (field == DatatypeConstants.HOURS) {
- return hours != null;
- }
-
- if (field == DatatypeConstants.MINUTES) {
- return minutes != null;
- }
-
- if (field == DatatypeConstants.SECONDS) {
- return seconds != null;
- }
+ if (field == DatatypeConstants.MINUTES) {
+ return minutes != null;
+ }
+
+ if (field == DatatypeConstants.SECONDS) {
+ return seconds != null;
+ }
String methodName = "javax.xml.datatype.Duration" + "#isSet(DatatypeConstants.Field field)";
-
+
throw new IllegalArgumentException(
- DatatypeMessageFormatter.formatMessage(null,"UnknownField", new Object[]{methodName, field.toString()})
- );
-
+ DatatypeMessageFormatter.formatMessage(null,"UnknownField", new Object[]{methodName, field.toString()})
+ );
+
}
-
+
/**
- * Gets the value of a field.
- *
+ * Gets the value of a field.
+ *
* Fields of a duration object may contain arbitrary large value.
* Therefore this method is designed to return a {@link Number} object.
- *
+ *
* In case of YEARS, MONTHS, DAYS, HOURS, and MINUTES, the returned
* number will be a non-negative integer. In case of seconds,
* the returned number may be a non-negative decimal value.
- *
+ *
* @param field
* one of the six Field constants (YEARS,MONTHS,DAYS,HOURS,
* MINUTES, or SECONDS.)
@@ -1144,73 +1149,73 @@
* represents its value. If it is not present, return null.
* For YEARS, MONTHS, DAYS, HOURS, and MINUTES, this method
* returns a {@link BigInteger} object. For SECONDS, this
- * method returns a {@link BigDecimal}.
- *
+ * method returns a {@link BigDecimal}.
+ *
* @throws NullPointerException
* If the field parameter is null.
*/
public Number getField(DatatypeConstants.Field field) {
- if (field == null) {
+ if (field == null) {
String methodName = "javax.xml.datatype.Duration" + "#isSet(DatatypeConstants.Field field) " ;
-
- throw new NullPointerException(
+
+ throw new NullPointerException(
DatatypeMessageFormatter.formatMessage(null,"FieldCannotBeNull", new Object[]{methodName})
);
- }
+ }
+
+ if (field == DatatypeConstants.YEARS) {
+ return years;
+ }
- if (field == DatatypeConstants.YEARS) {
- return years;
- }
+ if (field == DatatypeConstants.MONTHS) {
+ return months;
+ }
- if (field == DatatypeConstants.MONTHS) {
- return months;
- }
+ if (field == DatatypeConstants.DAYS) {
+ return days;
+ }
- if (field == DatatypeConstants.DAYS) {
- return days;
- }
+ if (field == DatatypeConstants.HOURS) {
+ return hours;
+ }
- if (field == DatatypeConstants.HOURS) {
- return hours;
- }
-
- if (field == DatatypeConstants.MINUTES) {
- return minutes;
- }
-
- if (field == DatatypeConstants.SECONDS) {
- return seconds;
- }
- /**
- throw new IllegalArgumentException(
- "javax.xml.datatype.Duration"
- + "#(getSet(DatatypeConstants.Field field) called with an unknown field: "
- + field.toString()
- );
+ if (field == DatatypeConstants.MINUTES) {
+ return minutes;
+ }
+
+ if (field == DatatypeConstants.SECONDS) {
+ return seconds;
+ }
+ /**
+ throw new IllegalArgumentException(
+ "javax.xml.datatype.Duration"
+ + "#(getSet(DatatypeConstants.Field field) called with an unknown field: "
+ + field.toString()
+ );
*/
String methodName = "javax.xml.datatype.Duration" + "#(getSet(DatatypeConstants.Field field)";
-
+
throw new IllegalArgumentException(
- DatatypeMessageFormatter.formatMessage(null,"UnknownField", new Object[]{methodName, field.toString()})
- );
-
+ DatatypeMessageFormatter.formatMessage(null,"UnknownField", new Object[]{methodName, field.toString()})
+ );
+
}
-
+
/**
* Obtains the value of the YEARS field as an integer value,
* or 0 if not present.
- *
+ *
* - * This method is a convenience method around the + * This method is a convenience method around the * {@link #getField(DatatypeConstants.Field)} method. - * + * *
* Note that since this method returns int, this
* method will return an incorrect value for {@link Duration}s
* with the year field that goes beyond the range of int.
* Use getField(YEARS)
to avoid possible loss of precision.
Duration
.
*/
public int getMonths() {
return getInt(DatatypeConstants.MONTHS);
}
-
+
/**
* Obtains the value of the DAYS field as an integer value,
* or 0 if not present.
- *
+ *
* This method works just like {@link #getYears()} except
* that this method works on the DAYS field.
- *
+ *
* @return Days of this Duration
.
*/
public int getDays() {
return getInt(DatatypeConstants.DAYS);
}
-
+
/**
* Obtains the value of the HOURS field as an integer value,
* or 0 if not present.
- *
+ *
* This method works just like {@link #getYears()} except
* that this method works on the HOURS field.
- *
+ *
* @return Hours of this Duration
.
- *
+ *
*/
public int getHours() {
return getInt(DatatypeConstants.HOURS);
}
-
+
/**
* Obtains the value of the MINUTES field as an integer value,
* or 0 if not present.
- *
+ *
* This method works just like {@link #getYears()} except
* that this method works on the MINUTES field.
- *
+ *
* @return Minutes of this Duration
.
- *
+ *
*/
public int getMinutes() {
return getInt(DatatypeConstants.MINUTES);
}
-
+
/**
* Obtains the value of the SECONDS field as an integer value,
* or 0 if not present.
- *
+ *
* This method works just like {@link #getYears()} except
* that this method works on the SECONDS field.
- *
+ *
* @return seconds in the integer value. The fraction of seconds
* will be discarded (for example, if the actual value is 2.5,
* this method returns 2)
@@ -1288,14 +1293,14 @@
public int getSeconds() {
return getInt(DatatypeConstants.SECONDS);
}
-
+
/**
* Return the requested field value as an int.
- * + * *If field is not set, i.e. == null, 0 is returned.
- * + * * @param field To get value for. - * + * * @return int value of field or 0 if field is not set. */ private int getInt(DatatypeConstants.Field field) { @@ -1302,74 +1307,74 @@ Number n = getField(field); if (n == null) { return 0; - } else { + } + else { return n.intValue(); } } - + /** *Returns the length of the duration in milli-seconds.
- * + * *If the seconds field carries more digits than milli-second order,
- * those will be simply discarded (or in other words, rounded to zero.)
+ * those will be simply discarded (or in other words, rounded to zero.)
* For example, for any Calendar value x
,
*- * + * *new Duration("PT10.00099S").getTimeInMills(x) == 10000
. *new Duration("-PT10.00099S").getTimeInMills(x) == -10000
. *
* Note that this method uses the {@link #addTo(Calendar)} method,
* which may work incorectly with {@link Duration} objects with
* very large values in its fields. See the {@link #addTo(Calendar)}
* method for details.
- *
+ *
* @param startInstant
* The length of a month/year varies. The startInstant
is
* used to disambiguate this variance. Specifically, this method
* returns the difference between startInstant
and
* startInstant+duration
- *
+ *
* @return milliseconds between startInstant
and
* startInstant
plus this Duration
*
- * @throws NullPointerException if startInstant
parameter
+ * @throws NullPointerException if startInstant
parameter
* is null.
- *
+ *
*/
public long getTimeInMillis(final Calendar startInstant) {
Calendar cal = (Calendar) startInstant.clone();
addTo(cal);
- return getCalendarTimeInMillis(cal)
- - getCalendarTimeInMillis(startInstant);
+ return getCalendarTimeInMillis(cal) - getCalendarTimeInMillis(startInstant);
}
-
+
/**
*
Returns the length of the duration in milli-seconds.
- * + * *If the seconds field carries more digits than milli-second order,
* those will be simply discarded (or in other words, rounded to zero.)
- * For example, for any Date
value x
,
Date
value x,
*
* new Duration("PT10.00099S").getTimeInMills(x) == 10000
.
* new Duration("-PT10.00099S").getTimeInMills(x) == -10000
.
*
- *
+ *
*
* Note that this method uses the {@link #addTo(Date)} method,
* which may work incorectly with {@link Duration} objects with
* very large values in its fields. See the {@link #addTo(Date)}
* method for details.
- *
+ *
* @param startInstant
* The length of a month/year varies. The startInstant
is
* used to disambiguate this variance. Specifically, this method
* returns the difference between startInstant
and
* startInstant+duration
.
- *
+ *
* @throws NullPointerException
* If the startInstant parameter is null.
- *
+ *
* @return milliseconds between startInstant
and
* startInstant
plus this Duration
*
@@ -1381,15 +1386,15 @@
this.addTo(cal);
return getCalendarTimeInMillis(cal) - startInstant.getTime();
}
-
+
// /**
// * Returns an equivalent but "normalized" duration value.
-// *
+// *
// * Intuitively, the normalization moves YEARS into
// * MONTHS (by x12) and moves DAYS, HOURS, and MINUTES fields
// * into SECONDS (by x86400, x3600, and x60 respectively.)
-// *
-// *
+// *
+// *
// * Formally, this method satisfies the following conditions:
// *
// * - x.normalize().equals(x)
@@ -1398,33 +1403,33 @@
// *
- !x.normalize().isSet(Duration.HOURS)
// *
- !x.normalize().isSet(Duration.MINUTES)
// *
-// *
+// *
// * @return
-// * always return a non-null valid value.
+// * always return a non-null valid value.
// */
// public Duration normalize() {
// return null;
// }
-
+
/**
* Converts the years and months fields into the days field
* by using a specific time instant as the reference point.
- *
+ *
* For example, duration of one month normalizes to 31 days
* given the start time instance "July 8th 2003, 17:40:32".
- *
+ *
* Formally, the computation is done as follows:
*
* - The given Calendar object is cloned.
*
- The years, months and days fields will be added to
* the {@link Calendar} object
- * by using the {@link Calendar#add(int,int)} method.
+ * by using the {@link Calendar#add(int,int)} method.
*
- The difference between two Calendars are computed in terms of days.
*
- The computed days, along with the hours, minutes and seconds
* fields of this duration object is used to construct a new
* Duration object.
*
- *
+ *
* Note that since the Calendar class uses int
to
* hold the value of year and month, this method may produce
* an unexpected result if this duration object holds
@@ -1431,9 +1436,9 @@
* a very large value in the years or months fields.
*
* @param startTimeInstant Calendar
reference point.
- *
+ *
* @return Duration
of years and months of this Duration
as days.
- *
+ *
* @throws NullPointerException If the startTimeInstant parameter is null.
*/
public Duration normalizeWith(Calendar startTimeInstant) {
@@ -1440,7 +1445,7 @@
Calendar c = (Calendar) startTimeInstant.clone();
- // using int may cause overflow, but
+ // using int may cause overflow, but
// Calendar internally treats value as int anyways.
c.add(Calendar.YEAR, getYears() * signum);
c.add(Calendar.MONTH, getMonths() * signum);
@@ -1451,39 +1456,39 @@
int days = (int) (diff / (1000L * 60L * 60L * 24L));
return new DurationImpl(
- days >= 0,
- null,
- null,
- wrap(Math.abs(days)),
- (BigInteger) getField(DatatypeConstants.HOURS),
- (BigInteger) getField(DatatypeConstants.MINUTES),
- (BigDecimal) getField(DatatypeConstants.SECONDS));
+ days >= 0,
+ null,
+ null,
+ wrap(Math.abs(days)),
+ (BigInteger) getField(DatatypeConstants.HOURS),
+ (BigInteger) getField(DatatypeConstants.MINUTES),
+ (BigDecimal) getField(DatatypeConstants.SECONDS));
}
-
+
/**
* Computes a new duration whose value is factor
times
* longer than the value of this duration.
- *
+ *
* This method is provided for the convenience.
* It is functionally equivalent to the following code:
*
* multiply(new BigDecimal(String.valueOf(factor)))
*
- *
+ *
* @param factor Factor times longer of new Duration
to create.
- *
+ *
* @return New Duration
that is factor
times longer than this Duration
.
- *
+ *
* @see #multiply(BigDecimal)
*/
public Duration multiply(int factor) {
return multiply(BigDecimal.valueOf(factor));
}
-
+
/**
* Computes a new duration whose value is factor
times
* longer than the value of this duration.
- *
+ *
*
* For example,
*
@@ -1491,12 +1496,12 @@
* "PT1M" (1 min) * "0.3" = "PT18S" (18 seconds)
* "P1M" (1 month) * "1.5" = IllegalStateException
*
- *
+ *
*
* Since the {@link Duration} class is immutable, this method
* doesn't change the value of this object. It simply computes
* a new Duration object and returns it.
- *
+ *
*
* The operation will be performed field by field with the precision
* of {@link BigDecimal}. Since all the fields except seconds are
@@ -1507,23 +1512,23 @@
* which will be carried down to "PT12H" (12 hours).
* When fractions of month cannot be meaningfully carried down
* to days, or year to months, this will cause an
- * {@link IllegalStateException} to be thrown.
+ * {@link IllegalStateException} to be thrown.
* For example if you multiple one month by 0.5.
- *
+ *
*
* To avoid {@link IllegalStateException}, use
* the {@link #normalizeWith(Calendar)} method to remove the years
* and months fields.
- *
+ *
* @param factor to multiply by
- *
+ *
* @return
* returns a non-null valid {@link Duration} object
*
- * @throws IllegalStateException if operation produces fraction in
+ * @throws IllegalStateException if operation produces fraction in
* the months field.
*
- * @throws NullPointerException if the factor
parameter is
+ * @throws NullPointerException if the factor
parameter is
* null
.
*
*/
@@ -1531,15 +1536,15 @@
BigDecimal carry = ZERO;
int factorSign = factor.signum();
factor = factor.abs();
-
+
BigDecimal[] buf = new BigDecimal[6];
-
+
for (int i = 0; i < 5; i++) {
BigDecimal bd = getFieldAsBigDecimal(FIELDS[i]);
bd = bd.multiply(factor).add(carry);
-
+
buf[i] = bd.setScale(0, BigDecimal.ROUND_DOWN);
-
+
bd = bd.subtract(buf[i]);
if (i == 1) {
if (bd.signum() != 0) {
@@ -1547,17 +1552,19 @@
} else {
carry = ZERO;
}
- } else {
+ }
+ else {
carry = bd.multiply(FACTORS[i]);
}
}
-
+
if (seconds != null) {
buf[5] = seconds.multiply(factor).add(carry);
- } else {
+ }
+ else {
buf[5] = carry;
}
-
+
return new DurationImpl(
this.signum * factorSign >= 0,
toBigInteger(buf[0], null == years),
@@ -1567,14 +1574,14 @@
toBigInteger(buf[4], null == minutes),
(buf[5].signum() == 0 && seconds == null) ? null : buf[5]);
}
-
+
/**
*
Gets the value of the field as a {@link BigDecimal}.
- *
+ *
* If the field is unset, return 0.
- *
+ *
* @param f Field to get value for.
- *
+ *
* @return non-null valid {@link BigDecimal}.
*/
private BigDecimal getFieldAsBigDecimal(DatatypeConstants.Field f) {
@@ -1581,25 +1588,28 @@
if (f == DatatypeConstants.SECONDS) {
if (seconds != null) {
return seconds;
- } else {
+ }
+ else {
return ZERO;
}
- } else {
+ }
+ else {
BigInteger bi = (BigInteger) getField(f);
if (bi == null) {
return ZERO;
- } else {
+ }
+ else {
return new BigDecimal(bi);
}
}
}
-
+
/**
* BigInteger value of BigDecimal value.
- *
+ *
* @param value Value to convert.
* @param canBeNull Can returned value be null?
- *
+ *
* @return BigInteger value of BigDecimal, possibly null.
*/
private static BigInteger toBigInteger(
@@ -1607,26 +1617,27 @@
boolean canBeNull) {
if (canBeNull && value.signum() == 0) {
return null;
- } else {
+ }
+ else {
return value.unscaledValue();
}
}
-
+
/**
* 1 unit of FIELDS[i] is equivalent to FACTORS[i]
unit of
* FIELDS[i+1].
*/
- private static final BigDecimal[] FACTORS = new BigDecimal[]{
+ private static final BigDecimal[] FACTORS = new BigDecimal[] {
BigDecimal.valueOf(12),
null/*undefined*/,
BigDecimal.valueOf(24),
BigDecimal.valueOf(60),
BigDecimal.valueOf(60)
- };
-
+ };
+
/**
* Computes a new duration whose value is this+rhs
.
- *
+ *
* For example,
*
* "1 day" + "-3 days" = "-2 days"
@@ -1635,11 +1646,11 @@
* "15 hours" + "-3 days" = "-(2 days,9 hours)"
* "1 year" + "-1 day" = IllegalStateException
*
- *
+ *
* Since there's no way to meaningfully subtract 1 day from 1 month,
* there are cases where the operation fails in
- * {@link IllegalStateException}.
- *
+ * {@link IllegalStateException}.
+ *
*
* Formally, the computation is defined as follows.
*
@@ -1647,23 +1658,23 @@
* are both positive without losing generality (i.e.,
* (-X)+Y=Y-X
, X+(-Y)=X-Y
,
* (-X)+(-Y)=-(X+Y)
)
- *
+ *
*
- * Addition of two positive {@link Duration}s are simply defined as
+ * Addition of two positive {@link Duration}s are simply defined as
* field by field addition where missing fields are treated as 0.
*
* A field of the resulting {@link Duration} will be unset if and
- * only if respective fields of two input {@link Duration}s are unset.
+ * only if respective fields of two input {@link Duration}s are unset.
*
* Note that lhs.add(rhs)
will be always successful if
* lhs.signum()*rhs.signum()!=-1
or both of them are
* normalized.
- *
+ *
* @param rhs Duration
to add to this Duration
- *
+ *
* @return
* non-null valid Duration object.
- *
+ *
* @throws NullPointerException
* If the rhs parameter is null.
* @throws IllegalStateException
@@ -1670,31 +1681,31 @@
* If two durations cannot be meaningfully added. For
* example, adding negative one day to one month causes
* this exception.
- *
- *
+ *
+ *
* @see #subtract(Duration)
*/
public Duration add(final Duration rhs) {
Duration lhs = this;
BigDecimal[] buf = new BigDecimal[6];
-
+
buf[0] = sanitize((BigInteger) lhs.getField(DatatypeConstants.YEARS),
- lhs.getSign()).add(sanitize((BigInteger) rhs.getField(DatatypeConstants.YEARS), rhs.getSign()));
+ lhs.getSign()).add(sanitize((BigInteger) rhs.getField(DatatypeConstants.YEARS), rhs.getSign()));
buf[1] = sanitize((BigInteger) lhs.getField(DatatypeConstants.MONTHS),
- lhs.getSign()).add(sanitize((BigInteger) rhs.getField(DatatypeConstants.MONTHS), rhs.getSign()));
+ lhs.getSign()).add(sanitize((BigInteger) rhs.getField(DatatypeConstants.MONTHS), rhs.getSign()));
buf[2] = sanitize((BigInteger) lhs.getField(DatatypeConstants.DAYS),
- lhs.getSign()).add(sanitize((BigInteger) rhs.getField(DatatypeConstants.DAYS), rhs.getSign()));
+ lhs.getSign()).add(sanitize((BigInteger) rhs.getField(DatatypeConstants.DAYS), rhs.getSign()));
buf[3] = sanitize((BigInteger) lhs.getField(DatatypeConstants.HOURS),
- lhs.getSign()).add(sanitize((BigInteger) rhs.getField(DatatypeConstants.HOURS), rhs.getSign()));
+ lhs.getSign()).add(sanitize((BigInteger) rhs.getField(DatatypeConstants.HOURS), rhs.getSign()));
buf[4] = sanitize((BigInteger) lhs.getField(DatatypeConstants.MINUTES),
- lhs.getSign()).add(sanitize((BigInteger) rhs.getField(DatatypeConstants.MINUTES), rhs.getSign()));
+ lhs.getSign()).add(sanitize((BigInteger) rhs.getField(DatatypeConstants.MINUTES), rhs.getSign()));
buf[5] = sanitize((BigDecimal) lhs.getField(DatatypeConstants.SECONDS),
- lhs.getSign()).add(sanitize((BigDecimal) rhs.getField(DatatypeConstants.SECONDS), rhs.getSign()));
-
+ lhs.getSign()).add(sanitize((BigDecimal) rhs.getField(DatatypeConstants.SECONDS), rhs.getSign()));
+
// align sign
alignSigns(buf, 0, 2); // Y,M
alignSigns(buf, 2, 6); // D,h,m,s
-
+
// make sure that the sign bit is consistent across all 6 fields.
int s = 0;
for (int i = 0; i < 6; i++) {
@@ -1705,28 +1716,28 @@
s = buf[i].signum();
}
}
-
+
return new DurationImpl(
s >= 0,
toBigInteger(sanitize(buf[0], s),
- lhs.getField(DatatypeConstants.YEARS) == null && rhs.getField(DatatypeConstants.YEARS) == null),
+ lhs.getField(DatatypeConstants.YEARS) == null && rhs.getField(DatatypeConstants.YEARS) == null),
toBigInteger(sanitize(buf[1], s),
- lhs.getField(DatatypeConstants.MONTHS) == null && rhs.getField(DatatypeConstants.MONTHS) == null),
+ lhs.getField(DatatypeConstants.MONTHS) == null && rhs.getField(DatatypeConstants.MONTHS) == null),
toBigInteger(sanitize(buf[2], s),
- lhs.getField(DatatypeConstants.DAYS) == null && rhs.getField(DatatypeConstants.DAYS) == null),
+ lhs.getField(DatatypeConstants.DAYS) == null && rhs.getField(DatatypeConstants.DAYS) == null),
toBigInteger(sanitize(buf[3], s),
- lhs.getField(DatatypeConstants.HOURS) == null && rhs.getField(DatatypeConstants.HOURS) == null),
+ lhs.getField(DatatypeConstants.HOURS) == null && rhs.getField(DatatypeConstants.HOURS) == null),
toBigInteger(sanitize(buf[4], s),
- lhs.getField(DatatypeConstants.MINUTES) == null && rhs.getField(DatatypeConstants.MINUTES) == null),
+ lhs.getField(DatatypeConstants.MINUTES) == null && rhs.getField(DatatypeConstants.MINUTES) == null),
(buf[5].signum() == 0
&& lhs.getField(DatatypeConstants.SECONDS) == null
&& rhs.getField(DatatypeConstants.SECONDS) == null) ? null : sanitize(buf[5], s));
}
-
+
private static void alignSigns(BigDecimal[] buf, int start, int end) {
// align sign
boolean touched;
-
+
do { // repeat until all the sign bits become consistent
touched = false;
int s = 0; // sign of the left fields
@@ -1755,7 +1766,7 @@
}
} while (touched);
}
-
+
/**
* Compute value*signum
where value==null is treated as
* value==0.
@@ -1773,13 +1784,13 @@
}
return new BigDecimal(value.negate());
}
-
+
/**
* Compute value*signum
where value==null
is treated as value==0
.
- *
+ *
* @param value Value to sanitize.
* @param signum 0 to sanitize to 0, > 0 to sanitize to value
, < 0 to sanitize to negative value
.
- *
+ *
* @return non-null {@link BigDecimal}.
*/
static BigDecimal sanitize(BigDecimal value, int signum) {
@@ -1791,10 +1802,10 @@
}
return value.negate();
}
-
+
/**
* Computes a new duration whose value is this-rhs
.
- *
+ *
* For example:
*
* "1 day" - "-3 days" = "4 days"
@@ -1803,57 +1814,57 @@
* "15 hours" - "-3 days" = "3 days and 15 hours"
* "1 year" - "-1 day" = "1 year and 1 day"
*
- *
+ *
* Since there's no way to meaningfully subtract 1 day from 1 month,
- * there are cases where the operation fails in {@link IllegalStateException}.
- *
+ * there are cases where the operation fails in {@link IllegalStateException}.
+ *
* Formally the computation is defined as follows.
* First, we can assume that two {@link Duration}s are both positive
* without losing generality. (i.e.,
* (-X)-Y=-(X+Y)
, X-(-Y)=X+Y
,
* (-X)-(-Y)=-(X-Y)
)
- *
+ *
* Then two durations are subtracted field by field.
* If the sign of any non-zero field F is different from
* the sign of the most significant field,
* 1 (if F is negative) or -1 (otherwise)
* will be borrowed from the next bigger unit of F.
- *
+ *
* This process is repeated until all the non-zero fields have
- * the same sign.
- *
+ * the same sign.
+ *
* If a borrow occurs in the days field (in other words, if
* the computation needs to borrow 1 or -1 month to compensate
* days), then the computation fails by throwing an
* {@link IllegalStateException}.
- *
+ *
* @param rhs Duration
to substract from this Duration
.
- *
+ *
* @return New Duration
created from subtracting rhs
from this Duration
.
- *
+ *
* @throws IllegalStateException
* If two durations cannot be meaningfully subtracted. For
* example, subtracting one day from one month causes
* this exception.
- *
+ *
* @throws NullPointerException
* If the rhs parameter is null.
- *
+ *
* @see #add(Duration)
*/
public Duration subtract(final Duration rhs) {
return add(rhs.negate());
}
-
+
/**
* Returns a new {@link Duration} object whose
* value is -this
.
- *
+ *
*
* Since the {@link Duration} class is immutable, this method
* doesn't change the value of this object. It simply computes
* a new Duration object and returns it.
- *
+ *
* @return
* always return a non-null valid {@link Duration} object.
*/
@@ -1867,10 +1878,10 @@
minutes,
seconds);
}
-
+
/**
* Returns the sign of this duration in -1,0, or 1.
- *
+ *
* @return
* -1 if this duration is negative, 0 if the duration is zero,
* and 1 if the duration is postive.
@@ -1878,11 +1889,11 @@
public int signum() {
return signum;
}
-
-
+
+
/**
* Adds this duration to a {@link Calendar} object.
- *
+ *
*
* Calls {@link java.util.Calendar#add(int,int)} in the
* order of YEARS, MONTHS, DAYS, HOURS, MINUTES, SECONDS, and MILLISECONDS
@@ -1889,22 +1900,22 @@
* if those fields are present. Because the {@link Calendar} class
* uses int to hold values, there are cases where this method
* won't work correctly (for example if values of fields
- * exceed the range of int.)
+ * exceed the range of int.)
*
- *
+ *
*
* Also, since this duration class is a Gregorian duration, this
* method will not work correctly if the given {@link Calendar}
- * object is based on some other calendar systems.
+ * object is based on some other calendar systems.
*
- *
+ *
*
* Any fractional parts of this {@link Duration} object
* beyond milliseconds will be simply ignored. For example, if
* this duration is "P1.23456S", then 1 is added to SECONDS,
- * 234 is added to MILLISECONDS, and the rest will be unused.
+ * 234 is added to MILLISECONDS, and the rest will be unused.
*
- *
+ *
*
* Note that because {@link Calendar#add(int, int)} is using
* int, {@link Duration} with values beyond the
@@ -1913,7 +1924,7 @@
* {@link XMLGregorianCalendar#add(Duration)} provides the same
* basic operation as this method while avoiding
* the overflow/underflow issues.
- *
+ *
* @param calendar
* A calendar object whose value will be modified.
* @throws NullPointerException
@@ -1934,23 +1945,23 @@
calendar.add(Calendar.MILLISECOND, millisec * signum);
}
}
-
+
/**
* Adds this duration to a {@link Date} object.
- *
+ *
*
* The given date is first converted into
* a {@link java.util.GregorianCalendar}, then the duration
* is added exactly like the {@link #addTo(Calendar)} method.
- *
+ *
*
* The updated time instant is then converted back into a
* {@link Date} object and used to update the given {@link Date} object.
- *
+ *
*
* This somewhat redundant computation is necessary to unambiguously
* determine the duration of months and years.
- *
+ *
* @param date
* A date object whose value will be modified.
* @throws NullPointerException
@@ -1962,19 +1973,29 @@
this.addTo(cal);
date.setTime(getCalendarTimeInMillis(cal));
}
-
+
/**
+ * Returns time value in milliseconds
+ * @param cal A calendar object
+ * @return time value
+ *
+ * Diff from Xerces; Use JDK 1.5 feature.
+ */
+ private static long getCalendarTimeInMillis(Calendar cal) {
+ return cal.getTimeInMillis();
+ }
+
+ /**
*
Stream Unique Identifier.
- *
- * TODO: Serialization should use the XML string representation as
- * the serialization format to ensure future compatibility.
+ *
+ * Serialization uses the lexical form returned by toString().
*/
private static final long serialVersionUID = 1L;
-
+
/**
* Writes {@link Duration} as a lexical representation
* for maximum future compatibility.
- *
+ *
* @return
* An object that encapsulates the string
* returned by this.toString()
.
@@ -1996,25 +2017,10 @@
}
private Object readResolve() throws ObjectStreamException {
- // try {
return new DurationImpl(lexical);
- // } catch( ParseException e ) {
- // throw new StreamCorruptedException("unable to parse "+lexical+" as duration");
- // }
}
private static final long serialVersionUID = 1L;
}
- /**
- * Calls the {@link Calendar#getTimeInMillis} method.
- * Prior to JDK1.4, this method was protected and therefore
- * cannot be invoked directly.
- *
- * In future, this should be replaced by
- * cal.getTimeInMillis()
- */
- private static long getCalendarTimeInMillis(Calendar cal) {
- return cal.getTime().getTime();
- }
}
--- old/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/datatype/XMLGregorianCalendarImpl.java Tue Feb 18 09:40:14 2014
+++ new/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/datatype/XMLGregorianCalendarImpl.java Tue Feb 18 09:40:14 2014
@@ -25,6 +25,8 @@
package com.sun.org.apache.xerces.internal.jaxp.datatype;
+import java.io.IOException;
+import java.io.ObjectInputStream;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
@@ -194,6 +196,17 @@
public class XMLGregorianCalendarImpl
extends XMLGregorianCalendar
implements Serializable, Cloneable {
+
+ /** Backup values **/
+ transient private BigInteger orig_eon;
+ transient private int orig_year = DatatypeConstants.FIELD_UNDEFINED;
+ transient private int orig_month = DatatypeConstants.FIELD_UNDEFINED;
+ transient private int orig_day = DatatypeConstants.FIELD_UNDEFINED;
+ transient private int orig_hour = DatatypeConstants.FIELD_UNDEFINED;
+ transient private int orig_minute = DatatypeConstants.FIELD_UNDEFINED;
+ transient private int orig_second = DatatypeConstants.FIELD_UNDEFINED;
+ transient private BigDecimal orig_fracSeconds;
+ transient private int orig_timezone = DatatypeConstants.FIELD_UNDEFINED;
/**
* Eon of this XMLGregorianCalendar
.
@@ -241,11 +254,16 @@
private BigDecimal fractionalSecond = null;
/**
- * Constant to represent a billion.
+ * BigInteger constant; representing a billion.
*/
- private static final BigInteger BILLION = new BigInteger("1000000000");
-
+ private static final BigInteger BILLION_B = new BigInteger("1000000000");
+
/**
+ * int constant; representing a billion.
+ */
+ private static final int BILLION_I = 1000000000;
+
+ /**
* Obtain a pure Gregorian Calendar by calling
* GregorianCalendar.setChange(PURE_GREGORIAN_CHANGE).
*/
@@ -441,9 +459,26 @@
//"\"" + lexicalRepresentation + "\" is not a valid representation of an XML Gregorian Calendar value."
);
}
+
+ save();
}
/**
+ * save original values
+ */
+ private void save() {
+ orig_eon = eon;
+ orig_year = year;
+ orig_month = month;
+ orig_day = day;
+ orig_hour = hour;
+ orig_minute = minute;
+ orig_second = second;
+ orig_fracSeconds = fractionalSecond;
+ orig_timezone = timezone;
+ }
+
+ /**
* Create an instance with all date/time datatype fields set to
* {@link DatatypeConstants#FIELD_UNDEFINED} or null respectively.
*/
@@ -479,14 +514,14 @@
BigDecimal fractionalSecond,
int timezone) {
- setYear(year);
+ setYear(year);
setMonth(month);
setDay(day);
setTime(hour, minute, second, fractionalSecond);
- setTimezone(timezone);
+ setTimezone(timezone);
- // check for validity
- if (!isValid()) {
+ // check for validity
+ if (!isValid()) {
throw new IllegalArgumentException(
DatatypeMessageFormatter.formatMessage(null,
@@ -519,8 +554,9 @@
);
*/
- }
-
+ }
+
+ save();
}
/**
@@ -547,17 +583,21 @@
int hour,
int minute,
int second,
- int millisecond,
+ int millisecond,
int timezone) {
- setYear(year);
+ setYear(year);
setMonth(month);
setDay(day);
setTime(hour, minute, second);
- setTimezone(timezone);
- setMillisecond(millisecond);
+ setTimezone(timezone);
+ BigDecimal realMilliseconds = null;
+ if (millisecond != DatatypeConstants.FIELD_UNDEFINED) {
+ realMilliseconds = BigDecimal.valueOf(millisecond, 3);
+ }
+ setFractionalSecond(realMilliseconds);
- if (!isValid()) {
+ if (!isValid()) {
throw new IllegalArgumentException(
DatatypeMessageFormatter.formatMessage(null,
@@ -580,7 +620,9 @@
);
*/
- }
+ }
+
+ save();
}
/**
@@ -661,6 +703,7 @@
// Calendar ZONE_OFFSET and DST_OFFSET fields are in milliseconds.
int offsetInMinutes = (cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET)) / (60 * 1000);
this.setTimezone(offsetInMinutes);
+ save();
}
// Factories
@@ -1164,7 +1207,7 @@
this.eon = null;
this.year = DatatypeConstants.FIELD_UNDEFINED;
} else {
- BigInteger temp = year.remainder(BILLION);
+ BigInteger temp = year.remainder(BILLION_B);
this.year = temp.intValue();
setEon(year.subtract(temp));
}
@@ -1187,12 +1230,13 @@
if (year == DatatypeConstants.FIELD_UNDEFINED) {
this.year = DatatypeConstants.FIELD_UNDEFINED;
this.eon = null;
- } else if (Math.abs(year) < BILLION.intValue()) {
+ }
+ else if (Math.abs(year) < BILLION_I) {
this.year = year;
this.eon = null;
} else {
BigInteger theYear = BigInteger.valueOf((long) year);
- BigInteger remainder = theYear.remainder(BILLION);
+ BigInteger remainder = theYear.remainder(BILLION_B);
this.year = remainder.intValue();
setEon(theYear.subtract(remainder));
}
@@ -1684,10 +1728,13 @@
* @return true
when compare(this,(XMLGregorianCalendar)obj) == EQUAL.
.
*/
public boolean equals(Object obj) {
-
+
if (obj == null || !(obj instanceof XMLGregorianCalendar)) {
return false;
}
+ if (obj == this) {
+ return true;
+ }
return compare((XMLGregorianCalendar) obj) == DatatypeConstants.EQUAL;
}
@@ -1945,56 +1992,41 @@
* @return true if data values are valid.
*/
public boolean isValid() {
- // since setters do not allow for invalid values,
+ // since setters do not allow for invalid values,
// (except for exceptional case of year field of zero),
// no need to check for anything except for constraints
- // between fields.
+ // between fields.
- //check if days in month is valid. Can be dependent on leap year.
- if (getMonth() == DatatypeConstants.FEBRUARY) {
- // years could not be set
- int maxDays = 29;
-
- if (eon == null) {
- if(year!=DatatypeConstants.FIELD_UNDEFINED)
- maxDays = maximumDayInMonthFor(year,getMonth());
- } else {
- BigInteger years = getEonAndYear();
- if (years != null) {
- maxDays = maximumDayInMonthFor(getEonAndYear(), DatatypeConstants.FEBRUARY);
+ // check if days in month is valid. Can be dependent on leap year.
+ if (month != DatatypeConstants.FIELD_UNDEFINED && day != DatatypeConstants.FIELD_UNDEFINED) {
+ if (year != DatatypeConstants.FIELD_UNDEFINED) {
+ if (eon == null) {
+ if (day > maximumDayInMonthFor(year, month)) {
+ return false;
+ }
}
+ else if (day > maximumDayInMonthFor(getEonAndYear(), month)) {
+ return false;
+ }
}
- if (getDay() > maxDays) {
+ // Use 2000 as a default since it's a leap year.
+ else if (day > maximumDayInMonthFor(2000, month)) {
return false;
}
}
// http://www.w3.org/2001/05/xmlschema-errata#e2-45
- if (getHour() == 24) {
- if(getMinute() != 0) {
- return false;
- } else if (getSecond() != 0) {
- return false;
- }
+ if (hour == 24 && (minute != 0 || second != 0 ||
+ (fractionalSecond != null && fractionalSecond.compareTo(DECIMAL_ZERO) != 0))) {
+ return false;
}
// XML Schema 1.0 specification defines year value of zero as
// invalid. Allow this class to set year field to zero
- // since XML Schema 1.0 errata states that lexical zero will
+ // since XML Schema 1.0 errata states that lexical zero will
// be allowed in next version and treated as 1 B.C.E.
- if (eon == null) {
- // optimize check.
- if (year == 0) {
- return false;
- }
- } else {
- BigInteger yearField = getEonAndYear();
- if (yearField != null) {
- int result = compareField(yearField, BigInteger.ZERO);
- if (result == DatatypeConstants.EQUAL) {
- return false;
- }
- }
+ if (eon == null && year == 0) {
+ return false;
}
return true;
}
@@ -2213,7 +2245,7 @@
int quotient;
if (endMonth < 0) {
endMonth = (13 - 1) + endMonth + 1;
- quotient = new BigDecimal(intTemp - 1).divide(new BigDecimal(TWELVE), BigDecimal.ROUND_UP).intValue();
+ quotient = BigDecimal.valueOf(intTemp - 1).divide(new BigDecimal(TWELVE), BigDecimal.ROUND_UP).intValue();
} else {
quotient = (intTemp - 1) / (13 - 1);
endMonth += 1;
@@ -2259,18 +2291,20 @@
private static final BigInteger SIXTY = BigInteger.valueOf(60);
private static final BigInteger TWENTY_FOUR = BigInteger.valueOf(24);
private static final BigInteger TWELVE = BigInteger.valueOf(12);
- private static final BigDecimal DECIMAL_ZERO = new BigDecimal("0");
- private static final BigDecimal DECIMAL_ONE = new BigDecimal("1");
- private static final BigDecimal DECIMAL_SIXTY = new BigDecimal("60");
+ private static final BigDecimal DECIMAL_ZERO = BigDecimal.valueOf(0);
+ private static final BigDecimal DECIMAL_ONE = BigDecimal.valueOf(1);
+ private static final BigDecimal DECIMAL_SIXTY = BigDecimal.valueOf(60);
- private static int daysInMonth[] = { 0, // XML Schema months start at 1.
- 31, 28, 31, 30, 31, 30,
- 31, 31, 30, 31, 30, 31};
+ private static class DaysInMonth {
+ private static final int [] table = { 0, // XML Schema months start at 1.
+ 31, 28, 31, 30, 31, 30,
+ 31, 31, 30, 31, 30, 31};
+ }
private static int maximumDayInMonthFor(BigInteger year, int month) {
if (month != DatatypeConstants.FEBRUARY) {
- return daysInMonth[month];
+ return DaysInMonth.table[month];
} else {
if (year.mod(FOUR_HUNDRED).equals(BigInteger.ZERO) ||
(!year.mod(HUNDRED).equals(BigInteger.ZERO) &&
@@ -2278,7 +2312,7 @@
// is a leap year.
return 29;
} else {
- return daysInMonth[month];
+ return DaysInMonth.table[month];
}
}
}
@@ -2285,7 +2319,7 @@
private static int maximumDayInMonthFor(int year, int month) {
if (month != DatatypeConstants.FEBRUARY) {
- return daysInMonth[month];
+ return DaysInMonth.table[month];
} else {
if (((year % 400) == 0) ||
(((year % 100) != 0) && ((year % 4) == 0))) {
@@ -2292,7 +2326,7 @@
// is a leap year.
return 29;
} else {
- return daysInMonth[DatatypeConstants.FEBRUARY];
+ return DaysInMonth.table[DatatypeConstants.FEBRUARY];
}
}
}
@@ -2404,10 +2438,16 @@
result.setGregorianChange(PURE_GREGORIAN_CHANGE);
// if year( and eon) are undefined, leave default Calendar values
- BigInteger year = getEonAndYear();
- if (year != null) {
- result.set(Calendar.ERA, year.signum() == -1 ? GregorianCalendar.BC : GregorianCalendar.AD);
- result.set(Calendar.YEAR, year.abs().intValue());
+ if (year != DatatypeConstants.FIELD_UNDEFINED) {
+ if (eon == null) {
+ result.set(Calendar.ERA, year < 0 ? GregorianCalendar.BC : GregorianCalendar.AD);
+ result.set(Calendar.YEAR, Math.abs(year));
+ }
+ else {
+ BigInteger eonAndYear = getEonAndYear();
+ result.set(Calendar.ERA, eonAndYear.signum() == -1 ? GregorianCalendar.BC : GregorianCalendar.AD);
+ result.set(Calendar.YEAR, eonAndYear.abs().intValue());
+ }
}
// only set month if it is set
@@ -2543,16 +2583,31 @@
result.setGregorianChange(PURE_GREGORIAN_CHANGE);
// if year( and eon) are undefined, leave default Calendar values
- BigInteger year = getEonAndYear();
- if (year != null) {
- result.set(Calendar.ERA, year.signum() == -1 ? GregorianCalendar.BC : GregorianCalendar.AD);
- result.set(Calendar.YEAR, year.abs().intValue());
+ if (year != DatatypeConstants.FIELD_UNDEFINED) {
+ if (eon == null) {
+ result.set(Calendar.ERA, year < 0 ? GregorianCalendar.BC : GregorianCalendar.AD);
+ result.set(Calendar.YEAR, Math.abs(year));
+ }
+ else {
+ final BigInteger eonAndYear = getEonAndYear();
+ result.set(Calendar.ERA, eonAndYear.signum() == -1 ? GregorianCalendar.BC : GregorianCalendar.AD);
+ result.set(Calendar.YEAR, eonAndYear.abs().intValue());
+ }
} else {
// use default if set
- BigInteger defaultYear = (defaults != null) ? defaults.getEonAndYear() : null;
- if (defaultYear != null) {
- result.set(Calendar.ERA, defaultYear.signum() == -1 ? GregorianCalendar.BC : GregorianCalendar.AD);
- result.set(Calendar.YEAR, defaultYear.abs().intValue());
+ if (defaults != null) {
+ final int defaultYear = defaults.getYear();
+ if (defaultYear != DatatypeConstants.FIELD_UNDEFINED) {
+ if (defaults.getEon() == null) {
+ result.set(Calendar.ERA, defaultYear < 0 ? GregorianCalendar.BC : GregorianCalendar.AD);
+ result.set(Calendar.YEAR, Math.abs(defaultYear));
+ }
+ else {
+ final BigInteger defaultEonAndYear = defaults.getEonAndYear();
+ result.set(Calendar.ERA, defaultEonAndYear.signum() == -1 ? GregorianCalendar.BC : GregorianCalendar.AD);
+ result.set(Calendar.YEAR, defaultEonAndYear.abs().intValue());
+ }
+ }
}
}
@@ -2562,7 +2617,7 @@
result.set(Calendar.MONTH, month - 1);
} else {
// use default if set
- int defaultMonth = (defaults != null) ? defaults.getMonth() : DatatypeConstants.FIELD_UNDEFINED;
+ final int defaultMonth = (defaults != null) ? defaults.getMonth() : DatatypeConstants.FIELD_UNDEFINED;
if (defaultMonth != DatatypeConstants.FIELD_UNDEFINED) {
// Calendar.MONTH is zero based while XMLGregorianCalendar month field is not.
result.set(Calendar.MONTH, defaultMonth - 1);
@@ -2574,7 +2629,7 @@
result.set(Calendar.DAY_OF_MONTH, day);
} else {
// use default if set
- int defaultDay = (defaults != null) ? defaults.getDay() : DatatypeConstants.FIELD_UNDEFINED;
+ final int defaultDay = (defaults != null) ? defaults.getDay() : DatatypeConstants.FIELD_UNDEFINED;
if (defaultDay != DatatypeConstants.FIELD_UNDEFINED) {
result.set(Calendar.DAY_OF_MONTH, defaultDay);
}
@@ -2596,7 +2651,7 @@
result.set(Calendar.MINUTE, minute);
} else {
// use default if set
- int defaultMinute = (defaults != null) ? defaults.getMinute() : DatatypeConstants.FIELD_UNDEFINED;
+ final int defaultMinute = (defaults != null) ? defaults.getMinute() : DatatypeConstants.FIELD_UNDEFINED;
if (defaultMinute != DatatypeConstants.FIELD_UNDEFINED) {
result.set(Calendar.MINUTE, defaultMinute);
}
@@ -2607,7 +2662,7 @@
result.set(Calendar.SECOND, second);
} else {
// use default if set
- int defaultSecond = (defaults != null) ? defaults.getSecond() : DatatypeConstants.FIELD_UNDEFINED;
+ final int defaultSecond = (defaults != null) ? defaults.getSecond() : DatatypeConstants.FIELD_UNDEFINED;
if (defaultSecond != DatatypeConstants.FIELD_UNDEFINED) {
result.set(Calendar.SECOND, defaultSecond);
}
@@ -2618,7 +2673,7 @@
result.set(Calendar.MILLISECOND, getMillisecond());
} else {
// use default if set
- BigDecimal defaultFractionalSecond = (defaults != null) ? defaults.getFractionalSecond() : null;
+ final BigDecimal defaultFractionalSecond = (defaults != null) ? defaults.getFractionalSecond() : null;
if (defaultFractionalSecond != null) {
result.set(Calendar.MILLISECOND, defaults.getMillisecond());
}
@@ -2671,6 +2726,9 @@
customTimezoneId.append(sign);
customTimezoneId.append(hour);
if (minutes != 0) {
+ if (minutes < 10) {
+ customTimezoneId.append('0');
+ }
customTimezoneId.append(minutes);
}
result = TimeZone.getTimeZone(customTimezoneId.toString());
@@ -2718,7 +2776,7 @@
if(millisecond<0 || 999
- * I wrote a custom format method for a particular format string to
- * see if it improves the performance, but it didn't. So this interpreting
- * approach isn't too bad.
- *
- *
* StringBuffer -> StringBuilder change had a very visible impact.
- * It almost cut the execution time to half, but unfortunately we can't use it
- * because we need to run on JDK 1.3
+ * It almost cut the execution time to half.
+ * Diff from Xerces:
+ * Xerces use StringBuffer due to the requirement to support
+ * JDKs older than JDK 1.5
*/
private String format( String format ) {
- char[] buf = new char[32];
- int bufPtr = 0;
-
+ StringBuilder buf = new StringBuilder();
int fidx=0,flen=format.length();
while(fidx= 0) {
- String zeros = frac.substring(pos+2);
- frac = frac.substring(0,pos);
- pos = frac.indexOf(".");
- if (pos >= 0) {
- frac = frac.substring(0,pos) + frac.substring(pos+1);
+ case 'Y':
+ if (eon == null) {
+ int absYear = year;
+ if (absYear < 0) {
+ buf.append('-');
+ absYear = -year;
}
- int count = Integer.parseInt(zeros);
- if (count < 40) {
- frac = "00000000000000000000000000000000000000000".substring(0,count-1) + frac;
- } else {
- // do it the hard way
- while (count > 1) {
- frac = "0" + frac;
- count--;
- }
- }
- frac = "0." + frac;
+ printNumber(buf, absYear, 4);
}
-
- // reallocate the buffer now so that it has enough space
- char[] n = new char[buf.length+frac.length()];
- System.arraycopy(buf,0,n,0,bufPtr);
- buf = n;
- //skip leading zero.
- frac.getChars(1, frac.length(), buf, bufPtr);
- bufPtr += frac.length()-1;
- }
- break;
- case 'z':
- int offset = getTimezone();
- if (offset == 0) {
- buf[bufPtr++] = 'Z';
- } else
- if (offset != DatatypeConstants.FIELD_UNDEFINED) {
- if (offset < 0) {
- buf[bufPtr++] = '-';
- offset *= -1;
- } else {
- buf[bufPtr++] = '+';
+ else {
+ printNumber(buf, getEonAndYear(), 4);
}
- bufPtr = print2Number(buf, bufPtr, offset / 60);
- buf[bufPtr++] = ':';
- bufPtr = print2Number(buf, bufPtr, offset % 60);
- }
- break;
- default:
- throw new InternalError(); // impossible
+ break;
+ case 'M':
+ printNumber(buf,getMonth(),2);
+ break;
+ case 'D':
+ printNumber(buf,getDay(),2);
+ break;
+ case 'h':
+ printNumber(buf,getHour(),2);
+ break;
+ case 'm':
+ printNumber(buf,getMinute(),2);
+ break;
+ case 's':
+ printNumber(buf,getSecond(),2);
+ if (getFractionalSecond() != null) {
+ //Xerces uses a custom method toString instead of
+ //toPlainString() since it needs to support JDKs older than 1.5
+ String frac = getFractionalSecond().toPlainString();
+ //skip leading zero.
+ buf.append(frac.substring(1, frac.length()));
+ }
+ break;
+ case 'z':
+ int offset = getTimezone();
+ if (offset == 0) {
+ buf.append('Z');
+ }
+ else if (offset != DatatypeConstants.FIELD_UNDEFINED) {
+ if (offset < 0) {
+ buf.append('-');
+ offset *= -1;
+ }
+ else {
+ buf.append('+');
+ }
+ printNumber(buf,offset/60,2);
+ buf.append(':');
+ printNumber(buf,offset%60,2);
+ }
+ break;
+ default:
+ throw new InternalError(); // impossible
}
}
- return new String(buf,0,bufPtr);
+ return buf.toString();
}
/**
- * Prints an int as two digits into the buffer.
- *
+ * Prints an integer as a String.
+ *
+ * @param out
+ * The formatted string will be appended into this buffer.
* @param number
- * Number to be printed. Must be positive.
+ * The integer to be printed.
+ * @param nDigits
+ * The field will be printed by using at least this
+ * number of digits. For example, 5 will be printed as "0005"
+ * if nDigits==4.
*/
- private int print2Number( char[] out, int bufptr, int number ) {
- out[bufptr++] = (char) ('0'+(number/10));
- out[bufptr++] = (char) ('0'+(number%10));
- return bufptr;
+ private void printNumber( StringBuilder out, int number, int nDigits ) {
+ String s = String.valueOf(number);
+ for (int i = s.length(); i < nDigits; i++) {
+ out.append('0');
+ }
+ out.append(s);
}
/**
- * Prints an int as four digits into the buffer.
- *
+ * Prints an BigInteger as a String.
+ *
+ * @param out
+ * The formatted string will be appended into this buffer.
* @param number
- * Number to be printed. Must be positive.
+ * The integer to be printed.
+ * @param nDigits
+ * The field will be printed by using at least this
+ * number of digits. For example, 5 will be printed as "0005"
+ * if nDigits==4.
*/
- private int print4Number( char[] out, int bufptr, int number ) {
- out[bufptr+3] = (char) ('0'+(number%10));
- number /= 10;
- out[bufptr+2] = (char) ('0'+(number%10));
- number /= 10;
- out[bufptr+1] = (char) ('0'+(number%10));
- number /= 10;
- out[bufptr ] = (char) ('0'+(number%10));
- return bufptr+4;
+ private void printNumber( StringBuilder out, BigInteger number, int nDigits) {
+ String s = number.toString();
+ for (int i=s.length(); i < nDigits; i++) {
+ out.append('0');
+ }
+ out.append(s);
}
/**
@@ -3085,6 +3108,26 @@
* with the creation of new XMLGregorianCalendar
s.
*/
public void reset() {
- //PENDING : Implementation of reset method
+ eon = orig_eon;
+ year = orig_year;
+ month = orig_month;
+ day = orig_day;
+ hour = orig_hour;
+ minute = orig_minute;
+ second = orig_second;
+ fractionalSecond = orig_fracSeconds;
+ timezone = orig_timezone;
}
+
+ /** Deserialize Calendar. */
+ private void readObject(ObjectInputStream ois)
+ throws ClassNotFoundException, IOException {
+
+ // perform default deseralization
+ ois.defaultReadObject();
+
+ // initialize orig_* fields
+ save();
+
+ } // readObject(ObjectInputStream)
}
--- /dev/null Tue Feb 18 09:40:17 2014
+++ new/jdk/test/javax/xml/jaxp/datatype/8033980/CalendarDuration1097Test.java Tue Feb 18 09:40:15 2014
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8033980
+ * @summary verify that offset in minutes in getTimeZone is converted correctly
+ * Note that JDK did not have this bug.
+ * @run main CalendarDuration1097Test
+ */
+
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.datatype.XMLGregorianCalendar;
+
+
+/**
+ *
+ * @author Joe Wang huizhe.wang@oracle.com
+ */
+public class CalendarDuration1097Test {
+
+ /**
+ * main method.
+ *
+ * @param args Standard args.
+ */
+ public static void main(String[] args) {
+ try {
+ String dateTimeString = "0001-01-01T00:00:00.0000000-05:00";
+ DatatypeFactory dtf = DatatypeFactory.newInstance();
+ XMLGregorianCalendar cal = dtf.newXMLGregorianCalendar( dateTimeString );
+ System.out.println( "Expected: 0001-01-01T00:00:00.0000000-05:00");
+ System.out.println( "Actual:" + cal.toString() );
+ System.out.println( "toXMLFormat:" + cal.toXMLFormat() );
+ String test = cal.toString();
+ if (test.indexOf("E-7") > -1) {
+ throw new RuntimeException("Expected: 0001-01-01T00:00:00.0000000-05:00");
+ }
+ } catch (DatatypeConfigurationException ex) {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+
+}
--- /dev/null Tue Feb 18 09:40:18 2014
+++ new/jdk/test/javax/xml/jaxp/datatype/8033980/CalendarDuration1243Test.java Tue Feb 18 09:40:17 2014
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8033980
+ * @summary verify that offset in minutes in getTimeZone is converted correctly
+ * @run main CalendarDuration1243Test
+ */
+
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.datatype.XMLGregorianCalendar;
+
+
+/**
+ *
+ * @author Joe Wang huizhe.wang@oracle.com
+ */
+public class CalendarDuration1243Test {
+
+ /**
+ * main method.
+ *
+ * @param args Standard args.
+ */
+ public static void main(String[] args) {
+ try {
+ String dateTimeString = "2006-11-22T00:00:00.0+01:02";
+ DatatypeFactory dtf = DatatypeFactory.newInstance();
+ XMLGregorianCalendar cal = dtf.newXMLGregorianCalendar( dateTimeString );
+ System.out.println( "XMLGregCal:" + cal.toString() );
+ System.out.println( "GregCal:" + cal.toGregorianCalendar() );
+ String toGCal = cal.toGregorianCalendar().toString();
+ if (toGCal.indexOf("GMT+12:00") > -1) {
+ throw new RuntimeException("Expected GMT+01:02");
+ }
+ } catch (DatatypeConfigurationException ex) {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+
+}
--- /dev/null Tue Feb 18 09:40:19 2014
+++ new/jdk/test/javax/xml/jaxp/datatype/8033980/CalendarDuration1416Test.java Tue Feb 18 09:40:18 2014
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8033980
+ * @summary test that invalid durations are caught
+ * @run main CalendarDuration1416Test
+ */
+
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.datatype.DatatypeFactory;
+
+
+/**
+ *
+ * @author Joe Wang huizhe.wang@oracle.com
+ */
+public class CalendarDuration1416Test {
+
+ /**
+ * main method.
+ *
+ * @param args Standard args.
+ */
+ public static void main(String[] args) {
+ test1416("PT1D1H");
+ test1416("PT1D1H30M");
+ test1416("PT1D1H30S");
+ }
+
+ static void test1416(String d) {
+ try
+ {
+ DatatypeFactory dtf = DatatypeFactory.newInstance();
+ dtf.newDuration(d);
+ throw new Error("no bug for " + d);
+ } catch (DatatypeConfigurationException ex) {
+ fail(ex.getMessage());
+ }
+ catch (NullPointerException e) {
+ fail("NPE bug ! " + d);
+
+ }
+ catch(IllegalArgumentException e)
+ {
+ System.out.println("OK, BUG FIXED for " + d);
+ }
+
+ }
+
+ static void fail(String errMessage) {
+ throw new RuntimeException(errMessage);
+ }
+}
Binary files /tmp/dYIaWQP and new/jdk/test/javax/xml/jaxp/datatype/8033980/JDK6_Duration.ser differ
Binary files /tmp/d5YaGVP and new/jdk/test/javax/xml/jaxp/datatype/8033980/JDK6_XMLGregorianCalendar.ser differ
Binary files /tmp/dlfaq0P and new/jdk/test/javax/xml/jaxp/datatype/8033980/JDK7_Duration.ser differ
Binary files /tmp/dNzaa5P and new/jdk/test/javax/xml/jaxp/datatype/8033980/JDK7_XMLGregorianCalendar.ser differ
Binary files /tmp/dXZaW9P and new/jdk/test/javax/xml/jaxp/datatype/8033980/JDK8_Duration.ser differ
Binary files /tmp/dtzaGcQ and new/jdk/test/javax/xml/jaxp/datatype/8033980/JDK8_XMLGregorianCalendar.ser differ
Binary files /tmp/d_UaqhQ and new/jdk/test/javax/xml/jaxp/datatype/8033980/JDK9_Duration.ser differ
Binary files /tmp/dj_aGmQ and new/jdk/test/javax/xml/jaxp/datatype/8033980/JDK9_XMLGregorianCalendar.ser differ
--- /dev/null Tue Feb 18 09:40:31 2014
+++ new/jdk/test/javax/xml/jaxp/datatype/8033980/SerializationTest.java Tue Feb 18 09:40:30 2014
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8033980
+ * @summary verify serialization compatibility for XMLGregorianCalendar and Duration
+ * @run main SerializationTest read
+ */
+
+import java.io.*;
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.datatype.Duration;
+import javax.xml.datatype.XMLGregorianCalendar;
+
+/**
+ * use "read" to test compatibility
+ * SerializationTest read
+ *
+ * use "write" to create test files
+ * SerializationTest write javaVersion
+ * where javaVersion is 6, 7, 8, or 9
+ *
+ * @author huizhe.wang@oracle.com
+ */
+public class SerializationTest {
+
+ final String FILENAME_CAL = "_XMLGregorianCalendar.ser";
+ final String FILENAME_DURATION = "_Duration.ser";
+ String filePath;
+
+ {
+ filePath = System.getProperty("test.src");
+ if (filePath == null) {
+ //current directory
+ filePath = System.getProperty("user.dir");
+ }
+ filePath += File.separator;
+ }
+ final String EXPECTED_CAL = "0001-01-01T00:00:00.0000000-05:00";
+ final String EXPECTED_DURATION = "P1Y1M1DT1H1M1S";
+ static String[] JDK = {"JDK6", "JDK7", "JDK8", "JDK9"};
+
+ public static void main(String[] args) {
+ SerializationTest test = new SerializationTest();
+
+ if (args[0].equalsIgnoreCase("read")) {
+ test.testReadCal();
+ test.testReadDuration();
+ test.report();
+ } else {
+ int ver = Integer.valueOf(args[1]).intValue();
+ test.createTestFile(JDK[ver - 6]);
+ }
+
+ }
+
+ public void testReadCal() {
+ try {
+ for (String javaVersion : JDK) {
+ XMLGregorianCalendar d1 = (XMLGregorianCalendar) fromFile(
+ javaVersion + FILENAME_CAL);
+ if (!d1.toString().equalsIgnoreCase(EXPECTED_CAL)) {
+ fail("Java version: " + javaVersion
+ + "\nExpected: " + EXPECTED_CAL
+ + "\nActual: " + d1.toString());
+ } else {
+ success("testReadCal: read " + javaVersion + " serialized file, passed.");
+ }
+ }
+ } catch (ClassNotFoundException ex) {
+ fail("testReadCal: " + ex.getMessage());
+ } catch (IOException ex) {
+ fail("testReadCal: " + ex.getMessage());
+ }
+ }
+
+ public void testReadDuration() {
+ try {
+ for (String javaVersion : JDK) {
+ Duration d1 = (Duration) fromFile(
+ javaVersion + FILENAME_DURATION);
+ if (!d1.toString().equalsIgnoreCase(EXPECTED_DURATION)) {
+ fail("Java version: " + javaVersion
+ + "\nExpected: " + EXPECTED_DURATION
+ + "\nActual: " + d1.toString());
+ } else {
+ success("testReadDuration: read " + javaVersion + " serialized file, passed.");
+ }
+ }
+ } catch (ClassNotFoundException ex) {
+ fail("testReadDuration: " + ex.getMessage());
+ } catch (IOException ex) {
+ fail("testReadDuration: " + ex.getMessage());
+ }
+ }
+
+ /**
+ * Create test files
+ *
+ * @param javaVersion JDK version
+ */
+ public void createTestFile(String javaVersion) {
+ try {
+ DatatypeFactory dtf = DatatypeFactory.newInstance();
+ XMLGregorianCalendar c = dtf.newXMLGregorianCalendar(EXPECTED_CAL);
+ Duration d = dtf.newDuration(EXPECTED_DURATION);
+ toFile((Serializable) c, filePath + javaVersion + FILENAME_CAL);
+ toFile((Serializable) d, filePath + javaVersion + FILENAME_DURATION);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+ }
+
+ /**
+ * Read the object from a file.
+ */
+ private static Object fromFile(String filePath) throws IOException,
+ ClassNotFoundException {
+ InputStream streamIn = SerializationTest.class.getResourceAsStream(
+ filePath);
+ ObjectInputStream objectinputstream = new ObjectInputStream(streamIn);
+ Object o = objectinputstream.readObject();
+ return o;
+ }
+
+ /**
+ * Write the object to a file.
+ */
+ private static void toFile(Serializable o, String filePath) throws IOException {
+System.out.println("filePath=" + filePath);
+ FileOutputStream fout = new FileOutputStream(filePath, true);
+ ObjectOutputStream oos = new ObjectOutputStream(fout);
+ oos.writeObject(o);
+ oos.close();
+ }
+
+ static String errMessage;
+ int passed = 0, failed = 0;
+
+ void fail(String errMsg) {
+ if (errMessage == null) {
+ errMessage = errMsg;
+ } else {
+ errMessage = errMessage + "\n" + errMsg;
+ }
+ failed++;
+ }
+
+ void success(String msg) {
+ passed++;
+ System.out.println(msg);
+ }
+
+ public void report() {
+
+ System.out.println("\nNumber of tests passed: " + passed);
+ System.out.println("Number of tests failed: " + failed + "\n");
+
+ if (errMessage != null) {
+ throw new RuntimeException(errMessage);
+ }
+ }
+}