Author: ebourg
Date: Fri Feb 15 03:31:07 2008
New Revision: 628021
URL: http://svn.apache.org/viewvc?rev=628021&view=rev
Log:
The calendar objects are now formatted with their own time zone
Removed the Java 1.3 workaround in PropertyListConfiguration to parse and
format the dates without a SimpleDateFormat
Modified:
commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/plist/PropertyListConfiguration.java
commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/plist/TestPropertyListConfiguration.java
commons/proper/configuration/branches/configuration2_experimental/xdocs/changes.xml
Modified:
commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/plist/PropertyListConfiguration.java
URL:
http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/plist/PropertyListConfiguration.java?rev=628021&r1=628020&r2=628021&view=diff
==============================================================================
---
commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/plist/PropertyListConfiguration.java
(original)
+++
commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/plist/PropertyListConfiguration.java
Fri Feb 15 03:31:07 2008
@@ -22,6 +22,7 @@
import java.io.Reader;
import java.io.Writer;
import java.net.URL;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
@@ -83,51 +84,17 @@
*/
public class PropertyListConfiguration extends
AbstractHierarchicalFileConfiguration
{
- /** Constant for the separator parser for the date part. */
- private static final DateComponentParser DATE_SEPARATOR_PARSER = new
DateSeparatorParser(
- "-");
-
- /** Constant for the separator parser for the time part. */
- private static final DateComponentParser TIME_SEPARATOR_PARSER = new
DateSeparatorParser(
- ":");
-
- /** Constant for the separator parser for blanks between the parts. */
- private static final DateComponentParser BLANK_SEPARATOR_PARSER = new
DateSeparatorParser(
- " ");
-
- /** An array with the component parsers for dealing with dates. */
- private static final DateComponentParser[] DATE_PARSERS =
- {new DateSeparatorParser("<*D"), new DateFieldParser(Calendar.YEAR, 4),
- DATE_SEPARATOR_PARSER, new DateFieldParser(Calendar.MONTH, 2, 1),
- DATE_SEPARATOR_PARSER, new DateFieldParser(Calendar.DATE, 2),
- BLANK_SEPARATOR_PARSER,
- new DateFieldParser(Calendar.HOUR_OF_DAY, 2),
- TIME_SEPARATOR_PARSER, new DateFieldParser(Calendar.MINUTE, 2),
- TIME_SEPARATOR_PARSER, new DateFieldParser(Calendar.SECOND, 2),
- BLANK_SEPARATOR_PARSER, new DateTimeZoneParser(),
- new DateSeparatorParser(">")};
+ static final SimpleDateFormat DEFAULT_DATE_FORMAT = new
SimpleDateFormat("<*'D'yyyy-MM-dd HH:mm:ss Z>");
- /** Constant for the ID prefix for GMT time zones. */
- private static final String TIME_ZONE_PREFIX = "GMT";
+ /** Instance specific format that can be used to format date in differents
time zones */
+ final SimpleDateFormat DATE_FORMAT = new
SimpleDateFormat(DEFAULT_DATE_FORMAT.toPattern());
/** The serial version UID. */
private static final long serialVersionUID = 3227248503779092127L;
- /** Constant for the milliseconds of a minute.*/
- private static final int MILLIS_PER_MINUTE = 1000 * 60;
-
- /** Constant for the minutes per hour.*/
- private static final int MINUTES_PER_HOUR = 60;
-
/** Size of the indentation for the generated file. */
private static final int INDENT_SIZE = 4;
- /** Constant for the length of a time zone.*/
- private static final int TIME_ZONE_LENGTH = 5;
-
- /** Constant for the padding character in the date format.*/
- private static final char PAD_CHAR = '0';
-
/**
* Creates an empty PropertyListConfiguration object which can be
* used to synthesize a new plist file by adding values and
@@ -369,7 +336,19 @@
}
else if (value instanceof Date)
{
- out.print(formatDate((Date) value));
+ out.print(DATE_FORMAT.format((Date) value));
+ }
+ else if (value instanceof Calendar)
+ {
+ // change the time zone of the date format
+ Calendar calendar = (Calendar) value;
+ TimeZone previousZone = DATE_FORMAT.getTimeZone();
+ DATE_FORMAT.setTimeZone(calendar.getTimeZone());
+
+ out.print(DATE_FORMAT.format(calendar.getTime()));
+
+ // restore the previous time zone of the date format
+ DATE_FORMAT.setTimeZone(previousZone);
}
else if (value != null)
{
@@ -431,248 +410,16 @@
*/
static Date parseDate(String s) throws ParseException
{
- Calendar cal = Calendar.getInstance();
- cal.clear();
- int index = 0;
-
- for (int i = 0; i < DATE_PARSERS.length; i++)
- {
- index += DATE_PARSERS[i].parseComponent(s, index, cal);
- }
-
- return cal.getTime();
- }
-
- /**
- * Returns a string representation for the date specified by the given
- * calendar.
- *
- * @param cal the calendar with the initialized date
- * @return a string for this date
- */
- static String formatDate(Calendar cal)
- {
- StringBuilder buf = new StringBuilder();
-
- for (int i = 0; i < DATE_PARSERS.length; i++)
- {
- DATE_PARSERS[i].formatComponent(buf, cal);
- }
-
- return buf.toString();
- }
-
- /**
- * Returns a string representation for the specified date.
- *
- * @param date the date
- * @return a string for this date
- */
- static String formatDate(Date date)
- {
- Calendar cal = Calendar.getInstance();
- cal.setTime(date);
- return formatDate(cal);
- }
-
- /**
- * A helper class for parsing and formatting date literals. Usually we
would
- * use <code>SimpleDateFormat</code> for this purpose, but in Java 1.3 the
- * functionality of this class is limited. So we have a hierarchy of parser
- * classes instead that deal with the different components of a date
- * literal.
- */
- private abstract static class DateComponentParser
- {
- /**
- * Parses a component from the given input string.
- *
- * @param s the string to be parsed
- * @param index the current parsing position
- * @param cal the calendar where to store the result
- * @return the length of the processed component
- * @throws ParseException if the component cannot be extracted
- */
- public abstract int parseComponent(String s, int index, Calendar cal)
- throws ParseException;
-
- /**
- * Formats a date component. This method is used for converting a date
- * in its internal representation into a string literal.
- *
- * @param buf the target buffer
- * @param cal the calendar with the current date
- */
- public abstract void formatComponent(StringBuilder buf, Calendar cal);
-
- /**
- * Checks whether the given string has at least <code>length</code>
- * characters starting from the given parsing position. If this is not
- * the case, an exception will be thrown.
- *
- * @param s the string to be tested
- * @param index the current index
- * @param length the minimum length after the index
- * @throws ParseException if the string is too short
- */
- protected void checkLength(String s, int index, int length)
- throws ParseException
- {
- int len = (s == null) ? 0 : s.length();
- if (index + length > len)
- {
- throw new ParseException("Input string too short: " + s
- + ", index: " + index);
- }
- }
-
- /**
- * Adds a number to the given string buffer and adds leading '0'
- * characters until the given length is reached.
- *
- * @param buf the target buffer
- * @param num the number to add
- * @param length the required length
- */
- protected void padNum(StringBuilder buf, int num, int length)
- {
- buf.append(StringUtils.leftPad(String.valueOf(num), length,
PAD_CHAR));
- }
- }
-
- /**
- * A specialized date component parser implementation that deals with
- * numeric calendar fields. The class is able to extract fields from a
- * string literal and to format a literal from a calendar.
- */
- private static class DateFieldParser extends DateComponentParser
- {
- /** Stores the calendar field to be processed. */
- private int calendarField;
-
- /** Stores the length of this field. */
- private int length;
-
- /** An optional offset to add to the calendar field. */
- private int offset;
-
- /**
- * Creates a new instance of <code>DateFieldParser</code>.
- *
- * @param calFld the calendar field code
- * @param len the length of this field
- */
- public DateFieldParser(int calFld, int len)
- {
- this(calFld, len, 0);
- }
-
- /**
- * Creates a new instance of <code>DateFieldParser</code> and fully
- * initializes it.
- *
- * @param calFld the calendar field code
- * @param len the length of this field
- * @param ofs an offset to add to the calendar field
- */
- public DateFieldParser(int calFld, int len, int ofs)
- {
- calendarField = calFld;
- length = len;
- offset = ofs;
- }
-
- public void formatComponent(StringBuilder buf, Calendar cal)
- {
- padNum(buf, cal.get(calendarField) + offset, length);
- }
-
- public int parseComponent(String s, int index, Calendar cal)
- throws ParseException
- {
- checkLength(s, index, length);
- try
- {
- cal.set(calendarField, Integer.parseInt(s.substring(index,
index + length)) - offset);
- return length;
- }
- catch (NumberFormatException nfex)
- {
- throw new ParseException("Invalid number: " + s + ", index " +
index);
- }
- }
- }
-
- /**
- * A specialized date component parser implementation that deals with
- * separator characters.
- */
- private static class DateSeparatorParser extends DateComponentParser
- {
- /** Stores the separator. */
- private String separator;
-
- /**
- * Creates a new instance of <code>DateSeparatorParser</code> and sets
- * the separator string.
- *
- * @param sep the separator string
- */
- public DateSeparatorParser(String sep)
- {
- separator = sep;
- }
-
- public void formatComponent(StringBuilder buf, Calendar cal)
- {
- buf.append(separator);
- }
-
- public int parseComponent(String s, int index, Calendar cal)
- throws ParseException
+ try
{
- checkLength(s, index, separator.length());
- if (!s.startsWith(separator, index))
+ synchronized (DEFAULT_DATE_FORMAT)
{
- throw new ParseException("Invalid input: " + s + ", index " +
index + ", expected " + separator);
+ return DEFAULT_DATE_FORMAT.parse(s);
}
- return separator.length();
}
- }
-
- /**
- * A specialized date component parser implementation that deals with the
- * time zone part of a date component.
- */
- private static class DateTimeZoneParser extends DateComponentParser
- {
- public void formatComponent(StringBuilder buf, Calendar cal)
+ catch (Exception e)
{
- TimeZone tz = cal.getTimeZone();
- int ofs = tz.getRawOffset() / MILLIS_PER_MINUTE;
- if (ofs < 0)
- {
- buf.append('-');
- ofs = -ofs;
- }
- else
- {
- buf.append('+');
- }
- int hour = ofs / MINUTES_PER_HOUR;
- int min = ofs % MINUTES_PER_HOUR;
- padNum(buf, hour, 2);
- padNum(buf, min, 2);
- }
-
- public int parseComponent(String s, int index, Calendar cal)
- throws ParseException
- {
- checkLength(s, index, TIME_ZONE_LENGTH);
- TimeZone tz = TimeZone.getTimeZone(TIME_ZONE_PREFIX
- + s.substring(index, index + TIME_ZONE_LENGTH));
- cal.setTimeZone(tz);
- return TIME_ZONE_LENGTH;
+ throw (ParseException) new ParseException("Unable to parse the
date").initCause(e);
}
}
}
Modified:
commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/plist/TestPropertyListConfiguration.java
URL:
http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/plist/TestPropertyListConfiguration.java?rev=628021&r1=628020&r2=628021&view=diff
==============================================================================
---
commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/plist/TestPropertyListConfiguration.java
(original)
+++
commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/plist/TestPropertyListConfiguration.java
Fri Feb 15 03:31:07 2008
@@ -17,25 +17,28 @@
package org.apache.commons.configuration2.plist;
+import java.io.BufferedReader;
import java.io.File;
+import java.io.FileReader;
import java.io.StringReader;
+import java.text.SimpleDateFormat;
import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.List;
-import java.util.Date;
import java.util.TimeZone;
-import junit.framework.TestCase;
-import junitx.framework.ArrayAssert;
-import junitx.framework.ListAssert;
-import junitx.framework.ObjectAssert;
import org.apache.commons.configuration2.Configuration;
import org.apache.commons.configuration2.ConfigurationAssert;
import org.apache.commons.configuration2.ConfigurationComparator;
import org.apache.commons.configuration2.ConfigurationException;
import org.apache.commons.configuration2.StrictConfigurationComparator;
-import org.apache.commons.configuration2.plist.ParseException;
-import org.apache.commons.configuration2.plist.PropertyListConfiguration;
+
+import junit.framework.TestCase;
+import junitx.framework.ArrayAssert;
+import junitx.framework.ListAssert;
+import junitx.framework.ObjectAssert;
/**
* @author Emmanuel Bourg
@@ -191,6 +194,33 @@
assertEquals("date", date, config.getProperty("date"));
}
+ /**
+ * Test if the calendar objets are saved with their time zone
+ */
+ public void testCalendar() throws Exception
+ {
+ File savedFile = new File("target/testcalendar.plist");
+
+ // remove the file previously saved if necessary
+ if (savedFile.exists())
+ {
+ assertTrue(savedFile.delete());
+ }
+
+ Calendar calendar = new GregorianCalendar(2008, Calendar.JANUARY, 1);
+ calendar.setTimeZone(TimeZone.getTimeZone("GMT-0200"));
+
+ PropertyListConfiguration config = new PropertyListConfiguration();
+ config.setProperty("calendar", calendar);
+ config.save(savedFile);
+
+ BufferedReader in = new BufferedReader(new FileReader(savedFile));
+ in.readLine();
+ assertEquals("calendar output", "calendar = <*D2008-01-01 00:00:00
-0200>;", in.readLine().trim());
+
+ in.close();
+ }
+
public void testSave() throws Exception
{
File savedFile = new File("target/testsave.plist");
@@ -314,8 +344,7 @@
{
try
{
- PropertyListConfiguration
- .parseDate("<*D2002-03-22 1c:30:00 +0100>");
+ PropertyListConfiguration.parseDate("<*D2002-03-22 1c:30:00
+0100>");
fail("Could parse date with an invalid number!");
}
catch (ParseException pex)
@@ -347,8 +376,7 @@
{
try
{
- PropertyListConfiguration
- .parseDate("<*D2002+03-22 11:30:00 +0100>");
+ PropertyListConfiguration.parseDate("<*D2002+03-22 11:30:00
+0100>");
fail("Could parse date with an invalid separator!");
}
catch (ParseException pex)
@@ -378,16 +406,18 @@
*/
public void testFormatDate()
{
- Calendar cal = Calendar.getInstance();
- cal.clear();
- cal.set(2007, 9, 29, 23, 4, 30);
+ SimpleDateFormat format = config.DATE_FORMAT;
+
+ Calendar cal = new GregorianCalendar(2007, Calendar.OCTOBER, 29, 23,
4, 30);
cal.setTimeZone(TimeZone.getTimeZone("GMT-0230"));
- assertEquals("Wrong date literal (1)", "<*D2007-10-29 23:04:30 -0230>",
- PropertyListConfiguration.formatDate(cal));
- cal.clear();
- cal.set(2007, 9, 30, 22, 2, 15);
+ format.setTimeZone(cal.getTimeZone());
+
+ assertEquals("Wrong date literal (1)", "<*D2007-10-29 23:04:30
-0230>", format.format(cal.getTime()));
+
+ cal = new GregorianCalendar(2007, Calendar.OCTOBER, 30, 22, 2, 15);
cal.setTimeZone(TimeZone.getTimeZone("GMT+1111"));
- assertEquals("Wrong date literal (2)", "<*D2007-10-30 22:02:15 +1111>",
- PropertyListConfiguration.formatDate(cal));
+ format.setTimeZone(cal.getTimeZone());
+
+ assertEquals("Wrong date literal (2)", "<*D2007-10-30 22:02:15
+1111>", format.format(cal.getTime()));
}
}
Modified:
commons/proper/configuration/branches/configuration2_experimental/xdocs/changes.xml
URL:
http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/xdocs/changes.xml?rev=628021&r1=628020&r2=628021&view=diff
==============================================================================
---
commons/proper/configuration/branches/configuration2_experimental/xdocs/changes.xml
(original)
+++
commons/proper/configuration/branches/configuration2_experimental/xdocs/changes.xml
Fri Feb 15 03:31:07 2008
@@ -29,11 +29,14 @@
</action>
<action dev="oheger" type="update">
To avoid incompatibilities with older versions the package structure
- has been changed. The main package is now
- org.apache.commons.configuration2.
+ has been changed. The main package is now
+ org.apache.commons.configuration2.
</action>
<action dev="oheger" type="update">
- Commons Configuration now requires Java 1.5.
+ Commons Configuration now requires Java 5.
+ </action>
+ <action dev="ebourg" type="update">
+ Calendar objects in PropertyListConfiguration are now saved with their
own time zone.
</action>
</release>