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) }