RESOLVED - issue BATCH-935: Use NumberFormat when parsing real numbers
This commit is contained in:
@@ -19,11 +19,10 @@ package org.springframework.batch.item.file.transform;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Abstract class handling common concerns of various {@link LineTokenizer} implementations
|
||||
* such as dealing with names and actual construction of {@link FieldSet}
|
||||
* Abstract class handling common concerns of various {@link LineTokenizer}
|
||||
* implementations such as dealing with names and actual construction of
|
||||
* {@link FieldSet}
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Robert Kasanicky
|
||||
@@ -33,6 +32,18 @@ public abstract class AbstractLineTokenizer implements LineTokenizer {
|
||||
|
||||
protected String[] names = new String[0];
|
||||
|
||||
private FieldSetFactory fieldSetFactory = new DefaultFieldSetFactory();
|
||||
|
||||
/**
|
||||
* Factory for {@link FieldSet} instances. Can be injected by clients to
|
||||
* customize the default number and date formats.
|
||||
*
|
||||
* @param fieldSetFactory the {@link FieldSetFactory} to set
|
||||
*/
|
||||
public void setFieldSetFactory(FieldSetFactory fieldSetFactory) {
|
||||
this.fieldSetFactory = fieldSetFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for column names. Optional, but if set, then all lines must have
|
||||
* as many or fewer tokens.
|
||||
@@ -42,7 +53,7 @@ public abstract class AbstractLineTokenizer implements LineTokenizer {
|
||||
public void setNames(String[] names) {
|
||||
this.names = names;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if column names have been specified
|
||||
* @see #setNames(String[])
|
||||
@@ -63,24 +74,24 @@ public abstract class AbstractLineTokenizer implements LineTokenizer {
|
||||
* @return the resulting tokens
|
||||
*/
|
||||
public FieldSet tokenize(String line) {
|
||||
|
||||
if(line == null){
|
||||
|
||||
if (line == null) {
|
||||
line = "";
|
||||
}
|
||||
|
||||
List<String> tokens = new ArrayList<String>(doTokenize(line));
|
||||
|
||||
String[] values = (String[]) tokens.toArray(new String[tokens.size()]);
|
||||
|
||||
if (names.length==0) {
|
||||
return new DefaultFieldSet(values);
|
||||
|
||||
if (names.length == 0) {
|
||||
return fieldSetFactory.create(values);
|
||||
}
|
||||
else if(values.length != names.length){
|
||||
else if (values.length != names.length) {
|
||||
throw new IncorrectTokenCountException(names.length, values.length);
|
||||
}
|
||||
return new DefaultFieldSet(values, names);
|
||||
return fieldSetFactory.create(values, names);
|
||||
}
|
||||
|
||||
|
||||
protected abstract List<String> doTokenize(String line);
|
||||
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
package org.springframework.batch.item.file.transform;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.text.DateFormat;
|
||||
import java.text.NumberFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
@@ -35,10 +37,21 @@ import org.springframework.util.StringUtils;
|
||||
* @author Rob Harrop
|
||||
* @author Dave Syer
|
||||
*/
|
||||
/**
|
||||
* @author dsyer
|
||||
*
|
||||
*/
|
||||
public class DefaultFieldSet implements FieldSet {
|
||||
|
||||
private final static String DEFAULT_DATE_PATTERN = "yyyy-MM-dd";
|
||||
|
||||
private DateFormat dateFormat = new SimpleDateFormat(DEFAULT_DATE_PATTERN);
|
||||
{
|
||||
dateFormat.setLenient(false);
|
||||
}
|
||||
|
||||
private NumberFormat numberFormat = NumberFormat.getInstance();
|
||||
|
||||
/**
|
||||
* The fields wrapped by this '<code>FieldSet</code>' instance.
|
||||
*/
|
||||
@@ -46,6 +59,24 @@ public class DefaultFieldSet implements FieldSet {
|
||||
|
||||
private List<String> names;
|
||||
|
||||
/**
|
||||
* The {@link NumberFormat} to use for parsing numbers. If unset the default
|
||||
* locale will be used.
|
||||
* @param numberFormat the {@link NumberFormat} to use for number parsing
|
||||
*/
|
||||
public void setNumberFormat(NumberFormat numberFormat) {
|
||||
this.numberFormat = numberFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link DateFormat} to use for parsing numbers. If unset the default
|
||||
* pattern is ISO standard <code>yyyy/MM/dd</code>.
|
||||
* @param dateFormat the {@link DateFormat} to use for date parsing
|
||||
*/
|
||||
public void setDateFormat(DateFormat dateFormat) {
|
||||
this.dateFormat = dateFormat;
|
||||
}
|
||||
|
||||
public DefaultFieldSet(String[] tokens) {
|
||||
this.tokens = tokens == null ? null : (String[]) tokens.clone();
|
||||
}
|
||||
@@ -60,9 +91,10 @@ public class DefaultFieldSet implements FieldSet {
|
||||
this.tokens = (String[]) tokens.clone();
|
||||
this.names = Arrays.asList(names);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#getNames()
|
||||
*/
|
||||
public String[] getNames() {
|
||||
@@ -71,16 +103,19 @@ public class DefaultFieldSet implements FieldSet {
|
||||
}
|
||||
return names.toArray(new String[names.size()]);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.batch.item.file.mapping.FieldSet#hasNames()
|
||||
*/
|
||||
public boolean hasNames() {
|
||||
return names!=null;
|
||||
return names != null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#getValues()
|
||||
*/
|
||||
public String[] getValues() {
|
||||
@@ -89,7 +124,9 @@ public class DefaultFieldSet implements FieldSet {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#readString(int)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.batch.item.file.mapping.IFieldSet#readString(int)
|
||||
*/
|
||||
public String readString(int index) {
|
||||
return readAndTrim(index);
|
||||
@@ -97,23 +134,31 @@ public class DefaultFieldSet implements FieldSet {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#readString(java.lang.String)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.batch.item.file.mapping.IFieldSet#readString(java
|
||||
* .lang.String)
|
||||
*/
|
||||
public String readString(String name) {
|
||||
return readString(indexOf(name));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#readRawString(int)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.batch.item.file.mapping.IFieldSet#readRawString(int)
|
||||
*/
|
||||
public String readRawString(int index) {
|
||||
return tokens[index];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#readRawString(java.lang.String)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.batch.item.file.mapping.IFieldSet#readRawString(java
|
||||
* .lang.String)
|
||||
*/
|
||||
public String readRawString(String name) {
|
||||
return readRawString(indexOf(name));
|
||||
@@ -121,7 +166,9 @@ public class DefaultFieldSet implements FieldSet {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#readBoolean(int)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.batch.item.file.mapping.IFieldSet#readBoolean(int)
|
||||
*/
|
||||
public boolean readBoolean(int index) {
|
||||
return readBoolean(index, "true");
|
||||
@@ -129,7 +176,10 @@ public class DefaultFieldSet implements FieldSet {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#readBoolean(java.lang.String)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.batch.item.file.mapping.IFieldSet#readBoolean(java
|
||||
* .lang.String)
|
||||
*/
|
||||
public boolean readBoolean(String name) {
|
||||
return readBoolean(indexOf(name));
|
||||
@@ -137,7 +187,9 @@ public class DefaultFieldSet implements FieldSet {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#readBoolean(int,
|
||||
*
|
||||
* @see
|
||||
* org.springframework.batch.item.file.mapping.IFieldSet#readBoolean(int,
|
||||
* java.lang.String)
|
||||
*/
|
||||
public boolean readBoolean(int index, String trueValue) {
|
||||
@@ -150,8 +202,10 @@ public class DefaultFieldSet implements FieldSet {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#readBoolean(java.lang.String,
|
||||
* java.lang.String)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.batch.item.file.mapping.IFieldSet#readBoolean(java
|
||||
* .lang.String, java.lang.String)
|
||||
*/
|
||||
public boolean readBoolean(String name, String trueValue) {
|
||||
return readBoolean(indexOf(name), trueValue);
|
||||
@@ -159,6 +213,7 @@ public class DefaultFieldSet implements FieldSet {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#readChar(int)
|
||||
*/
|
||||
public char readChar(int index) {
|
||||
@@ -171,7 +226,10 @@ public class DefaultFieldSet implements FieldSet {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#readChar(java.lang.String)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.batch.item.file.mapping.IFieldSet#readChar(java.lang
|
||||
* .String)
|
||||
*/
|
||||
public char readChar(String name) {
|
||||
return readChar(indexOf(name));
|
||||
@@ -179,6 +237,7 @@ public class DefaultFieldSet implements FieldSet {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#readByte(int)
|
||||
*/
|
||||
public byte readByte(int index) {
|
||||
@@ -187,7 +246,10 @@ public class DefaultFieldSet implements FieldSet {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#readByte(java.lang.String)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.batch.item.file.mapping.IFieldSet#readByte(java.lang
|
||||
* .String)
|
||||
*/
|
||||
public byte readByte(String name) {
|
||||
return readByte(indexOf(name));
|
||||
@@ -195,6 +257,7 @@ public class DefaultFieldSet implements FieldSet {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#readShort(int)
|
||||
*/
|
||||
public short readShort(int index) {
|
||||
@@ -203,7 +266,10 @@ public class DefaultFieldSet implements FieldSet {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#readShort(java.lang.String)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.batch.item.file.mapping.IFieldSet#readShort(java.
|
||||
* lang.String)
|
||||
*/
|
||||
public short readShort(String name) {
|
||||
return readShort(indexOf(name));
|
||||
@@ -211,15 +277,19 @@ public class DefaultFieldSet implements FieldSet {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#readInt(int)
|
||||
*/
|
||||
public int readInt(int index) {
|
||||
return Integer.parseInt(readAndTrim(index));
|
||||
return parseNumber(readAndTrim(index)).intValue();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#readInt(java.lang.String)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.batch.item.file.mapping.IFieldSet#readInt(java.lang
|
||||
* .String)
|
||||
*/
|
||||
public int readInt(String name) {
|
||||
return readInt(indexOf(name));
|
||||
@@ -227,6 +297,7 @@ public class DefaultFieldSet implements FieldSet {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#readInt(int,
|
||||
* int)
|
||||
*/
|
||||
@@ -238,8 +309,10 @@ public class DefaultFieldSet implements FieldSet {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#readInt(java.lang.String,
|
||||
* int)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.batch.item.file.mapping.IFieldSet#readInt(java.lang
|
||||
* .String, int)
|
||||
*/
|
||||
public int readInt(String name, int defaultValue) {
|
||||
return readInt(indexOf(name), defaultValue);
|
||||
@@ -247,15 +320,19 @@ public class DefaultFieldSet implements FieldSet {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#readLong(int)
|
||||
*/
|
||||
public long readLong(int index) {
|
||||
return Long.parseLong(readAndTrim(index));
|
||||
return (Long) parseNumber(readAndTrim(index));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#readLong(java.lang.String)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.batch.item.file.mapping.IFieldSet#readLong(java.lang
|
||||
* .String)
|
||||
*/
|
||||
public long readLong(String name) {
|
||||
return readLong(indexOf(name));
|
||||
@@ -263,6 +340,7 @@ public class DefaultFieldSet implements FieldSet {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#readLong(int,
|
||||
* long)
|
||||
*/
|
||||
@@ -274,8 +352,10 @@ public class DefaultFieldSet implements FieldSet {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#readLong(java.lang.String,
|
||||
* long)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.batch.item.file.mapping.IFieldSet#readLong(java.lang
|
||||
* .String, long)
|
||||
*/
|
||||
public long readLong(String name, long defaultValue) {
|
||||
return readLong(indexOf(name), defaultValue);
|
||||
@@ -283,15 +363,19 @@ public class DefaultFieldSet implements FieldSet {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#readFloat(int)
|
||||
*/
|
||||
public float readFloat(int index) {
|
||||
return Float.parseFloat(readAndTrim(index));
|
||||
return parseNumber(readAndTrim(index)).floatValue();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#readFloat(java.lang.String)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.batch.item.file.mapping.IFieldSet#readFloat(java.
|
||||
* lang.String)
|
||||
*/
|
||||
public float readFloat(String name) {
|
||||
return readFloat(indexOf(name));
|
||||
@@ -299,15 +383,20 @@ public class DefaultFieldSet implements FieldSet {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#readDouble(int)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.batch.item.file.mapping.IFieldSet#readDouble(int)
|
||||
*/
|
||||
public double readDouble(int index) {
|
||||
return Double.parseDouble(readAndTrim(index));
|
||||
return (Double) parseNumber(readAndTrim(index));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#readDouble(java.lang.String)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.batch.item.file.mapping.IFieldSet#readDouble(java
|
||||
* .lang.String)
|
||||
*/
|
||||
public double readDouble(String name) {
|
||||
return readDouble(indexOf(name));
|
||||
@@ -315,7 +404,9 @@ public class DefaultFieldSet implements FieldSet {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#readBigDecimal(int)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.batch.item.file.mapping.IFieldSet#readBigDecimal(int)
|
||||
*/
|
||||
public BigDecimal readBigDecimal(int index) {
|
||||
return readBigDecimal(index, null);
|
||||
@@ -323,7 +414,10 @@ public class DefaultFieldSet implements FieldSet {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#readBigDecimal(java.lang.String)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.batch.item.file.mapping.IFieldSet#readBigDecimal(
|
||||
* java.lang.String)
|
||||
*/
|
||||
public BigDecimal readBigDecimal(String name) {
|
||||
return readBigDecimal(name, null);
|
||||
@@ -331,7 +425,9 @@ public class DefaultFieldSet implements FieldSet {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#readBigDecimal(int,
|
||||
*
|
||||
* @see
|
||||
* org.springframework.batch.item.file.mapping.IFieldSet#readBigDecimal(int,
|
||||
* java.math.BigDecimal)
|
||||
*/
|
||||
public BigDecimal readBigDecimal(int index, BigDecimal defaultValue) {
|
||||
@@ -347,8 +443,10 @@ public class DefaultFieldSet implements FieldSet {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#readBigDecimal(java.lang.String,
|
||||
* java.math.BigDecimal)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.batch.item.file.mapping.IFieldSet#readBigDecimal(
|
||||
* java.lang.String, java.math.BigDecimal)
|
||||
*/
|
||||
public BigDecimal readBigDecimal(String name, BigDecimal defaultValue) {
|
||||
try {
|
||||
@@ -361,43 +459,47 @@ public class DefaultFieldSet implements FieldSet {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#readDate(int)
|
||||
*/
|
||||
public Date readDate(int index) {
|
||||
return readDate(index, DEFAULT_DATE_PATTERN);
|
||||
return parseDate(readAndTrim(index), dateFormat);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#readDate(java.lang.String)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.batch.item.file.mapping.IFieldSet#readDate(java.lang
|
||||
* .String)
|
||||
*/
|
||||
public Date readDate(String name) {
|
||||
return readDate(name, DEFAULT_DATE_PATTERN);
|
||||
try {
|
||||
return readDate(indexOf(name));
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException(e.getMessage() + ", name: [" + name + "]");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#readDate(int,
|
||||
* java.lang.String)
|
||||
*/
|
||||
public Date readDate(int index, String pattern) {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
|
||||
sdf.setLenient(false);
|
||||
Date date;
|
||||
String value = readAndTrim(index);
|
||||
try {
|
||||
date = sdf.parse(value);
|
||||
}
|
||||
catch (ParseException e) {
|
||||
throw new IllegalArgumentException(e.getMessage() + ", pattern: [" + pattern + "]");
|
||||
}
|
||||
return date;
|
||||
return parseDate(readAndTrim(index), sdf);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#readDate(java.lang.String,
|
||||
* java.lang.String)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.batch.item.file.mapping.IFieldSet#readDate(java.lang
|
||||
* .String, java.lang.String)
|
||||
*/
|
||||
public Date readDate(String name, String pattern) {
|
||||
try {
|
||||
@@ -410,7 +512,9 @@ public class DefaultFieldSet implements FieldSet {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#getFieldCount()
|
||||
*
|
||||
* @see
|
||||
* org.springframework.batch.item.file.mapping.IFieldSet#getFieldCount()
|
||||
*/
|
||||
public int getFieldCount() {
|
||||
return tokens.length;
|
||||
@@ -433,7 +537,8 @@ public class DefaultFieldSet implements FieldSet {
|
||||
}
|
||||
|
||||
/**
|
||||
* Read and trim the {@link String} value from column with given '<code>name</code>.
|
||||
* Read and trim the {@link String} value from column with given '
|
||||
* <code>name</code>.
|
||||
*
|
||||
* @throws IllegalArgumentException if a column with given name is not
|
||||
* defined.
|
||||
@@ -492,7 +597,9 @@ public class DefaultFieldSet implements FieldSet {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.item.file.mapping.IFieldSet#getProperties()
|
||||
*
|
||||
* @see
|
||||
* org.springframework.batch.item.file.mapping.IFieldSet#getProperties()
|
||||
*/
|
||||
public Properties getProperties() {
|
||||
if (names == null) {
|
||||
@@ -508,4 +615,29 @@ public class DefaultFieldSet implements FieldSet {
|
||||
return props;
|
||||
}
|
||||
|
||||
private Number parseNumber(String candidate) {
|
||||
try {
|
||||
return numberFormat.parse(candidate);
|
||||
}
|
||||
catch (ParseException e) {
|
||||
throw new NumberFormatException("Unparseable number: " + candidate);
|
||||
}
|
||||
}
|
||||
|
||||
private Date parseDate(String readAndTrim, DateFormat dateFormat) {
|
||||
try {
|
||||
return dateFormat.parse(readAndTrim);
|
||||
}
|
||||
catch (ParseException e) {
|
||||
String pattern;
|
||||
if (dateFormat instanceof SimpleDateFormat) {
|
||||
pattern = ((SimpleDateFormat) dateFormat).toPattern();
|
||||
} else {
|
||||
pattern = dateFormat.toString();
|
||||
}
|
||||
throw new IllegalArgumentException(e.getMessage() + ", format: [" + pattern + "]");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
package org.springframework.batch.item.file.transform;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.NumberFormat;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link FieldSetFactory} with no special knowledge
|
||||
* of the {@link FieldSet} required. Returns a {@link DefaultFieldSet} from both
|
||||
* factory methods.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class DefaultFieldSetFactory implements FieldSetFactory {
|
||||
|
||||
private DateFormat dateFormat;
|
||||
|
||||
private NumberFormat numberFormat;
|
||||
|
||||
/**
|
||||
* The {@link NumberFormat} to use for parsing numbers. If unset the default
|
||||
* locale will be used.
|
||||
* @param numberFormat the {@link NumberFormat} to use for number parsing
|
||||
*/
|
||||
public void setNumberFormat(NumberFormat numberFormat) {
|
||||
this.numberFormat = numberFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link DateFormat} to use for parsing numbers. If unset the default
|
||||
* pattern is ISO standard <code>yyyy/MM/dd</code>.
|
||||
* @param dateFormat the {@link DateFormat} to use for date parsing
|
||||
*/
|
||||
public void setDateFormat(DateFormat dateFormat) {
|
||||
this.dateFormat = dateFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public FieldSet create(String[] values, String[] names) {
|
||||
DefaultFieldSet fieldSet = new DefaultFieldSet(values, names);
|
||||
return enhance(fieldSet);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public FieldSet create(String[] values) {
|
||||
DefaultFieldSet fieldSet = new DefaultFieldSet(values);
|
||||
return enhance(fieldSet);
|
||||
}
|
||||
|
||||
private FieldSet enhance(DefaultFieldSet fieldSet) {
|
||||
if (dateFormat!=null) {
|
||||
fieldSet.setDateFormat(dateFormat);
|
||||
}
|
||||
if (numberFormat!=null) {
|
||||
fieldSet.setDateFormat(dateFormat);
|
||||
}
|
||||
return fieldSet;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package org.springframework.batch.item.file.transform;
|
||||
|
||||
/**
|
||||
* Factory interface for creating {@link FieldSet} instances.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public interface FieldSetFactory {
|
||||
|
||||
FieldSet create(String[] names, String[] values);
|
||||
|
||||
FieldSet create(String[] values);
|
||||
|
||||
}
|
||||
@@ -39,7 +39,7 @@ public class PrefixMatchingCompositeLineMapperTests {
|
||||
private PrefixMatchingCompositeLineMapper<Name> mapper = new PrefixMatchingCompositeLineMapper<Name>();
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void test_NoMappers() throws Exception {
|
||||
public void testNoMappers() throws Exception {
|
||||
mapper.setTokenizers(Collections.singletonMap("", (LineTokenizer) new DelimitedLineTokenizer()));
|
||||
Map<String, FieldSetMapper<Name>> fieldSetMappers = Collections.emptyMap();
|
||||
mapper.setFieldSetMappers(fieldSetMappers);
|
||||
@@ -47,7 +47,7 @@ public class PrefixMatchingCompositeLineMapperTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_KeyFound() throws Exception {
|
||||
public void testKeyFound() throws Exception {
|
||||
Map<String, LineTokenizer> tokenizers = new HashMap<String, LineTokenizer>();
|
||||
tokenizers.put("foo", new LineTokenizer() {
|
||||
public FieldSet tokenize(String line) {
|
||||
@@ -79,7 +79,7 @@ public class PrefixMatchingCompositeLineMapperTests {
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void test_MapperKeyNotFound() throws Exception {
|
||||
public void testMapperKeyNotFound() throws Exception {
|
||||
Map<String, LineTokenizer> tokenizers = new HashMap<String, LineTokenizer>();
|
||||
tokenizers.put("foo", new LineTokenizer() {
|
||||
public FieldSet tokenize(String line) {
|
||||
|
||||
@@ -16,23 +16,31 @@
|
||||
|
||||
package org.springframework.batch.item.file.transform;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.text.NumberFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Locale;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.batch.item.file.transform.DefaultFieldSet;
|
||||
import org.springframework.batch.item.file.transform.FieldSet;
|
||||
public class FieldSetTests {
|
||||
|
||||
public class FieldSetTests extends TestCase {
|
||||
FieldSet fieldSet;
|
||||
DefaultFieldSet fieldSet;
|
||||
|
||||
String[] tokens;
|
||||
|
||||
String[] names;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
|
||||
tokens = new String[] { "TestString", "true", "C", "10", "-472", "354224", "543", "124.3", "424.3", "324",
|
||||
null, "2007-10-12", "12-10-2007", "" };
|
||||
@@ -44,11 +52,13 @@ public class FieldSetTests extends TestCase {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNames() throws Exception {
|
||||
assertTrue(fieldSet.hasNames());
|
||||
assertEquals(fieldSet.getFieldCount(), fieldSet.getNames().length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNamesNotKnown() throws Exception {
|
||||
fieldSet = new DefaultFieldSet(new String[] { "foo" });
|
||||
assertFalse(fieldSet.hasNames());
|
||||
@@ -61,6 +71,7 @@ public class FieldSetTests extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadString() throws ParseException {
|
||||
|
||||
assertEquals(fieldSet.readString(0), "TestString");
|
||||
@@ -68,6 +79,7 @@ public class FieldSetTests extends TestCase {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadChar() throws Exception {
|
||||
|
||||
assertTrue(fieldSet.readChar(2) == 'C');
|
||||
@@ -75,6 +87,7 @@ public class FieldSetTests extends TestCase {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadBooleanTrue() throws Exception {
|
||||
|
||||
assertTrue(fieldSet.readBoolean(1));
|
||||
@@ -82,6 +95,7 @@ public class FieldSetTests extends TestCase {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadByte() throws Exception {
|
||||
|
||||
assertTrue(fieldSet.readByte(3) == 10);
|
||||
@@ -89,6 +103,7 @@ public class FieldSetTests extends TestCase {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadShort() throws Exception {
|
||||
|
||||
assertTrue(fieldSet.readShort(4) == -472);
|
||||
@@ -96,6 +111,7 @@ public class FieldSetTests extends TestCase {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadFloat() throws Exception {
|
||||
|
||||
assertTrue(fieldSet.readFloat(7) == 124.3F);
|
||||
@@ -103,6 +119,7 @@ public class FieldSetTests extends TestCase {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadDouble() throws Exception {
|
||||
|
||||
assertTrue(fieldSet.readDouble(8) == 424.3);
|
||||
@@ -110,6 +127,7 @@ public class FieldSetTests extends TestCase {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadBigDecimal() throws Exception {
|
||||
|
||||
BigDecimal bd = new BigDecimal(324);
|
||||
@@ -118,6 +136,7 @@ public class FieldSetTests extends TestCase {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadBigDecimalWithDefaultvalue() throws Exception {
|
||||
|
||||
BigDecimal bd = new BigDecimal(324);
|
||||
@@ -126,6 +145,7 @@ public class FieldSetTests extends TestCase {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadNonExistentField() throws Exception {
|
||||
|
||||
try {
|
||||
@@ -138,6 +158,7 @@ public class FieldSetTests extends TestCase {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadIndexOutOfRange() throws Exception {
|
||||
|
||||
try {
|
||||
@@ -157,6 +178,7 @@ public class FieldSetTests extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadBooleanWithTrueValue() {
|
||||
assertTrue(fieldSet.readBoolean(1, "true"));
|
||||
assertFalse(fieldSet.readBoolean(1, "incorrect trueValue"));
|
||||
@@ -165,11 +187,13 @@ public class FieldSetTests extends TestCase {
|
||||
assertFalse(fieldSet.readBoolean("Boolean", "incorrect trueValue"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadBooleanFalse() {
|
||||
fieldSet = new DefaultFieldSet(new String[] { "false" });
|
||||
assertFalse(fieldSet.readBoolean(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadCharException() {
|
||||
try {
|
||||
fieldSet.readChar(1);
|
||||
@@ -188,11 +212,26 @@ public class FieldSetTests extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadInt() throws Exception {
|
||||
assertEquals(354224, fieldSet.readInt(5));
|
||||
assertEquals(354224, fieldSet.readInt("Integer"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadIntWithSeparator() throws Exception {
|
||||
fieldSet = new DefaultFieldSet(new String[] {"354,224"});
|
||||
assertEquals(354224, fieldSet.readInt(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadIntWithSeparatorAndFormat() throws Exception {
|
||||
fieldSet = new DefaultFieldSet(new String[] {"354.224"});
|
||||
fieldSet.setNumberFormat(NumberFormat.getInstance(Locale.GERMAN));
|
||||
assertEquals(354224, fieldSet.readInt(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadBlankInt() {
|
||||
|
||||
// Trying to parse a blank field as an integer, but without a default
|
||||
@@ -215,26 +254,31 @@ public class FieldSetTests extends TestCase {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadLong() throws Exception {
|
||||
assertEquals(543, fieldSet.readLong(6));
|
||||
assertEquals(543, fieldSet.readLong("Long"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadLongWithPadding() throws Exception {
|
||||
fieldSet = new DefaultFieldSet(new String[] { "000009" });
|
||||
assertEquals(9, fieldSet.readLong(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadIntWithNullValue() {
|
||||
assertEquals(5, fieldSet.readInt(10, 5));
|
||||
assertEquals(5, fieldSet.readInt("Null", 5));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadIntWithDefaultAndNotNull() throws Exception {
|
||||
assertEquals(354224, fieldSet.readInt(5, 5));
|
||||
assertEquals(354224, fieldSet.readInt("Integer", 5));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadLongWithNullValue() {
|
||||
int defaultValue = 5;
|
||||
int indexOfNull = 10;
|
||||
@@ -250,6 +294,7 @@ public class FieldSetTests extends TestCase {
|
||||
assertEquals(fieldSet.readLong(nameNotNull, defaultValue), longValueAtIndex);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadBigDecimalInvalid() {
|
||||
int index = 0;
|
||||
|
||||
@@ -263,6 +308,7 @@ public class FieldSetTests extends TestCase {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadBigDecimalByNameInvalid() throws Exception {
|
||||
try {
|
||||
fieldSet.readBigDecimal("String");
|
||||
@@ -274,11 +320,21 @@ public class FieldSetTests extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadDate() throws Exception {
|
||||
assertNotNull(fieldSet.readDate(11));
|
||||
assertNotNull(fieldSet.readDate("Date"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadDateWithFormat() throws Exception {
|
||||
fieldSet = new DefaultFieldSet(new String[] {"13/01/1999"});
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
|
||||
fieldSet.setDateFormat(dateFormat);
|
||||
assertEquals(dateFormat.parse("13/01/1999"), fieldSet.readDate(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadDateInvalid() throws Exception {
|
||||
|
||||
try {
|
||||
@@ -291,6 +347,7 @@ public class FieldSetTests extends TestCase {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadDateInvalidByName() throws Exception {
|
||||
|
||||
try {
|
||||
@@ -303,6 +360,7 @@ public class FieldSetTests extends TestCase {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadDateInvalidWithPattern() throws Exception {
|
||||
|
||||
try {
|
||||
@@ -314,6 +372,7 @@ public class FieldSetTests extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStrictReadDateWithPattern() throws Exception {
|
||||
|
||||
fieldSet = new DefaultFieldSet(new String[] {"50-2-13"});
|
||||
@@ -327,6 +386,7 @@ public class FieldSetTests extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStrictReadDateWithPatternAndStrangeDate() throws Exception {
|
||||
|
||||
fieldSet = new DefaultFieldSet(new String[] {"5550212"});
|
||||
@@ -340,6 +400,7 @@ public class FieldSetTests extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadDateByNameInvalidWithPattern() throws Exception {
|
||||
|
||||
try {
|
||||
@@ -352,6 +413,7 @@ public class FieldSetTests extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEquals() {
|
||||
|
||||
assertEquals(fieldSet, fieldSet);
|
||||
@@ -364,18 +426,22 @@ public class FieldSetTests extends TestCase {
|
||||
assertEquals(fs1, fs2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullField() {
|
||||
assertEquals(null, fieldSet.readString(10));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualsNull() {
|
||||
assertFalse(fieldSet.equals(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualsNullTokens() {
|
||||
assertFalse(new DefaultFieldSet(null).equals(fieldSet));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualsNotEqual() throws Exception {
|
||||
|
||||
String[] tokens1 = new String[] { "token1" };
|
||||
@@ -386,14 +452,17 @@ public class FieldSetTests extends TestCase {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHashCode() throws Exception {
|
||||
assertEquals(fieldSet.hashCode(), new DefaultFieldSet(tokens).hashCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHashCodeWithNullTokens() throws Exception {
|
||||
assertEquals(0, new DefaultFieldSet(null).hashCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstructor() throws Exception {
|
||||
try {
|
||||
new DefaultFieldSet(new String[] { "1", "2" }, new String[] { "a" });
|
||||
@@ -404,26 +473,31 @@ public class FieldSetTests extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToStringWithNames() throws Exception {
|
||||
fieldSet = new DefaultFieldSet(new String[] { "foo", "bar" }, new String[] { "Foo", "Bar" });
|
||||
assertTrue(fieldSet.toString().indexOf("Foo=foo") >= 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToStringWithoutNames() throws Exception {
|
||||
fieldSet = new DefaultFieldSet(new String[] { "foo", "bar" });
|
||||
assertTrue(fieldSet.toString().indexOf("foo") >= 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToStringNullTokens() throws Exception {
|
||||
fieldSet = new DefaultFieldSet(null);
|
||||
assertEquals("", fieldSet.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProperties() throws Exception {
|
||||
assertEquals("foo", new DefaultFieldSet(new String[] { "foo", "bar" }, new String[] { "Foo", "Bar" })
|
||||
.getProperties().getProperty("Foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPropertiesWithNoNames() throws Exception {
|
||||
try {
|
||||
new DefaultFieldSet(new String[] { "foo", "bar" }).getProperties();
|
||||
@@ -434,12 +508,14 @@ public class FieldSetTests extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPropertiesWithWhiteSpace() throws Exception {
|
||||
|
||||
assertEquals("bar", new DefaultFieldSet(new String[] { "foo", "bar " }, new String[] { "Foo", "Bar" })
|
||||
.getProperties().getProperty("Bar"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPropertiesWithNullValues() throws Exception {
|
||||
|
||||
fieldSet = new DefaultFieldSet(new String[] { null, "bar" }, new String[] { "Foo", "Bar" });
|
||||
@@ -447,6 +523,7 @@ public class FieldSetTests extends TestCase {
|
||||
assertEquals(null, fieldSet.getProperties().getProperty("Foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccessByNameWhenNamesMissing() throws Exception {
|
||||
try {
|
||||
new DefaultFieldSet(new String[] { "1", "2" }).readInt("a");
|
||||
@@ -457,6 +534,7 @@ public class FieldSetTests extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetValues() {
|
||||
String[] values = fieldSet.getValues();
|
||||
assertEquals(tokens.length, values.length);
|
||||
@@ -465,6 +543,7 @@ public class FieldSetTests extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPaddedLong() {
|
||||
FieldSet fs = new DefaultFieldSet(new String[] { "00000009" });
|
||||
|
||||
@@ -472,6 +551,7 @@ public class FieldSetTests extends TestCase {
|
||||
assertEquals(value, 9);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadRawString() {
|
||||
String name = "fieldName";
|
||||
String value = " string with trailing whitespace ";
|
||||
|
||||
Reference in New Issue
Block a user