- Revision
- 625
- Author
- mauro
- Date
- 2008-04-19 08:11:22 -0500 (Sat, 19 Apr 2008)
Log Message
WAFFLE-68: Refactored bind value converters to return null for missing values, but allow behaviour to be overridden to throw a bind exception.
Modified Paths
- trunk/examples/simple-example/src/main/webapp/WEB-INF/web.xml
- trunk/waffle-core/src/main/java/org/codehaus/waffle/bind/converters/DateValueConverter.java
- trunk/waffle-core/src/main/java/org/codehaus/waffle/bind/converters/ListValueConverter.java
- trunk/waffle-core/src/test/java/org/codehaus/waffle/bind/converters/DateValueConverterTest.java
- trunk/waffle-core/src/test/java/org/codehaus/waffle/bind/converters/ListValueConverterTest.java
- trunk/waffle-core/src/test/java/org/codehaus/waffle/bind/ognl/DelegatingTypeConverterTest.java
- trunk/waffle-distribution/src/site/content/binding.html
Added Paths
Diff
Added: trunk/examples/simple-example/src/main/java/org/codehaus/waffle/example/simple/StrictDateValueConverter.java (0 => 625)
--- trunk/examples/simple-example/src/main/java/org/codehaus/waffle/example/simple/StrictDateValueConverter.java (rev 0) +++ trunk/examples/simple-example/src/main/java/org/codehaus/waffle/example/simple/StrictDateValueConverter.java 2008-04-19 13:11:22 UTC (rev 625) @@ -0,0 +1,22 @@ +package org.codehaus.waffle.example.simple; + +import org.codehaus.waffle.bind.converters.DateValueConverter; +import org.codehaus.waffle.i18n.MessageResources; + +/** + * Extends DateValueConverter to enforce no missing values are allowed. + * + * @author Mauro Talevi + */ +public class StrictDateValueConverter extends DateValueConverter { + + public StrictDateValueConverter(MessageResources messageResources) { + super(messageResources); + } + + @Override + protected Object convertMissingValue(String key, String defaultMessage, Object... parameters) { + throw newBindException(key, defaultMessage, parameters); + } + +}
Modified: trunk/examples/simple-example/src/main/webapp/WEB-INF/web.xml (624 => 625)
--- trunk/examples/simple-example/src/main/webapp/WEB-INF/web.xml 2008-04-18 17:03:29 UTC (rev 624) +++ trunk/examples/simple-example/src/main/webapp/WEB-INF/web.xml 2008-04-19 13:11:22 UTC (rev 625) @@ -15,7 +15,7 @@ <!-- 2. We are adding a custom components --> <context-param> <param-name>register:DateConverter</param-name> - <param-value>org.codehaus.waffle.bind.converters.DateValueConverter</param-value> + <param-value>org.codehaus.waffle.example.simple.StrictDateValueConverter</param-value> </context-param> <context-param> <param-name>org.codehaus.waffle.monitor.ActionMonitor</param-name>
Added: trunk/waffle-core/src/main/java/org/codehaus/waffle/bind/converters/AbstractValueConverter.java (0 => 625)
--- trunk/waffle-core/src/main/java/org/codehaus/waffle/bind/converters/AbstractValueConverter.java (rev 0) +++ trunk/waffle-core/src/main/java/org/codehaus/waffle/bind/converters/AbstractValueConverter.java 2008-04-19 13:11:22 UTC (rev 625) @@ -0,0 +1,55 @@ +/***************************************************************************** + * Copyright (c) 2005-2008 Michael Ward * + * All rights reserved. * + * ------------------------------------------------------------------------- * + * The software in this package is published under the terms of the BSD * + * style license a copy of which has been included with this distribution in * + * the LICENSE.txt file. * + * * + * Original code by: Mauro Talevi * + *****************************************************************************/ +package org.codehaus.waffle.bind.converters; + +import org.codehaus.waffle.bind.BindException; +import org.codehaus.waffle.bind.ValueConverter; +import org.codehaus.waffle.i18n.MessageResources; + +/** + * Abstract <code>ValueConverter</code> that holds utility functionality common to all value converters. + * + * @author Mauro Talevi + */ +public abstract class AbstractValueConverter implements ValueConverter { + + protected final MessageResources messageResources; + + protected AbstractValueConverter(MessageResources messageResources) { + this.messageResources = messageResources; + } + + protected boolean missingValue(String value) { + return value == null || value.trim().length() == 0; + } + + /** + * Handles the case of a missing value. By default it return a <code>null</code> converted value, + * but can be overridden to throw a BindException + * + * @param key the error message key + * @param defaultMessage the default message if key is not found + * @param parameters the message formatting parameters + * @return A converted object when value is missing, <code>null</code> by default. + */ + protected Object convertMissingValue(String key, String defaultMessage, Object... parameters) { + return null; + } + + protected BindException newBindException(String key, String defaultMessage, Object... parameters) { + String message = messageResources.getMessageWithDefault(key, defaultMessage, parameters); + return new BindException(message); + } + + protected String messageFor(String key, String defaultMessage, Object... parameters) { + return messageResources.getMessageWithDefault(key, defaultMessage, parameters); + } +}
Modified: trunk/waffle-core/src/main/java/org/codehaus/waffle/bind/converters/DateValueConverter.java (624 => 625)
--- trunk/waffle-core/src/main/java/org/codehaus/waffle/bind/converters/DateValueConverter.java 2008-04-18 17:03:29 UTC (rev 624) +++ trunk/waffle-core/src/main/java/org/codehaus/waffle/bind/converters/DateValueConverter.java 2008-04-19 13:11:22 UTC (rev 625) @@ -10,14 +10,12 @@ *****************************************************************************/ package org.codehaus.waffle.bind.converters; -import org.codehaus.waffle.bind.BindException; -import org.codehaus.waffle.bind.ValueConverter; -import org.codehaus.waffle.i18n.MessageResources; - import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; +import org.codehaus.waffle.i18n.MessageResources; + /** * <code>ValueConverter</code> that converts Date values. The date format is configurable via the message resources bundle. * A <code>null</code>, empty or invalid value will cause a BindException to be thrown. @@ -31,17 +29,16 @@ * @author Michael Ward * @author Mauro Talevi */ -public class DateValueConverter implements ValueConverter { +public class DateValueConverter extends AbstractValueConverter { 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 DEFAULT_DATE_FORMAT = "dd/MM/yyyy"; 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 final MessageResources messageResources; public DateValueConverter(MessageResources messageResources) { - this.messageResources = messageResources; + super(messageResources); } public boolean accept(Class<?> type) { @@ -50,19 +47,17 @@ @SuppressWarnings({"unchecked"}) public <T> T convertValue(String propertyName, String value, Class<T> toType) { - String fieldName = messageResources.getMessageWithDefault(propertyName, propertyName); - if (value == null || value.trim().length() == 0) { - String message = messageResources.getMessageWithDefault(BIND_ERROR_DATE_MISSING_KEY, DEFAULT_DATE_MISSING_MESSAGE, fieldName); - throw new BindException(message); + String fieldName = messageFor(propertyName, propertyName); + if ( missingValue(value) ) { + return (T) convertMissingValue(BIND_ERROR_DATE_MISSING_KEY, DEFAULT_DATE_MISSING_MESSAGE, fieldName); } - String dateFormat = messageResources.getMessageWithDefault(DATE_FORMAT_KEY, DEFAULT_DATE_FORMAT); + String dateFormat = messageFor(DATE_FORMAT_KEY, DEFAULT_DATE_FORMAT); try { return (T) new SimpleDateFormat(dateFormat).parse(value); } catch (ParseException e) { - String message = messageResources.getMessageWithDefault(BIND_ERROR_DATE_KEY, DEFAULT_DATE_MESSAGE, fieldName, value, dateFormat); - throw new BindException(message); + throw newBindException(BIND_ERROR_DATE_KEY, DEFAULT_DATE_MESSAGE, fieldName, value, dateFormat); } }
Modified: trunk/waffle-core/src/main/java/org/codehaus/waffle/bind/converters/ListValueConverter.java (624 => 625)
--- trunk/waffle-core/src/main/java/org/codehaus/waffle/bind/converters/ListValueConverter.java 2008-04-18 17:03:29 UTC (rev 624) +++ trunk/waffle-core/src/main/java/org/codehaus/waffle/bind/converters/ListValueConverter.java 2008-04-19 13:11:22 UTC (rev 625) @@ -19,8 +19,6 @@ import java.util.ArrayList; import java.util.List; -import org.codehaus.waffle.bind.BindException; -import org.codehaus.waffle.bind.ValueConverter; import org.codehaus.waffle.i18n.MessageResources; /** @@ -37,15 +35,14 @@ * * @author Mauro Talevi */ -public class ListValueConverter implements ValueConverter { +public class ListValueConverter extends AbstractValueConverter { static final String BIND_ERROR_LIST_KEY = "bind.error.list"; static final String DEFAULT_LIST_MESSAGE = "Invalid list value for field {0}"; private static final String COMMA = ","; - private final MessageResources messageResources; public ListValueConverter(MessageResources messageResources) { - this.messageResources = messageResources; + super(messageResources); } public boolean accept(Class<?> type) { @@ -54,12 +51,12 @@ @SuppressWarnings( { "unchecked" }) public <T> T convertValue(String propertyName, String value, Class<T> toType) { - if (value == null) { - String fieldName = messageResources.getMessageWithDefault(propertyName, propertyName); - String message = messageResources.getMessageWithDefault(BIND_ERROR_LIST_KEY, - DEFAULT_LIST_MESSAGE, fieldName); - throw new BindException(message); + + if ( missingValue(value)){ + String fieldName = messageFor(propertyName, propertyName); + return (T)convertMissingValue(BIND_ERROR_LIST_KEY, DEFAULT_LIST_MESSAGE, fieldName); } + List<String> values = asList(value.split(COMMA)); if ( values.size() == 0 ){ return (T) values;
Modified: trunk/waffle-core/src/test/java/org/codehaus/waffle/bind/converters/DateValueConverterTest.java (624 => 625)
--- trunk/waffle-core/src/test/java/org/codehaus/waffle/bind/converters/DateValueConverterTest.java 2008-04-18 17:03:29 UTC (rev 624) +++ trunk/waffle-core/src/test/java/org/codehaus/waffle/bind/converters/DateValueConverterTest.java 2008-04-19 13:11:22 UTC (rev 625) @@ -8,7 +8,9 @@ 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.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.text.SimpleDateFormat; import java.util.Date; @@ -61,6 +63,15 @@ assertEquals("04/03/2008", new SimpleDateFormat(DEFAULT_DATE_FORMAT).format(date)); } + + @Test + public void canHandleMissingValues() { + DefaultMessageResources resources = new DefaultMessageResources(configuration); + DateValueConverter converter = new DateValueConverter(resources); + 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() { @@ -68,11 +79,19 @@ DateValueConverter converter = new DateValueConverter(resources); 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()); } + DateValueConverter strictConverter = new DateValueConverter(resources){ + @Override + protected Object convertMissingValue(String key, String defaultMessage, Object... parameters) { + throw newBindException(key, defaultMessage, parameters); + } + }; try { - converter.convertValue("property-name", null, Date.class); + strictConverter.convertValue("property-name", null, Date.class); + fail("Expected BindException"); } catch ( BindException e) { assertEquals(format(resources.getMessage(BIND_ERROR_DATE_MISSING_KEY), "property-name"), e.getMessage()); } @@ -83,11 +102,19 @@ DateValueConverter converter = new DateValueConverter(new DefaultMessageResources()); 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()); } + DateValueConverter strictConverter = new DateValueConverter(new DefaultMessageResources()){ + @Override + protected Object convertMissingValue(String key, String defaultMessage, Object... parameters) { + throw newBindException(key, defaultMessage, parameters); + } + }; try { - converter.convertValue("property-name", null, Date.class); + strictConverter.convertValue("property-name", null, Date.class); + fail("Expected BindException"); } catch ( BindException e) { assertEquals(format(DEFAULT_DATE_MISSING_MESSAGE, "property-name"), e.getMessage()); }
Modified: trunk/waffle-core/src/test/java/org/codehaus/waffle/bind/converters/ListValueConverterTest.java (624 => 625)
--- trunk/waffle-core/src/test/java/org/codehaus/waffle/bind/converters/ListValueConverterTest.java 2008-04-18 17:03:29 UTC (rev 624) +++ trunk/waffle-core/src/test/java/org/codehaus/waffle/bind/converters/ListValueConverterTest.java 2008-04-19 13:11:22 UTC (rev 625) @@ -3,7 +3,9 @@ import static java.text.MessageFormat.format; import static java.util.Arrays.asList; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.util.List; import java.util.Locale; @@ -58,11 +60,26 @@ } @Test + public void canHandleMissingValues() { + ListValueConverter converter = new ListValueConverter(new DefaultMessageResources()); + assertNull(converter.convertValue("property-name", null, List.class)); + assertNull(converter.convertValue("property-name", "", List.class)); + assertNull(converter.convertValue("property-name", " ", List.class)); + } + + @Test public void canFailConversionWithCustomErrorMessages() { DefaultMessageResources resources = new DefaultMessageResources(configuration); - ListValueConverter converter = new ListValueConverter(resources); + ListValueConverter converter = new ListValueConverter(resources){ + + @Override + protected Object convertMissingValue(String key, String defaultMessage, Object... parameters) { + throw newBindException(key, defaultMessage, parameters); + } + }; try { converter.convertValue("property-name", null, List.class); + fail("Expected BindException"); } catch ( BindException e) { assertEquals(format(resources.getMessage(ListValueConverter.BIND_ERROR_LIST_KEY), "property-name"), e.getMessage()); } @@ -70,9 +87,15 @@ @Test public void canFailConversionWithDefaultErrorMessages() { - ListValueConverter converter = new ListValueConverter(new DefaultMessageResources()); + ListValueConverter converter = new ListValueConverter(new DefaultMessageResources()){ + @Override + protected Object convertMissingValue(String key, String defaultMessage, Object... parameters) { + throw newBindException(key, defaultMessage, parameters); + } + }; try { converter.convertValue("property-name", null, List.class); + fail("Expected BindException"); } catch ( BindException e) { assertEquals(format(ListValueConverter.DEFAULT_LIST_MESSAGE, "property-name"), e.getMessage()); }
Modified: trunk/waffle-core/src/test/java/org/codehaus/waffle/bind/ognl/DelegatingTypeConverterTest.java (624 => 625)
--- trunk/waffle-core/src/test/java/org/codehaus/waffle/bind/ognl/DelegatingTypeConverterTest.java 2008-04-18 17:03:29 UTC (rev 624) +++ trunk/waffle-core/src/test/java/org/codehaus/waffle/bind/ognl/DelegatingTypeConverterTest.java 2008-04-19 13:11:22 UTC (rev 625) @@ -2,11 +2,11 @@ import static java.util.Arrays.asList; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import java.util.List; -import org.codehaus.waffle.bind.BindException; import org.codehaus.waffle.bind.ValueConverter; import org.codehaus.waffle.bind.converters.ListValueConverter; import org.codehaus.waffle.context.ContextLevel; @@ -30,37 +30,23 @@ @Test public void canConvertValueForEnum() { DelegatingTypeConverter converter = new DelegatingTypeConverter(); - Object result = converter.convertValue("foobar", "APPLICATION", ContextLevel.class); - - assertEquals(ContextLevel.APPLICATION, result); + assertEquals(ContextLevel.APPLICATION, converter.convertValue("foobar", "APPLICATION", ContextLevel.class)); } @Test public void canConvertValueForIntegers() { DelegatingTypeConverter converter = new DelegatingTypeConverter(); - int value = (Integer) converter.convertValue("foobar", "15", Integer.class); - - assertEquals(15, value); + assertEquals(15, converter.convertValue("foobar", "15", Integer.class)); } @Test public void canDelegateToListValueConverter() { final ValueConverter valueConverter = new ListValueConverter(new DefaultMessageResources()); - final List<String> list = asList("one","two"); DelegatingTypeConverter converter = new DelegatingTypeConverter(new OgnlValueConverterFinder(valueConverter)); - - Object convertedValue = converter.convertValue("propertyName", "one,two", List.class); - assertEquals(convertedValue, list); + assertEquals(asList("one","two"), converter.convertValue("propertyName", "one,two", List.class)); + assertNull(converter.convertValue("propertyName", "", List.class)); } - - @Test(expected=BindException.class) - public void cannotDelegateToListValueConverterNullValue() { - final ValueConverter valueConverter = new ListValueConverter(new DefaultMessageResources()); - DelegatingTypeConverter converter = new DelegatingTypeConverter(new OgnlValueConverterFinder(valueConverter)); - converter.convertValue("propertyName", null, List.class); - } - @Test public void canDelegateToCustomValueConverter() { // Mock ValueConverter @@ -75,9 +61,7 @@ } }); DelegatingTypeConverter converter = new DelegatingTypeConverter(new OgnlValueConverterFinder(valueConverter)); - - Object convertedValue = converter.convertValue("propertyName", "foobar", CustomType.class); - assertSame(convertedValue, type); + assertSame(type, converter.convertValue("propertyName", "foobar", CustomType.class)); } private static interface CustomType {};
Modified: trunk/waffle-distribution/src/site/content/binding.html (624 => 625)
--- trunk/waffle-distribution/src/site/content/binding.html 2008-04-18 17:03:29 UTC (rev 624) +++ trunk/waffle-distribution/src/site/content/binding.html 2008-04-19 13:11:22 UTC (rev 625) @@ -156,6 +156,25 @@ </tbody> </table> + <p> + Note that by default these converters handle missing values (ie <code>null</code> or empty) by return a <code>null</code> converted value, + The behaviour can be nonetheless overridden by extending the converters to throw a new <code>BindException</code> in the + <code>convertMissingValue</code> method: + + <textarea class="java:nogutter:nocontrols" name="code"> +public class StringDateValueConverter extends DateValueConverter { + public StrictDateValueConverter(MessageResources messageResources) { + super(messageResources); + } + + @Override + protected Object convertMissingValue(String key, String defaultMessage, Object... parameters) { + throw newBindException(key, defaultMessage, parameters); + } +} + </textarea> + </p> + </body> </html>
To unsubscribe from this list please visit:
