- Revision
- 665
- Author
- mauro
- Date
- 2008-05-01 13:42:47 -0500 (Thu, 01 May 2008)
Log Message
Added number pattern to match values to parse with number format in ListValueConverter. This is required for values that have mixed numbers and chars (in particular, start with numbers) and may be erroneously parsed as numbers.
Modified Paths
- trunk/waffle-core/src/main/java/org/codehaus/waffle/bind/converters/AbstractValueConverter.java
- 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
Diff
Modified: trunk/waffle-core/src/main/java/org/codehaus/waffle/bind/converters/AbstractValueConverter.java (664 => 665)
--- trunk/waffle-core/src/main/java/org/codehaus/waffle/bind/converters/AbstractValueConverter.java 2008-05-01 10:20:05 UTC (rev 664) +++ trunk/waffle-core/src/main/java/org/codehaus/waffle/bind/converters/AbstractValueConverter.java 2008-05-01 18:42:47 UTC (rev 665) @@ -10,6 +10,8 @@ *****************************************************************************/ package org.codehaus.waffle.bind.converters; +import java.util.Properties; + import org.codehaus.waffle.bind.BindException; import org.codehaus.waffle.bind.ValueConverter; import org.codehaus.waffle.i18n.MessageResources; @@ -58,4 +60,15 @@ protected String messageFor(String key, String defaultMessage, Object... parameters) { return messageResources.getMessageWithDefault(key, defaultMessage, parameters); } + + protected boolean matches(String value, String regex) { + return value != null && value.matches(regex); + } + + protected String patternFor(Properties patterns, String key, String defaultPattern) { + if ( patterns.containsKey(key)) { + return patterns.getProperty(key); + } + return messageFor(key, defaultPattern); + } }
Modified: trunk/waffle-core/src/main/java/org/codehaus/waffle/bind/converters/DateValueConverter.java (664 => 665)
--- trunk/waffle-core/src/main/java/org/codehaus/waffle/bind/converters/DateValueConverter.java 2008-05-01 10:20:05 UTC (rev 664) +++ trunk/waffle-core/src/main/java/org/codehaus/waffle/bind/converters/DateValueConverter.java 2008-05-01 18:42:47 UTC (rev 665) @@ -114,35 +114,24 @@ String pattern = null; switch (dateType) { case DAY: - pattern = patternFor(DAY_FORMAT_KEY, DEFAULT_DAY_FORMAT); + pattern = patternFor(patterns, DAY_FORMAT_KEY, DEFAULT_DAY_FORMAT); break; case TIME: - pattern = patternFor(TIME_FORMAT_KEY, DEFAULT_TIME_FORMAT); + pattern = patternFor(patterns, TIME_FORMAT_KEY, DEFAULT_TIME_FORMAT); break; default: - pattern = patternFor(DATE_FORMAT_KEY, DEFAULT_DATE_FORMAT); + pattern = patternFor(patterns, DATE_FORMAT_KEY, DEFAULT_DATE_FORMAT); } return new SimpleDateFormat(pattern); } private DateType dateType(String propertyName) { - if (matches(propertyName, patternFor(DAY_NAME_KEY , DEFAULT_DAY_NAME))) { + if (matches(propertyName, patternFor(patterns , DAY_NAME_KEY, DEFAULT_DAY_NAME))) { return DateType.DAY; - } else if (matches(propertyName, patternFor(TIME_NAME_KEY , DEFAULT_TIME_NAME))) { + } else if (matches(propertyName, patternFor(patterns , TIME_NAME_KEY, DEFAULT_TIME_NAME))) { return DateType.TIME; } return DateType.DATE; } - - private boolean matches(String propertyName, String regex) { - return propertyName != null && propertyName.matches(regex); - } - - private String patternFor(String key, String defaultPattern) { - if ( patterns.containsKey(key)) { - return patterns.getProperty(key); - } - return messageFor(key, defaultPattern); - } }
Modified: trunk/waffle-core/src/main/java/org/codehaus/waffle/bind/converters/ListValueConverter.java (664 => 665)
--- trunk/waffle-core/src/main/java/org/codehaus/waffle/bind/converters/ListValueConverter.java 2008-05-01 10:20:05 UTC (rev 664) +++ trunk/waffle-core/src/main/java/org/codehaus/waffle/bind/converters/ListValueConverter.java 2008-05-01 18:42:47 UTC (rev 665) @@ -16,36 +16,53 @@ import java.text.ParseException; import java.util.ArrayList; import java.util.List; +import java.util.Properties; import org.codehaus.waffle.i18n.MessageResources; /** + * <p> * <code>ValueConverter</code> that converts a CSV value to a List. A <code>null</code> or empty value (once * trimmed) will be returned as <code>null</code> (behaviour which can be overridden via the * [EMAIL PROTECTED] convertMissingValue()} method). The message keys and default values used are: * <ul> * <li>"bind.error.list" ([EMAIL PROTECTED] #BIND_ERROR_LIST_KEY}): list is <code>null</code> or empty (message defaults to * [EMAIL PROTECTED] #DEFAULT_LIST_MESSAGE})</li> + * <li>"list.number.pattern" ([EMAIL PROTECTED] #NUMBER_PATTERN_KEY}): pattern to use to identify the list as parseable numbers + * (defaults to [EMAIL PROTECTED] #DEFAULT_NUMBER_PATTERN})</li> * </ul> - * The converter first attempts to parse the values as numbers (using the <code>NumberFormat</code> instance provided, - * which defaults to <code>NumberFormat.getInstance()</code>) and if not successful returns the string values. + * The patterns are also optionally injectable via <code>Properties</code> in the constructor and take precedence over + * the ones configured in the messages resources. + * </p> + * <p> + * NOTE: the converter will first check if the values match the configured number regex pattern and only if it does will + * it attempt to parse them (using the <code>NumberFormat</code> instance provided, which defaults to + * <code>NumberFormat.getInstance()</code>) and if not successful returns the string values. The reason for the + * presence of the preliminary number pattern matching is to disable the attempt of number parsing altogether for some + * string values that may start with number and may be erronously parsed as numbers. + * </p> * * @author Mauro Talevi */ 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}"; + public static final String BIND_ERROR_LIST_KEY = "bind.error.list"; + public static final String DEFAULT_LIST_MESSAGE = "Invalid list value for field {0}"; + public static final String NUMBER_PATTERN_KEY = "list.number.pattern"; + public static final String DEFAULT_NUMBER_PATTERN = "[0-9.-]*"; + private static final String COMMA = ","; private NumberFormat numberFormat; + private Properties patterns; public ListValueConverter(MessageResources messageResources) { - this(messageResources, NumberFormat.getInstance()); + this(messageResources, NumberFormat.getInstance(), new Properties()); } - public ListValueConverter(MessageResources messageResources, NumberFormat numberFormat) { + public ListValueConverter(MessageResources messageResources, NumberFormat numberFormat, Properties patterns) { super(messageResources); this.numberFormat = numberFormat; + this.patterns = patterns; } public boolean accept(Class<?> type) { @@ -61,7 +78,7 @@ } List<String> values = asList(value.split(COMMA)); - if (values.size() != 0) { + if (areNumbers(values)) { try { return (T) toNumbers(values); } catch (ParseException e) { @@ -71,12 +88,32 @@ return (T) values; } - private List<Number> toNumbers(List<String> values) throws ParseException { - List<Number> list = new ArrayList<Number>(); + public Properties getPatterns() { + return patterns; + } + + public void changePatterns(Properties patterns) { + this.patterns = patterns; + } + + protected boolean areNumbers(List<String> values) { + if (values.size() == 0) { + return false; // return empty list + } for (String value : values) { - list.add(numberFormat.parse(value)); + if (!matches(value, patternFor(patterns, NUMBER_PATTERN_KEY, DEFAULT_NUMBER_PATTERN))) { + return false; + } } - return list; + return true; } + + protected List<Number> toNumbers(List<String> values) throws ParseException { + List<Number> numbers = new ArrayList<Number>(); + for (String value : values) { + numbers.add(numberFormat.parse(value)); + } + return numbers; + } }
Modified: trunk/waffle-core/src/test/java/org/codehaus/waffle/bind/converters/DateValueConverterTest.java (664 => 665)
--- trunk/waffle-core/src/test/java/org/codehaus/waffle/bind/converters/DateValueConverterTest.java 2008-05-01 10:20:05 UTC (rev 664) +++ trunk/waffle-core/src/test/java/org/codehaus/waffle/bind/converters/DateValueConverterTest.java 2008-05-01 18:42:47 UTC (rev 665) @@ -48,7 +48,7 @@ @Test public void canAccept() { - DateValueConverter converter = new DateValueConverter(new DefaultMessageResources()); + AbstractValueConverter converter = new DateValueConverter(new DefaultMessageResources()); assertTrue(converter.accept(Date.class)); assertTrue(converter.accept(java.sql.Date.class)); assertFalse(converter.accept(Object.class)); @@ -56,7 +56,7 @@ @Test public void canConvertWithDefaultDateFormats() { - DateValueConverter converter = new DateValueConverter(new DefaultMessageResources()); + AbstractValueConverter converter = new DateValueConverter(new DefaultMessageResources()); assertDateFormattable("04/03/2008", DEFAULT_DATE_FORMAT, converter.convertValue("property-name", "04/03/2008", Date.class)); assertDateFormattable("04/03/2008", DEFAULT_DAY_FORMAT, converter.convertValue("propertyDay", "04/03/2008", @@ -68,7 +68,7 @@ @Test public void canConvertWithDateFormatsConfiguredViaMessageResource() { DefaultMessageResources resources = new DefaultMessageResources(configuration); - DateValueConverter converter = new DateValueConverter(resources); + AbstractValueConverter converter = new DateValueConverter(resources); 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("day-property", "04", @@ -101,7 +101,7 @@ @Test public void canHandleMissingValues() { DefaultMessageResources resources = new DefaultMessageResources(configuration); - DateValueConverter converter = new DateValueConverter(resources); + AbstractValueConverter 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)); @@ -110,7 +110,7 @@ @Test public void canFailConversionWithCustomErrorMessages() { DefaultMessageResources resources = new DefaultMessageResources(configuration); - DateValueConverter converter = new DateValueConverter(resources); + AbstractValueConverter converter = new DateValueConverter(resources); try { converter.convertValue("property-name", "bad-value", Date.class); fail("Expected BindException"); @@ -118,7 +118,7 @@ assertEquals(format(resources.getMessage(BIND_ERROR_DATE_KEY), "property-name", "bad-value", resources .getMessage(DATE_FORMAT_KEY)), e.getMessage()); } - DateValueConverter strictConverter = new DateValueConverter(resources) { + AbstractValueConverter strictConverter = new DateValueConverter(resources) { @Override protected Object convertMissingValue(String key, String defaultMessage, Object... parameters) { throw newBindException(key, defaultMessage, parameters); @@ -134,7 +134,7 @@ @Test public void canFailConversionWithDefaultErrorMessages() { - DateValueConverter converter = new DateValueConverter(new DefaultMessageResources()); + AbstractValueConverter converter = new DateValueConverter(new DefaultMessageResources()); try { converter.convertValue("property-name", "bad-value", Date.class); fail("Expected BindException"); @@ -142,7 +142,7 @@ assertEquals(format(DEFAULT_DATE_MESSAGE, "property-name", "bad-value", DEFAULT_DATE_FORMAT), e .getMessage()); } - DateValueConverter strictConverter = new DateValueConverter(new DefaultMessageResources()) { + AbstractValueConverter strictConverter = new DateValueConverter(new DefaultMessageResources()) { @Override protected Object convertMissingValue(String key, String defaultMessage, Object... parameters) { throw newBindException(key, defaultMessage, parameters);
Modified: trunk/waffle-core/src/test/java/org/codehaus/waffle/bind/converters/ListValueConverterTest.java (664 => 665)
--- trunk/waffle-core/src/test/java/org/codehaus/waffle/bind/converters/ListValueConverterTest.java 2008-05-01 10:20:05 UTC (rev 664) +++ trunk/waffle-core/src/test/java/org/codehaus/waffle/bind/converters/ListValueConverterTest.java 2008-05-01 18:42:47 UTC (rev 665) @@ -23,11 +23,12 @@ */ public class ListValueConverterTest { - private static final List<Integer> INTEGERS = asList(1,2,3); + private static final List<Integer> INTEGERS = asList(-1,-2,-3); private static final List<Long> LONGS = asList(1L,2L,3L); private static final List<Double> DOUBLES = asList(0.1d,0.2d,0.3d); private static final List<Float> FLOATS = asList(0.1f,0.2f,0.3f); private static final List<String> STRINGS = asList("one","two","three"); + private static final List<String> MIXED_STRINGS = asList("0#.A", "1#.B"); private MessageResourcesConfiguration configuration = new MessageResourcesConfiguration(){ @@ -50,11 +51,12 @@ public void canConvert() throws OgnlException { DefaultMessageResources resources = new DefaultMessageResources(configuration); ListValueConverter converter = new ListValueConverter(resources); - assertCanConvertValueToList(converter, INTEGERS, "1,2,3", Integer.class); + assertCanConvertValueToList(converter, INTEGERS, "-1,-2,-3", Integer.class); assertCanConvertValueToList(converter, LONGS, "1,2,3", Long.class); assertCanConvertValueToList(converter, DOUBLES, "0.1,0.2,0.3", Double.class); assertCanConvertValueToList(converter, FLOATS, "0.1,0.2,0.3", Float.class); assertCanConvertValueToList(converter, STRINGS, "one,two,three", String.class); + assertCanConvertValueToList(converter, MIXED_STRINGS, "0#.A,1#.B", String.class); } private void assertCanConvertValueToList(ListValueConverter converter, List<?> list, String value, Class<?> type) {
To unsubscribe from this list please visit:
