From 4f550d42503025589bd39b8bfb3a514cf3adfd04 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 2 Aug 2011 17:17:09 +0100 Subject: [PATCH] BATCH-1777: add explicit check for custom numberformat when formatting doubles --- .../DefaultJobParametersConverter.java | 36 ++++++++++--- .../DefaultJobParametersConverterTests.java | 50 +++++++++++++++++++ 2 files changed, 79 insertions(+), 7 deletions(-) diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/converter/DefaultJobParametersConverter.java b/spring-batch-core/src/main/java/org/springframework/batch/core/converter/DefaultJobParametersConverter.java index 83f6261f2..83c4ea19e 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/converter/DefaultJobParametersConverter.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/converter/DefaultJobParametersConverter.java @@ -22,14 +22,15 @@ import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Iterator; +import java.util.Locale; import java.util.Map; -import java.util.Properties; import java.util.Map.Entry; +import java.util.Properties; import org.springframework.batch.core.JobParameter; +import org.springframework.batch.core.JobParameter.ParameterType; import org.springframework.batch.core.JobParameters; import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.JobParameter.ParameterType; import org.springframework.util.StringUtils; /** @@ -46,6 +47,12 @@ import org.springframework.util.StringUtils; * The literal values are converted to the correct type using the default Spring * strategies, augmented if necessary by the custom editors provided. * + *
+ * + * If you need to be able to parse and format local-specific dates and numbers, + * you can inject formatters ({@link #setDateFormat(DateFormat)} and + * {@link #setNumberFormat(NumberFormat)}). + * * @author Dave Syer * */ @@ -59,9 +66,13 @@ public class DefaultJobParametersConverter implements JobParametersConverter { private static final String DOUBLE_TYPE = "(double)"; + private static NumberFormat DEFAULT_NUMBER_FORMAT = NumberFormat.getInstance(Locale.US); + private DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd"); - private NumberFormat numberFormat = new DecimalFormat("#"); + private NumberFormat numberFormat = DEFAULT_NUMBER_FORMAT; + + private final NumberFormat longNumberFormat = new DecimalFormat("#"); /** * Check for suffix on keys and use those to decide how to convert the @@ -159,10 +170,10 @@ public class DefaultJobParametersConverter implements JobParametersConverter { result.setProperty(key + DATE_TYPE, dateFormat.format(value)); } else if (jobParameter.getType() == ParameterType.LONG) { - result.setProperty(key + LONG_TYPE, numberFormat.format(value)); + result.setProperty(key + LONG_TYPE, longNumberFormat.format(value)); } else if (jobParameter.getType() == ParameterType.DOUBLE) { - result.setProperty(key + DOUBLE_TYPE, value.toString()); + result.setProperty(key + DOUBLE_TYPE, decimalFormat((Double)value)); } else { result.setProperty(key, "" + value); @@ -171,6 +182,17 @@ public class DefaultJobParametersConverter implements JobParametersConverter { return result; } + /** + * @param value a decimal value + * @return a best guess at the desired format + */ + private String decimalFormat(double value) { + if (numberFormat != DEFAULT_NUMBER_FORMAT) { + return numberFormat.format(value); + } + return Double.toString(value); + } + /** * Public setter for injecting a date format. * @@ -181,8 +203,8 @@ public class DefaultJobParametersConverter implements JobParametersConverter { } /** - * Public setter for the {@link NumberFormat}. Used to parse longs, so must - * not contain decimal place (e.g. use "#" or "#,###"). + * Public setter for the {@link NumberFormat}. Used to parse longs and + * doubles, so must not contain decimal place (e.g. use "#" or "#,###"). * * @param numberFormat the {@link NumberFormat} to set */ diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/converter/DefaultJobParametersConverterTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/converter/DefaultJobParametersConverterTests.java index 3261df0f7..7fa4fe442 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/converter/DefaultJobParametersConverterTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/converter/DefaultJobParametersConverterTests.java @@ -21,8 +21,10 @@ import static org.junit.Assert.assertTrue; import java.text.DateFormat; import java.text.DecimalFormat; +import java.text.NumberFormat; import java.text.SimpleDateFormat; import java.util.Date; +import java.util.Locale; import java.util.Properties; import org.junit.Test; @@ -151,6 +153,20 @@ public class DefaultJobParametersConverterTests { assertEquals(1.38, props.getDouble("value"), Double.MIN_VALUE); } + @Test + public void testGetParametersWithDoubleAndLongAndNumberFormat() throws Exception { + + String[] args = new String[] { "value(double)=1,23456", "long(long)=123.456" }; + NumberFormat format = NumberFormat.getInstance(Locale.GERMAN); + factory.setNumberFormat(format); + + JobParameters props = factory.getJobParameters(StringUtils.splitArrayElementsIntoProperties(args, "=")); + assertNotNull(props); + assertEquals(1.23456, props.getDouble("value"), Double.MIN_VALUE); + assertEquals(123456, props.getLong("long")); + + } + @Test public void testGetParametersWithRoundDouble() throws Exception { @@ -186,6 +202,40 @@ public class DefaultJobParametersConverterTests { assertEquals("1.23", props.getProperty("double.key(double)")); } + @Test + public void testRoundTrip() throws Exception { + + String[] args = new String[] { "schedule.date(date)=2008/01/23", "job.key=myKey", "vendor.id(long)=33243243", + "double.key(double)=1.23" }; + + JobParameters parameters = factory.getJobParameters(StringUtils.splitArrayElementsIntoProperties(args, "=")); + + Properties props = factory.getProperties(parameters); + assertNotNull(props); + assertEquals("myKey", props.getProperty("job.key")); + assertEquals("33243243", props.getProperty("vendor.id(long)")); + assertEquals("2008/01/23", props.getProperty("schedule.date(date)")); + assertEquals("1.23", props.getProperty("double.key(double)")); + } + + @Test + public void testRoundTripWithNumberFormat() throws Exception { + + String[] args = new String[] { "schedule.date(date)=2008/01/23", "job.key=myKey", "vendor.id(long)=33243243", + "double.key(double)=1,23" }; + NumberFormat format = NumberFormat.getInstance(Locale.GERMAN); + factory.setNumberFormat(format); + + JobParameters parameters = factory.getJobParameters(StringUtils.splitArrayElementsIntoProperties(args, "=")); + + Properties props = factory.getProperties(parameters); + assertNotNull(props); + assertEquals("myKey", props.getProperty("job.key")); + assertEquals("33243243", props.getProperty("vendor.id(long)")); + assertEquals("2008/01/23", props.getProperty("schedule.date(date)")); + assertEquals("1,23", props.getProperty("double.key(double)")); + } + @Test public void testEmptyArgs() {