- Revision
- 654
- Author
- mauro
- Date
- 2008-04-28 09:01:31 -0500 (Mon, 28 Apr 2008)
Log Message
Enhanced DateValueConverter to handle different date types (DAY, TIME and DATE), with format patterns configurable via injectable properties as well as message resources.
Modified Paths
- trunk/examples/freemarker-example/src/main/java/org/codehaus/waffle/example/freemarker/model/Person.java
- trunk/examples/freemarker-example/src/main/java/org/codehaus/waffle/example/freemarker/persister/PersistablePerson.java
- trunk/examples/freemarker-example/src/main/webapp/people/edit.ftl
- trunk/waffle-core/src/main/java/org/codehaus/waffle/bind/converters/DateValueConverter.java
- trunk/waffle-core/src/test/java/org/codehaus/waffle/bind/converters/DateValueConverterTest.java
- trunk/waffle-core/src/test/resources/FakeResourceBundle.properties
Diff
Modified: trunk/examples/freemarker-example/src/main/java/org/codehaus/waffle/example/freemarker/model/Person.java (653 => 654)
--- trunk/examples/freemarker-example/src/main/java/org/codehaus/waffle/example/freemarker/model/Person.java 2008-04-28 10:31:41 UTC (rev 653) +++ trunk/examples/freemarker-example/src/main/java/org/codehaus/waffle/example/freemarker/model/Person.java 2008-04-28 14:01:31 UTC (rev 654) @@ -15,6 +15,10 @@ public Date getDateOfBirth(); + public Date getBirthDay(); + + public Date getBirthTime(); + public List<String> getSkills(); public List<Integer> getLevels();
Modified: trunk/examples/freemarker-example/src/main/java/org/codehaus/waffle/example/freemarker/persister/PersistablePerson.java (653 => 654)
--- trunk/examples/freemarker-example/src/main/java/org/codehaus/waffle/example/freemarker/persister/PersistablePerson.java 2008-04-28 10:31:41 UTC (rev 653) +++ trunk/examples/freemarker-example/src/main/java/org/codehaus/waffle/example/freemarker/persister/PersistablePerson.java 2008-04-28 14:01:31 UTC (rev 654) @@ -13,6 +13,8 @@ private String lastName; private String email; private Date dateOfBirth; + private Date birthDay; + private Date birthTime; private List<String> skills; private List<Integer> levels; private List<Double> grades; @@ -23,6 +25,8 @@ lastName = ""; email = ""; dateOfBirth = new Date(); + birthDay = new Date(); + birthTime = new Date(); skills = new ArrayList<String>(); levels = new ArrayList<Integer>(); grades = new ArrayList<Double>(); @@ -34,6 +38,8 @@ this.lastName = person.getLastName(); this.email = person.getEmail(); this.dateOfBirth = person.getDateOfBirth(); + this.birthDay = person.getBirthDay(); + this.birthTime = person.getBirthTime(); this.skills = person.getSkills(); this.levels = person.getLevels(); this.grades = person.getGrades(); @@ -79,6 +85,22 @@ this.dateOfBirth = dateOfBirth; } + public Date getBirthDay() { + return birthDay; + } + + public void setBirthDay(Date birthDay) { + this.birthDay = birthDay; + } + + public Date getBirthTime() { + return birthTime; + } + + public void setBirthTime(Date birthTime) { + this.birthTime = birthTime; + } + public List<String> getSkills() { return skills; }
Modified: trunk/examples/freemarker-example/src/main/webapp/people/edit.ftl (653 => 654)
--- trunk/examples/freemarker-example/src/main/webapp/people/edit.ftl 2008-04-28 10:31:41 UTC (rev 653) +++ trunk/examples/freemarker-example/src/main/webapp/people/edit.ftl 2008-04-28 14:01:31 UTC (rev 654) @@ -2,59 +2,69 @@ <#import "/ftl/waffle/validation.ftl" as v> <div class="editContainer" xmlns="http://www.w3.org/1999/xhtml"> - <h3>Edit Person</h3> - <@v.errorsAsUl errors "true" "false" "class='errors'"/> - <div class="fieldRow"> - <label for="" - <@w.text "person.id" "${person.id}" "readonly='true' disabled='true'"/> - <br style="clear:both"/> + <fieldset> + <label>Edit Person</label> + <p class="fieldRow"> + <label for="" + <@w.text "person.id" "${person.id}" "readonly='true' disabled='true'"/> + </p> + <p class="fieldRow"> + <label for="" Name:</label> + <@w.text "person.firstName" "${person.firstName}"/> + </p> + <p class="fieldRow"> + <label for="" Name:</label> + <@w.text "person.lastName" "${person.lastName}"/> + </p> + <p class="fieldRow"> + <label for="" + <@w.text "person.email" "${person.email}"/> + </p> + <p class="fieldRow"> + <label for="" Of Birth:</label> + <#if person.dateOfBirth??> + <@w.text "person.dateOfBirth" "${person.dateOfBirth?string('dd/MM/yyyy')}"/> + <#else> + <@w.text "person.dateOfBirth" ""/> + </#if> + </p> + <p class="fieldRow"> + <label for="" Day:</label> + <#if person.birthDay??> + <@w.text "person.birthDay" "${person.birthDay?string('dd/MM/yyyy')}"/> + <#else> + <@w.text "person.birthDay" ""/> + </#if> + </p> + <p class="fieldRow"> + <label for="" Time:</label> + <#if person.birthTime??> + <@w.text "person.birthTime" "${person.birthTime?string('dd/MM/yyyy HH:mm:ss')}"/> + <#else> + <@w.text "person.birthTime" ""/> + </#if> + </p> + <p class="fieldRow"> + <label for="" + <@w.selectMultiple "person.skills" controller.getSkills() person.getSkills() "size='5'"/> + </p> + <p class="fieldRow"> + <label for="" + <@w.textAsCSV "person.levels" person.getLevels()![] /> + </p> + <p class="fieldRow"> + <label for="" + <@w.textAsCSV "person.grades" person.getGrades()![] /> + </p> + </fieldset> + + <div class="controls"> + <a href="" | + <a href="" </div> - <div class="fieldRow"> - <label for="" Name:</label> - <@w.text "person.firstName" "${person.firstName}"/> - <br style="clear:both"/> - </div> - <div class="fieldRow"> - <label for="" Name:</label> - <@w.text "person.lastName" "${person.lastName}"/> - <br style="clear:both"/> - </div> - <div class="fieldRow"> - <label for="" - <@w.text "person.email" "${person.email}"/> - <br style="clear:both"/> - </div> - <div class="fieldRow"> - <label for="" Of Birth:</label> - <#if person.dateOfBirth??> - <@w.text "person.dateOfBirth" "${person.dateOfBirth?string('dd/MM/yyyy')}"/> - <#else> - <@w.text "person.dateOfBirth" ""/> - </#if> - <br style="clear:both"/> - </div> - <div class="fieldRow"> - <label for="" - <@w.selectMultiple "person.skills" controller.getSkills() person.getSkills() "size='5'"/> - <br style="clear:both"/> - </div> - <div class="fieldRow"> - <label for="" - <@w.textAsCSV "person.levels" person.getLevels()![] /> - <br style="clear:both"/> - </div> - <div class="fieldRow"> - <label for="" - <@w.textAsCSV "person.grades" person.getGrades()![] /> - <br style="clear:both"/> - </div> - - <br/> - <a href="" | - <a href="" - + <#include "/fielderrors.ftl" parse="true"> </div> \ No newline at end of file
Modified: trunk/waffle-core/src/main/java/org/codehaus/waffle/bind/converters/DateValueConverter.java (653 => 654)
--- trunk/waffle-core/src/main/java/org/codehaus/waffle/bind/converters/DateValueConverter.java 2008-04-28 10:31:41 UTC (rev 653) +++ trunk/waffle-core/src/main/java/org/codehaus/waffle/bind/converters/DateValueConverter.java 2008-04-28 14:01:31 UTC (rev 654) @@ -13,6 +13,7 @@ import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; +import java.util.Properties; import org.codehaus.waffle.i18n.MessageResources; @@ -28,7 +29,13 @@ * (message defaults to [EMAIL PROTECTED] #DEFAULT_DATE_MISSING_MESSAGE})</li> * <li>"date.format" ([EMAIL PROTECTED] #DATE_FORMAT_KEY}): date format used in parsing (defaults to * [EMAIL PROTECTED] #DEFAULT_DATE_FORMAT})</li> + * <li>"date.format.day" ([EMAIL PROTECTED] #DAY_FORMAT_KEY}): date format used in parsing properties that end in "Day" + * (defaults to [EMAIL PROTECTED] #DEFAULT_DAY_FORMAT})</li> + * <li>"date.format.time" ([EMAIL PROTECTED] #TIME_FORMAT_KEY}): date format used in parsing properties that end in "Time" + * (defaults to [EMAIL PROTECTED] #DEFAULT_TIME_FORMAT})</li> * </ul> + * The patterns are also optionally injectable via <code>Properties</code> in the constructor and take precedence over + * the ones configured in the messages resources. * * @author Michael Ward * @author Mauro Talevi @@ -37,32 +44,91 @@ static final String BIND_ERROR_DATE_KEY = "bind.error.date"; static final String BIND_ERROR_DATE_MISSING_KEY = "bind.error.date.missing"; static final String DATE_FORMAT_KEY = "date.format"; + static final String DAY_FORMAT_KEY = "date.format.day"; + static final String TIME_FORMAT_KEY = "date.format.time"; + static final String DAY_SUFFIX = "Day"; + static final String TIME_SUFFIX = "Time"; static final String DEFAULT_DATE_FORMAT = "dd/MM/yyyy"; + static final String DEFAULT_DAY_FORMAT = "dd/MM/yyyy"; + static final String DEFAULT_TIME_FORMAT = "dd/MM/yyyy HH:mm:ss"; static final String DEFAULT_DATE_MESSAGE = "Invalid date {1} (using format {2}) for field {0}"; static final String DEFAULT_DATE_MISSING_MESSAGE = "Missing date value for field {0}"; + private Properties patterns; + public DateValueConverter(MessageResources messageResources) { + this(messageResources, new Properties()); + } + + public DateValueConverter(MessageResources messageResources, Properties patterns) { super(messageResources); + this.patterns = patterns; } public boolean accept(Class<?> type) { return Date.class.isAssignableFrom(type); } - @SuppressWarnings({"unchecked"}) + @SuppressWarnings( { "unchecked" }) public <T> T convertValue(String propertyName, String value, Class<T> toType) { String fieldName = messageFor(propertyName, propertyName); - if ( missingValue(value) ) { + if (missingValue(value)) { return (T) convertMissingValue(BIND_ERROR_DATE_MISSING_KEY, DEFAULT_DATE_MISSING_MESSAGE, fieldName); } - String dateFormat = messageFor(DATE_FORMAT_KEY, DEFAULT_DATE_FORMAT); + SimpleDateFormat dateFormat = dateFormatFor(propertyName); try { - return (T) new SimpleDateFormat(dateFormat).parse(value); + return (T) dateFormat.parse(value); } catch (ParseException e) { - throw newBindException(BIND_ERROR_DATE_KEY, DEFAULT_DATE_MESSAGE, fieldName, value, dateFormat); + throw newBindException(BIND_ERROR_DATE_KEY, DEFAULT_DATE_MESSAGE, fieldName, value, dateFormat.toPattern()); } } + private enum DateType { + DAY, TIME, DATE + }; + + /** + * Retrieves the date format for the given property name + * + * @param propertyName the property name + * @return The SimpleDateFormat + */ + private SimpleDateFormat dateFormatFor(String propertyName) { + DateType dateType = dateType(propertyName); + String pattern = null; + switch (dateType) { + case DAY: + pattern = patternFor(DAY_FORMAT_KEY, DEFAULT_DAY_FORMAT); + break; + case TIME: + pattern = patternFor(TIME_FORMAT_KEY, DEFAULT_TIME_FORMAT); + break; + default: + pattern = patternFor(DATE_FORMAT_KEY, DEFAULT_DATE_FORMAT); + } + return new SimpleDateFormat(pattern); + } + + private String patternFor(String key, String defaultPattern) { + if ( patterns.containsKey(key)) { + return patterns.getProperty(key); + } + return messageFor(key, defaultPattern); + } + + private DateType dateType(String propertyName) { + if (endsWith(propertyName, DAY_SUFFIX)) { + return DateType.DAY; + } else if (endsWith(propertyName, TIME_SUFFIX)) { + return DateType.TIME; + } + return DateType.DATE; + } + + private boolean endsWith(String propertyName, String suffix) { + return propertyName != null && propertyName.endsWith(suffix); + } + }
Modified: trunk/waffle-core/src/test/java/org/codehaus/waffle/bind/converters/DateValueConverterTest.java (653 => 654)
--- trunk/waffle-core/src/test/java/org/codehaus/waffle/bind/converters/DateValueConverterTest.java 2008-04-28 10:31:41 UTC (rev 653) +++ trunk/waffle-core/src/test/java/org/codehaus/waffle/bind/converters/DateValueConverterTest.java 2008-04-28 14:01:31 UTC (rev 654) @@ -4,9 +4,11 @@ import static org.codehaus.waffle.bind.converters.DateValueConverter.BIND_ERROR_DATE_KEY; import static org.codehaus.waffle.bind.converters.DateValueConverter.BIND_ERROR_DATE_MISSING_KEY; import static org.codehaus.waffle.bind.converters.DateValueConverter.DATE_FORMAT_KEY; +import static org.codehaus.waffle.bind.converters.DateValueConverter.DAY_FORMAT_KEY; import static org.codehaus.waffle.bind.converters.DateValueConverter.DEFAULT_DATE_FORMAT; import static org.codehaus.waffle.bind.converters.DateValueConverter.DEFAULT_DATE_MESSAGE; import static org.codehaus.waffle.bind.converters.DateValueConverter.DEFAULT_DATE_MISSING_MESSAGE; +import static org.codehaus.waffle.bind.converters.DateValueConverter.TIME_FORMAT_KEY; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -15,21 +17,19 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; +import java.util.Properties; -import ognl.OgnlException; - import org.codehaus.waffle.bind.BindException; import org.codehaus.waffle.i18n.DefaultMessageResources; import org.codehaus.waffle.i18n.MessageResourcesConfiguration; import org.junit.Test; /** - * * @author Mauro Talevi */ public class DateValueConverterTest { - private MessageResourcesConfiguration configuration = new MessageResourcesConfiguration(){ + private MessageResourcesConfiguration configuration = new MessageResourcesConfiguration() { public Locale getDefaultLocale() { return Locale.UK; @@ -38,8 +38,9 @@ public String getResourceBundleName() { return "FakeResourceBundle"; } - + }; + @Test public void canAccept() { DateValueConverter converter = new DateValueConverter(new DefaultMessageResources()); @@ -48,22 +49,41 @@ } @Test - public void canConvertWithCustomDateFormat() throws OgnlException { + public void canConvertWithDateFormatConfiguredViaMessageResource() { DefaultMessageResources resources = new DefaultMessageResources(configuration); DateValueConverter converter = new DateValueConverter(resources); - Date date = converter.convertValue("property-name", "04-03-2008", Date.class); + assertDateFormattable("04-03-2008", resources.getMessage(DATE_FORMAT_KEY), converter.convertValue( + "property-name", "04-03-2008", Date.class)); + assertDateFormattable("04", resources.getMessage(DAY_FORMAT_KEY), converter.convertValue("someDay", "04", + Date.class)); + assertDateFormattable("11:11:11", resources.getMessage(TIME_FORMAT_KEY), converter.convertValue("someTime", + "11:11:11", Date.class)); + } - assertEquals("04-03-2008", new SimpleDateFormat(resources.getMessage(DATE_FORMAT_KEY)).format(date)); + @Test + public void canConvertWithDateFormatConfiguredViaProperties() { + Properties patterns = new Properties(); + patterns.setProperty(DateValueConverter.DATE_FORMAT_KEY, "dd-MM-yyyy"); + patterns.setProperty(DateValueConverter.DAY_FORMAT_KEY, "dd"); + patterns.setProperty(DateValueConverter.TIME_FORMAT_KEY, "HH:mm:ss"); + DateValueConverter converter = new DateValueConverter(new DefaultMessageResources(), patterns); + assertDateFormattable("04-03-2008", "dd-MM-yyyy", converter.convertValue("property-name", "04-03-2008", + Date.class)); + assertDateFormattable("04", "dd", converter.convertValue("someDay", "04", Date.class)); + assertDateFormattable("11:11:11", "HH:mm:ss", converter.convertValue("someTime", "11:11:11", Date.class)); } @Test public void canConvertWithDefaultDateFormat() { DateValueConverter converter = new DateValueConverter(new DefaultMessageResources()); - Date date = converter.convertValue("property-name", "04/03/2008", Date.class); + assertDateFormattable("04/03/2008", DEFAULT_DATE_FORMAT, converter.convertValue("property-name", "04/03/2008", + Date.class)); + } - assertEquals("04/03/2008", new SimpleDateFormat(DEFAULT_DATE_FORMAT).format(date)); + private void assertDateFormattable(String value, String pattern, Date date) { + assertEquals(value, new SimpleDateFormat(pattern).format(date)); } - + @Test public void canHandleMissingValues() { DefaultMessageResources resources = new DefaultMessageResources(configuration); @@ -71,7 +91,7 @@ assertNull(converter.convertValue("property-name", null, Date.class)); assertNull(converter.convertValue("property-name", "", Date.class)); assertNull(converter.convertValue("property-name", " ", Date.class)); - } + } @Test public void canFailConversionWithCustomErrorMessages() { @@ -80,22 +100,23 @@ try { converter.convertValue("property-name", "bad-value", Date.class); fail("Expected BindException"); - } catch ( BindException e) { - assertEquals(format(resources.getMessage(BIND_ERROR_DATE_KEY), "property-name", "bad-value", resources.getMessage(DATE_FORMAT_KEY)), e.getMessage()); + } catch (BindException e) { + assertEquals(format(resources.getMessage(BIND_ERROR_DATE_KEY), "property-name", "bad-value", resources + .getMessage(DATE_FORMAT_KEY)), e.getMessage()); } - DateValueConverter strictConverter = new DateValueConverter(resources){ + DateValueConverter strictConverter = new DateValueConverter(resources) { @Override protected Object convertMissingValue(String key, String defaultMessage, Object... parameters) { - throw newBindException(key, defaultMessage, parameters); + throw newBindException(key, defaultMessage, parameters); } }; try { strictConverter.convertValue("property-name", null, Date.class); fail("Expected BindException"); - } catch ( BindException e) { + } catch (BindException e) { assertEquals(format(resources.getMessage(BIND_ERROR_DATE_MISSING_KEY), "property-name"), e.getMessage()); } - } + } @Test public void canFailConversionWithDefaultErrorMessages() { @@ -103,22 +124,22 @@ try { converter.convertValue("property-name", "bad-value", Date.class); fail("Expected BindException"); - } catch ( BindException e) { - assertEquals(format(DEFAULT_DATE_MESSAGE, "property-name", "bad-value", DEFAULT_DATE_FORMAT), e.getMessage()); + } catch (BindException e) { + assertEquals(format(DEFAULT_DATE_MESSAGE, "property-name", "bad-value", DEFAULT_DATE_FORMAT), e + .getMessage()); } - DateValueConverter strictConverter = new DateValueConverter(new DefaultMessageResources()){ + DateValueConverter strictConverter = new DateValueConverter(new DefaultMessageResources()) { @Override protected Object convertMissingValue(String key, String defaultMessage, Object... parameters) { - throw newBindException(key, defaultMessage, parameters); + throw newBindException(key, defaultMessage, parameters); } }; try { strictConverter.convertValue("property-name", null, Date.class); fail("Expected BindException"); - } catch ( BindException e) { + } catch (BindException e) { assertEquals(format(DEFAULT_DATE_MISSING_MESSAGE, "property-name"), e.getMessage()); } - } + } } -
Modified: trunk/waffle-core/src/test/resources/FakeResourceBundle.properties (653 => 654)
--- trunk/waffle-core/src/test/resources/FakeResourceBundle.properties 2008-04-28 10:31:41 UTC (rev 653) +++ trunk/waffle-core/src/test/resources/FakeResourceBundle.properties 2008-04-28 14:01:31 UTC (rev 654) @@ -1,6 +1,8 @@ company=thoughtworks foo.bar=hello {0} date.format=dd-MM-yyyy +date.format.day=dd +date.format.time=HH:mm:ss bind.error.date=Date {1} has invalid format {2} for field {0} bind.error.date.missing=Date field {0} is missing bind.error.list=No list values for field {0}
To unsubscribe from this list please visit:
