--- a/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/datatype/DurationImpl.java Tue Jan 28 11:22:03 2014 -0800
+++ b/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/datatype/DurationImpl.java Tue Feb 18 10:51:16 2014 -0800
@@ -3,11 +3,12 @@
* 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
*
@@ -106,24 +107,20 @@
extends Duration
implements Serializable {
- /**
- * <p>Number of Fields.</p>
- */
- private static final int FIELD_NUM = 6;
/**
* <p>Internal array of value Fields.</p>
*/
- 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
+ };
- /**
+ /**
* <p>Internal array of value Field ids.</p>
*/
private static final int[] FIELD_IDS = {
@@ -141,9 +138,9 @@
private static final TimeZone GMT = TimeZone.getTimeZone("GMT");
/**
- * <p>BigDecimal value of 0.</p>
- */
- private static final BigDecimal ZERO = BigDecimal.valueOf((long) 0);
+ * <p>BigDecimal value of 0.</p>
+ */
+ private static final BigDecimal ZERO = BigDecimal.valueOf(0);
/**
* <p>Indicates the sign. -1, 0 or 1 if the duration is negative,
@@ -186,17 +183,17 @@
*/
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
@@ -206,20 +203,20 @@
*/
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;
+ }
}
/**
@@ -357,7 +354,7 @@
}
// int -> BigInteger
- return new BigInteger(String.valueOf(i));
+ return BigInteger.valueOf(i);
}
/**
@@ -373,14 +370,16 @@
if (l > 0) {
signum = 1;
- } else if (l < 0) {
+ }
+ else if (l < 0) {
signum = -1;
if (l == 0x8000000000000000L) {
// negating 0x8000000000000000L causes an overflow
l++;
}
l *= -1;
- } else {
+ }
+ else {
signum = 0;
}
@@ -454,21 +453,22 @@
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];
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);
}
@@ -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),
@@ -722,8 +726,7 @@
*/
public int compare(Duration rhs) {
- BigInteger maxintAsBigInteger = BigInteger.valueOf((long) Integer.MAX_VALUE);
- BigInteger minintAsBigInteger = BigInteger.valueOf((long) Integer.MIN_VALUE);
+ BigInteger maxintAsBigInteger = BigInteger.valueOf(Integer.MAX_VALUE);
// check for fields that are too large in this Duration
if (years != null && years.compareTo(maxintAsBigInteger) == 1) {
@@ -778,7 +781,7 @@
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()})
+ 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 "
@@ -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) {
@@ -1007,25 +1010,25 @@
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');
}
}
@@ -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++) {
@@ -1302,7 +1307,8 @@
Number n = getField(field);
if (n == null) {
return 0;
- } else {
+ }
+ else {
return n.intValue();
}
}
@@ -1340,8 +1346,7 @@
public long getTimeInMillis(final Calendar startInstant) {
Calendar cal = (Calendar) startInstant.clone();
addTo(cal);
- return getCalendarTimeInMillis(cal)
- - getCalendarTimeInMillis(startInstant);
+ return getCalendarTimeInMillis(cal) - getCalendarTimeInMillis(startInstant);
}
/**
@@ -1451,13 +1456,13 @@
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));
}
/**
@@ -1547,14 +1552,16 @@
} 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;
}
@@ -1581,14 +1588,17 @@
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);
}
}
@@ -1607,7 +1617,8 @@
boolean canBeNull) {
if (canBeNull && value.signum() == 0) {
return null;
- } else {
+ }
+ else {
return value.unscaledValue();
}
}
@@ -1616,7 +1627,7 @@
* 1 unit of FIELDS[i] is equivalent to <code>FACTORS[i]</code> 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),
@@ -1964,10 +1975,20 @@
}
/**
+ * 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();
+ }
+
+ /**
* <p>Stream Unique Identifier.</p>
*
- * <p>TODO: Serialization should use the XML string representation as
- * the serialization format to ensure future compatibility.</p>
+ * <p>Serialization uses the lexical form returned by toString().</p>
*/
private static final long serialVersionUID = 1L;
@@ -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
- * <code>cal.getTimeInMillis()</code>
- */
- private static long getCalendarTimeInMillis(Calendar cal) {
- return cal.getTime().getTime();
- }
}
--- a/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/datatype/XMLGregorianCalendarImpl.java Tue Jan 28 11:22:03 2014 -0800
+++ b/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/datatype/XMLGregorianCalendarImpl.java Tue Feb 18 10:51:16 2014 -0800
@@ -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;
@@ -195,6 +197,17 @@
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;
+
/**
* <p>Eon of this <code>XMLGregorianCalendar</code>.</p>
*/
@@ -241,9 +254,14 @@
private BigDecimal fractionalSecond = null;
/**
- * <p>Constant to represent a billion.</p>
+ * <p>BigInteger constant; representing a billion.</p>
*/
- private static final BigInteger BILLION = new BigInteger("1000000000");
+ private static final BigInteger BILLION_B = new BigInteger("1000000000");
+
+ /**
+ * <p>int constant; representing a billion.</p>
+ */
+ private static final int BILLION_I = 1000000000;
/**
* <p>Obtain a pure Gregorian Calendar by calling
@@ -441,6 +459,23 @@
//"\"" + 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;
}
/**
@@ -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));
}
@@ -1688,6 +1732,9 @@
if (obj == null || !(obj instanceof XMLGregorianCalendar)) {
return false;
}
+ if (obj == this) {
+ return true;
+ }
return compare((XMLGregorianCalendar) obj) == DatatypeConstants.EQUAL;
}
@@ -1950,51 +1997,36 @@
// no need to check for anything except for constraints
// 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
// 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,21 +2312,21 @@
// is a leap year.
return 29;
} else {
- return daysInMonth[month];
+ return DaysInMonth.table[month];
}
}
}
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))) {
// 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<millisecond)
if(millisecond!=DatatypeConstants.FIELD_UNDEFINED)
invalidFieldValue(MILLISECOND, millisecond);
- fractionalSecond = new BigDecimal((long) millisecond).movePointLeft(3);
+ fractionalSecond = BigDecimal.valueOf(millisecond, 3);
}
}
@@ -2770,7 +2828,7 @@
// seen meta character. we don't do error check against the format
switch (format.charAt(fidx++)) {
case 'Y' : // year
- parseAndSetYear(4);
+ parseYear();
break;
case 'M' : // month
@@ -2851,7 +2909,7 @@
int n = 0;
char ch;
int vstart = vidx;
- while (isDigit(ch=peek()) && (vidx - vstart) <= maxDigits) {
+ while (isDigit(ch=peek()) && (vidx - vstart) < maxDigits) {
vidx++;
n = n*10 + ch-'0';
}
@@ -2863,38 +2921,30 @@
return n;
}
- private void parseAndSetYear(int minDigits)
- throws IllegalArgumentException {
+ private void parseYear()
+ throws IllegalArgumentException {
int vstart = vidx;
- int n = 0;
- boolean neg = false;
+ int sign = 0;
// skip leading negative, if it exists
if (peek() == '-') {
vidx++;
- neg = true;
+ sign = 1;
}
- while(true) {
- char ch = peek();
- if(!isDigit(ch))
- break;
+ while (isDigit(peek())) {
vidx++;
- n = n*10 + ch-'0';
}
-
- if ((vidx - vstart) < minDigits) {
+ final int digits = vidx - vstart - sign;
+ if (digits < 4) {
// we are expecting more digits
throw new IllegalArgumentException(value); //,vidx);
}
-
- if(vidx-vstart<7) {
- // definitely int only. I don't know the exact # of digits that can be in int,
- // but as long as we can catch (0-9999) range, that should be enough.
- if(neg) n = -n;
- year = n;
- eon = null;
- } else {
- setYear(new BigInteger(value.substring(vstart, vidx)));
+ final String yearString = value.substring(vstart, vidx);
+ if (digits < 10) {
+ setYear(Integer.parseInt(yearString));
+ }
+ else {
+ setYear(new BigInteger(yearString));
}
}
@@ -2922,150 +2972,123 @@
* Prints this object according to the format specification.
*
* <p>
- * 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.
- *
- * <p>
* 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<flen) {
char fch = format.charAt(fidx++);
if(fch!='%') {// not a meta char
- buf[bufPtr++] = fch;
+ buf.append(fch);
continue;
}
switch(format.charAt(fidx++)) {
- case 'Y':
- if(eon==null) {
- // optimized path
- int y = getYear();
- if(y<0) {
- buf[bufPtr++] = '-';
- y = -y;
+ case 'Y':
+ if (eon == null) {
+ int absYear = year;
+ if (absYear < 0) {
+ buf.append('-');
+ absYear = -year;
+ }
+ printNumber(buf, absYear, 4);
+ }
+ else {
+ printNumber(buf, getEonAndYear(), 4);
}
- bufPtr = print4Number(buf,bufPtr,y);
- } else {
- String s = getEonAndYear().toString();
- // reallocate the buffer now so that it has enough space
- char[] n = new char[buf.length+s.length()];
- System.arraycopy(buf,0,n,0,bufPtr);
- buf = n;
- for(int i=s.length();i<4;i++)
- buf[bufPtr++] = '0';
- s.getChars(0,s.length(),buf,bufPtr);
- bufPtr += s.length();
- }
- break;
- case 'M':
- bufPtr = print2Number(buf,bufPtr,getMonth());
- break;
- case 'D':
- bufPtr = print2Number(buf,bufPtr,getDay());
- break;
- case 'h':
- bufPtr = print2Number(buf,bufPtr,getHour());
- break;
- case 'm':
- bufPtr = print2Number(buf,bufPtr,getMinute());
- break;
- case 's':
- bufPtr = print2Number(buf,bufPtr,getSecond());
- if (getFractionalSecond() != null) {
- // Note: toPlainString() isn't available before Java 1.5
- String frac = getFractionalSecond().toString();
-
- int pos = frac.indexOf("E-");
- if (pos >= 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);
+ 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;
}
- 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--;
- }
+ else {
+ buf.append('+');
}
- frac = "0." + frac;
+ printNumber(buf,offset/60,2);
+ buf.append(':');
+ printNumber(buf,offset%60,2);
}
-
- // 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++] = '+';
- }
- bufPtr = print2Number(buf, bufPtr, offset / 60);
- buf[bufPtr++] = ':';
- bufPtr = print2Number(buf, bufPtr, offset % 60);
- }
- break;
- default:
- throw new InternalError(); // impossible
+ 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 <code>XMLGregorianCalendar</code>s.</p>
*/
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)
}