BATCH-1777: add explicit check for custom numberformat when formatting doubles

This commit is contained in:
Dave Syer
2011-08-02 17:17:09 +01:00
parent c321a1dc07
commit 4f550d4250
2 changed files with 79 additions and 7 deletions

View File

@@ -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.
*
* <br/>
*
* 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
*/

View File

@@ -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() {