jaxp/src/com/sun/org/apache/xerces/internal/jaxp/datatype/XMLGregorianCalendarImpl.java
Print this page
*** 23,32 ****
--- 23,34 ----
* questions.
*/
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;
import java.util.TimeZone;
import java.util.Calendar;
*** 193,202 ****
--- 195,215 ----
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;
+
/**
* <p>Eon of this <code>XMLGregorianCalendar</code>.</p>
*/
private BigInteger eon = null;
*** 239,253 ****
* <p>Fractional second of this <code>XMLGregorianCalendar</code>.</p>
*/
private BigDecimal fractionalSecond = null;
/**
! * <p>Constant to represent a billion.</p>
*/
! private static final BigInteger BILLION = new BigInteger("1000000000");
/**
* <p>Obtain a pure Gregorian Calendar by calling
* GregorianCalendar.setChange(PURE_GREGORIAN_CHANGE). </p>
*/
private static final Date PURE_GREGORIAN_CHANGE =
new Date(Long.MIN_VALUE);
--- 252,271 ----
* <p>Fractional second of this <code>XMLGregorianCalendar</code>.</p>
*/
private BigDecimal fractionalSecond = null;
/**
! * <p>BigInteger constant; representing a billion.</p>
*/
! 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
* GregorianCalendar.setChange(PURE_GREGORIAN_CHANGE). </p>
*/
private static final Date PURE_GREGORIAN_CHANGE =
new Date(Long.MIN_VALUE);
*** 439,451 ****
--- 457,486 ----
throw new IllegalArgumentException(
DatatypeMessageFormatter.formatMessage(null, "InvalidXGCRepresentation", new Object[]{lexicalRepresentation})
//"\"" + 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;
+ }
+
+ /**
* <p>Create an instance with all date/time datatype fields set to
* {@link DatatypeConstants#FIELD_UNDEFINED} or null respectively.</p>
*/
public XMLGregorianCalendarImpl() {
*** 519,528 ****
--- 554,564 ----
);
*/
}
+ save();
}
/**
* <p>Private constructor of value spaces that a
* <code>java.util.GregorianCalendar</code> instance would need to convert to an
*** 553,563 ****
setYear(year);
setMonth(month);
setDay(day);
setTime(hour, minute, second);
setTimezone(timezone);
! setMillisecond(millisecond);
if (!isValid()) {
throw new IllegalArgumentException(
DatatypeMessageFormatter.formatMessage(null,
--- 589,603 ----
setYear(year);
setMonth(month);
setDay(day);
setTime(hour, minute, second);
setTimezone(timezone);
! BigDecimal realMilliseconds = null;
! if (millisecond != DatatypeConstants.FIELD_UNDEFINED) {
! realMilliseconds = BigDecimal.valueOf(millisecond, 3);
! }
! setFractionalSecond(realMilliseconds);
if (!isValid()) {
throw new IllegalArgumentException(
DatatypeMessageFormatter.formatMessage(null,
*** 579,588 ****
--- 619,630 ----
+ ", is not a valid representation of an XML Gregorian Calendar value."
);
*/
}
+
+ save();
}
/**
* <p>Convert a <code>java.util.GregorianCalendar</code> to XML Schema 1.0
* representation.</p>
*** 659,668 ****
--- 701,711 ----
cal.get(Calendar.MILLISECOND));
// 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
/**
*** 1162,1172 ****
public void setYear(BigInteger year) {
if (year == null) {
this.eon = null;
this.year = DatatypeConstants.FIELD_UNDEFINED;
} else {
! BigInteger temp = year.remainder(BILLION);
this.year = temp.intValue();
setEon(year.subtract(temp));
}
}
--- 1205,1215 ----
public void setYear(BigInteger year) {
if (year == null) {
this.eon = null;
this.year = DatatypeConstants.FIELD_UNDEFINED;
} else {
! BigInteger temp = year.remainder(BILLION_B);
this.year = temp.intValue();
setEon(year.subtract(temp));
}
}
*** 1185,1200 ****
*/
public void setYear(int year) {
if (year == DatatypeConstants.FIELD_UNDEFINED) {
this.year = DatatypeConstants.FIELD_UNDEFINED;
this.eon = null;
! } else if (Math.abs(year) < BILLION.intValue()) {
this.year = year;
this.eon = null;
} else {
BigInteger theYear = BigInteger.valueOf((long) year);
! BigInteger remainder = theYear.remainder(BILLION);
this.year = remainder.intValue();
setEon(theYear.subtract(remainder));
}
}
--- 1228,1244 ----
*/
public void setYear(int year) {
if (year == DatatypeConstants.FIELD_UNDEFINED) {
this.year = DatatypeConstants.FIELD_UNDEFINED;
this.eon = null;
! }
! 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_B);
this.year = remainder.intValue();
setEon(theYear.subtract(remainder));
}
}
*** 1686,1695 ****
--- 1730,1742 ----
public boolean equals(Object obj) {
if (obj == null || !(obj instanceof XMLGregorianCalendar)) {
return false;
}
+ if (obj == this) {
+ return true;
+ }
return compare((XMLGregorianCalendar) obj) == DatatypeConstants.EQUAL;
}
/**
* <p>Returns a hash code consistent with the definition of the equals method.</p>
*** 1948,2003 ****
// 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.
! //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);
}
}
! if (getDay() > maxDays) {
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;
}
- }
// 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;
- }
- }
- }
return true;
}
/**
* <p>Add <code>duration</code> to this instance.<\p>
--- 1995,2035 ----
// 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.
! // 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;
}
}
+ // 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 (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 && year == 0) {
return false;
}
return true;
}
/**
* <p>Add <code>duration</code> to this instance.<\p>
*** 2211,2221 ****
intTemp = getMonth() + monthCarry;
int endMonth = (intTemp - 1) % (13 - 1);
int quotient;
if (endMonth < 0) {
endMonth = (13 - 1) + endMonth + 1;
! quotient = new BigDecimal(intTemp - 1).divide(new BigDecimal(TWELVE), BigDecimal.ROUND_UP).intValue();
} else {
quotient = (intTemp - 1) / (13 - 1);
endMonth += 1;
}
setMonth(endMonth);
--- 2243,2253 ----
intTemp = getMonth() + monthCarry;
int endMonth = (intTemp - 1) % (13 - 1);
int quotient;
if (endMonth < 0) {
endMonth = (13 - 1) + endMonth + 1;
! quotient = BigDecimal.valueOf(intTemp - 1).divide(new BigDecimal(TWELVE), BigDecimal.ROUND_UP).intValue();
} else {
quotient = (intTemp - 1) / (13 - 1);
endMonth += 1;
}
setMonth(endMonth);
*** 2257,2300 ****
private static final BigInteger HUNDRED = BigInteger.valueOf(100);
private static final BigInteger FOUR_HUNDRED = BigInteger.valueOf(400);
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 int daysInMonth[] = { 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];
} else {
if (year.mod(FOUR_HUNDRED).equals(BigInteger.ZERO) ||
(!year.mod(HUNDRED).equals(BigInteger.ZERO) &&
year.mod(FOUR).equals(BigInteger.ZERO))) {
// is a leap year.
return 29;
} else {
! return daysInMonth[month];
}
}
}
private static int maximumDayInMonthFor(int year, int month) {
if (month != DatatypeConstants.FEBRUARY) {
! return daysInMonth[month];
} else {
if (((year % 400) == 0) ||
(((year % 100) != 0) && ((year % 4) == 0))) {
// is a leap year.
return 29;
} else {
! return daysInMonth[DatatypeConstants.FEBRUARY];
}
}
}
/**
--- 2289,2334 ----
private static final BigInteger HUNDRED = BigInteger.valueOf(100);
private static final BigInteger FOUR_HUNDRED = BigInteger.valueOf(400);
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 = BigDecimal.valueOf(0);
! private static final BigDecimal DECIMAL_ONE = BigDecimal.valueOf(1);
! private static final BigDecimal DECIMAL_SIXTY = BigDecimal.valueOf(60);
! 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.table[month];
} else {
if (year.mod(FOUR_HUNDRED).equals(BigInteger.ZERO) ||
(!year.mod(HUNDRED).equals(BigInteger.ZERO) &&
year.mod(FOUR).equals(BigInteger.ZERO))) {
// is a leap year.
return 29;
} else {
! return DaysInMonth.table[month];
}
}
}
private static int maximumDayInMonthFor(int year, int month) {
if (month != DatatypeConstants.FEBRUARY) {
! return DaysInMonth.table[month];
} else {
if (((year % 400) == 0) ||
(((year % 100) != 0) && ((year % 4) == 0))) {
// is a leap year.
return 29;
} else {
! return DaysInMonth.table[DatatypeConstants.FEBRUARY];
}
}
}
/**
*** 2402,2416 ****
result = new GregorianCalendar(tz, locale);
result.clear();
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());
}
// only set month if it is set
if (month != DatatypeConstants.FIELD_UNDEFINED) {
// Calendar.MONTH is zero based while XMLGregorianCalendar month field is not.
result.set(Calendar.MONTH, month - 1);
--- 2436,2456 ----
result = new GregorianCalendar(tz, locale);
result.clear();
result.setGregorianChange(PURE_GREGORIAN_CHANGE);
// if year( and eon) are undefined, leave default Calendar values
! 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
if (month != DatatypeConstants.FIELD_UNDEFINED) {
// Calendar.MONTH is zero based while XMLGregorianCalendar month field is not.
result.set(Calendar.MONTH, month - 1);
*** 2541,2570 ****
result = new GregorianCalendar(tz, aLocale);
result.clear();
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());
} 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());
}
}
// only set month if it is set
if (month != DatatypeConstants.FIELD_UNDEFINED) {
// Calendar.MONTH is zero based while XMLGregorianCalendar month field is not.
result.set(Calendar.MONTH, month - 1);
} else {
// use default if set
! 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);
}
}
--- 2581,2625 ----
result = new GregorianCalendar(tz, aLocale);
result.clear();
result.setGregorianChange(PURE_GREGORIAN_CHANGE);
// if year( and eon) are undefined, leave default Calendar values
! 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
! 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());
}
+ }
+ }
+ }
// only set month if it is set
if (month != DatatypeConstants.FIELD_UNDEFINED) {
// Calendar.MONTH is zero based while XMLGregorianCalendar month field is not.
result.set(Calendar.MONTH, month - 1);
} else {
// use default if set
! 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);
}
}
*** 2572,2582 ****
// only set day if it is set
if (day != DatatypeConstants.FIELD_UNDEFINED) {
result.set(Calendar.DAY_OF_MONTH, day);
} else {
// use default if set
! int defaultDay = (defaults != null) ? defaults.getDay() : DatatypeConstants.FIELD_UNDEFINED;
if (defaultDay != DatatypeConstants.FIELD_UNDEFINED) {
result.set(Calendar.DAY_OF_MONTH, defaultDay);
}
}
--- 2627,2637 ----
// only set day if it is set
if (day != DatatypeConstants.FIELD_UNDEFINED) {
result.set(Calendar.DAY_OF_MONTH, day);
} else {
// use default if set
! final int defaultDay = (defaults != null) ? defaults.getDay() : DatatypeConstants.FIELD_UNDEFINED;
if (defaultDay != DatatypeConstants.FIELD_UNDEFINED) {
result.set(Calendar.DAY_OF_MONTH, defaultDay);
}
}
*** 2594,2604 ****
// only set minute if it is set
if (minute != DatatypeConstants.FIELD_UNDEFINED) {
result.set(Calendar.MINUTE, minute);
} else {
// use default if set
! int defaultMinute = (defaults != null) ? defaults.getMinute() : DatatypeConstants.FIELD_UNDEFINED;
if (defaultMinute != DatatypeConstants.FIELD_UNDEFINED) {
result.set(Calendar.MINUTE, defaultMinute);
}
}
--- 2649,2659 ----
// only set minute if it is set
if (minute != DatatypeConstants.FIELD_UNDEFINED) {
result.set(Calendar.MINUTE, minute);
} else {
// use default if set
! final int defaultMinute = (defaults != null) ? defaults.getMinute() : DatatypeConstants.FIELD_UNDEFINED;
if (defaultMinute != DatatypeConstants.FIELD_UNDEFINED) {
result.set(Calendar.MINUTE, defaultMinute);
}
}
*** 2605,2615 ****
// only set second if it is set
if (second != DatatypeConstants.FIELD_UNDEFINED) {
result.set(Calendar.SECOND, second);
} else {
// use default if set
! int defaultSecond = (defaults != null) ? defaults.getSecond() : DatatypeConstants.FIELD_UNDEFINED;
if (defaultSecond != DatatypeConstants.FIELD_UNDEFINED) {
result.set(Calendar.SECOND, defaultSecond);
}
}
--- 2660,2670 ----
// only set second if it is set
if (second != DatatypeConstants.FIELD_UNDEFINED) {
result.set(Calendar.SECOND, second);
} else {
// use default if set
! final int defaultSecond = (defaults != null) ? defaults.getSecond() : DatatypeConstants.FIELD_UNDEFINED;
if (defaultSecond != DatatypeConstants.FIELD_UNDEFINED) {
result.set(Calendar.SECOND, defaultSecond);
}
}
*** 2616,2626 ****
// only set millisend if it is set
if (fractionalSecond != null) {
result.set(Calendar.MILLISECOND, getMillisecond());
} else {
// use default if set
! BigDecimal defaultFractionalSecond = (defaults != null) ? defaults.getFractionalSecond() : null;
if (defaultFractionalSecond != null) {
result.set(Calendar.MILLISECOND, defaults.getMillisecond());
}
}
--- 2671,2681 ----
// only set millisend if it is set
if (fractionalSecond != null) {
result.set(Calendar.MILLISECOND, getMillisecond());
} else {
// use default if set
! final BigDecimal defaultFractionalSecond = (defaults != null) ? defaults.getFractionalSecond() : null;
if (defaultFractionalSecond != null) {
result.set(Calendar.MILLISECOND, defaults.getMillisecond());
}
}
*** 2669,2678 ****
--- 2724,2736 ----
StringBuffer customTimezoneId = new StringBuffer(8);
customTimezoneId.append("GMT");
customTimezoneId.append(sign);
customTimezoneId.append(hour);
if (minutes != 0) {
+ if (minutes < 10) {
+ customTimezoneId.append('0');
+ }
customTimezoneId.append(minutes);
}
result = TimeZone.getTimeZone(customTimezoneId.toString());
}
return result;
*** 2716,2726 ****
fractionalSecond = null;
} else {
if(millisecond<0 || 999<millisecond)
if(millisecond!=DatatypeConstants.FIELD_UNDEFINED)
invalidFieldValue(MILLISECOND, millisecond);
! fractionalSecond = new BigDecimal((long) millisecond).movePointLeft(3);
}
}
public void setFractionalSecond(BigDecimal fractional) {
if (fractional != null) {
--- 2774,2784 ----
fractionalSecond = null;
} else {
if(millisecond<0 || 999<millisecond)
if(millisecond!=DatatypeConstants.FIELD_UNDEFINED)
invalidFieldValue(MILLISECOND, millisecond);
! fractionalSecond = BigDecimal.valueOf(millisecond, 3);
}
}
public void setFractionalSecond(BigDecimal fractional) {
if (fractional != null) {
*** 2768,2778 ****
}
// seen meta character. we don't do error check against the format
switch (format.charAt(fidx++)) {
case 'Y' : // year
! parseAndSetYear(4);
break;
case 'M' : // month
setMonth(parseInt(2, 2));
break;
--- 2826,2836 ----
}
// seen meta character. we don't do error check against the format
switch (format.charAt(fidx++)) {
case 'Y' : // year
! parseYear();
break;
case 'M' : // month
setMonth(parseInt(2, 2));
break;
*** 2849,2859 ****
throws IllegalArgumentException {
int n = 0;
char ch;
int vstart = vidx;
! while (isDigit(ch=peek()) && (vidx - vstart) <= maxDigits) {
vidx++;
n = n*10 + ch-'0';
}
if ((vidx - vstart) < minDigits) {
// we are expecting more digits
--- 2907,2917 ----
throws IllegalArgumentException {
int n = 0;
char ch;
int vstart = vidx;
! while (isDigit(ch=peek()) && (vidx - vstart) < maxDigits) {
vidx++;
n = n*10 + ch-'0';
}
if ((vidx - vstart) < minDigits) {
// we are expecting more digits
*** 2861,2904 ****
}
return n;
}
! private void parseAndSetYear(int minDigits)
throws IllegalArgumentException {
int vstart = vidx;
! int n = 0;
! boolean neg = false;
// skip leading negative, if it exists
if (peek() == '-') {
vidx++;
! neg = true;
}
! while(true) {
! char ch = peek();
! if(!isDigit(ch))
! break;
vidx++;
- n = n*10 + ch-'0';
}
!
! if ((vidx - vstart) < minDigits) {
// 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)));
}
}
private BigDecimal parseBigDecimal()
throws IllegalArgumentException {
int vstart = vidx;
--- 2919,2954 ----
}
return n;
}
! private void parseYear()
throws IllegalArgumentException {
int vstart = vidx;
! int sign = 0;
// skip leading negative, if it exists
if (peek() == '-') {
vidx++;
! sign = 1;
}
! while (isDigit(peek())) {
vidx++;
}
! final int digits = vidx - vstart - sign;
! if (digits < 4) {
// we are expecting more digits
throw new IllegalArgumentException(value); //,vidx);
}
! final String yearString = value.substring(vstart, vidx);
! if (digits < 10) {
! setYear(Integer.parseInt(yearString));
}
+ else {
+ setYear(new BigInteger(yearString));
}
+ }
private BigDecimal parseBigDecimal()
throws IllegalArgumentException {
int vstart = vidx;
*** 2920,3074 ****
/**
* 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
*/
private String format( String format ) {
! char[] buf = new char[32];
! int bufPtr = 0;
!
int fidx=0,flen=format.length();
while(fidx<flen) {
char fch = format.charAt(fidx++);
if(fch!='%') {// not a meta char
! buf[bufPtr++] = fch;
continue;
}
switch(format.charAt(fidx++)) {
case 'Y':
! if(eon==null) {
! // optimized path
! int y = getYear();
! if(y<0) {
! buf[bufPtr++] = '-';
! y = -y;
}
! 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);
! }
! 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;
! }
!
! // 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
}
}
! return new String(buf,0,bufPtr);
}
/**
! * Prints an int as two digits into the buffer.
*
* @param number
! * Number to be printed. Must be positive.
*/
! private int print2Number( char[] out, int bufptr, int number ) {
! out[bufptr++] = (char) ('0'+(number/10));
! out[bufptr++] = (char) ('0'+(number%10));
! return bufptr;
}
/**
! * Prints an int as four digits into the buffer.
*
* @param number
! * Number to be printed. Must be positive.
*/
! 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;
}
/**
* Compute <code>value*signum</code> where value==null is treated as
* value==0.
* @return non-null {@link BigInteger}.
--- 2970,3097 ----
/**
* Prints this object according to the format specification.
*
* <p>
* StringBuffer -> StringBuilder change had a very visible impact.
! * 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 ) {
! 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.append(fch);
continue;
}
switch(format.charAt(fidx++)) {
case 'Y':
! if (eon == null) {
! int absYear = year;
! if (absYear < 0) {
! buf.append('-');
! absYear = -year;
}
! printNumber(buf, absYear, 4);
}
+ else {
+ printNumber(buf, getEonAndYear(), 4);
+ }
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 buf.toString();
}
/**
! * Prints an integer as a String.
*
+ * @param out
+ * The formatted string will be appended into this buffer.
* @param number
! * 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 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 BigInteger as a String.
*
+ * @param out
+ * The formatted string will be appended into this buffer.
* @param number
! * 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 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);
+ }
/**
* Compute <code>value*signum</code> where value==null is treated as
* value==0.
* @return non-null {@link BigInteger}.
*** 3083,3090 ****
/** <p><code>reset()</code> is designed to allow the reuse of existing
* <code>XMLGregorianCalendar</code>s thus saving resources associated
* with the creation of new <code>XMLGregorianCalendar</code>s.</p>
*/
public void reset() {
! //PENDING : Implementation of reset method
}
}
--- 3106,3133 ----
/** <p><code>reset()</code> is designed to allow the reuse of existing
* <code>XMLGregorianCalendar</code>s thus saving resources associated
* with the creation of new <code>XMLGregorianCalendar</code>s.</p>
*/
public void reset() {
! 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)
}