RESOLVED - issue BATCH-211: Specify column names in flat file on first line

http://opensource.atlassian.com/projects/spring/browse/BATCH-211

Patch applied with some modifications.
This commit is contained in:
dsyer
2007-11-22 07:57:30 +00:00
parent 1176fa912d
commit ad85f55175
9 changed files with 1121 additions and 958 deletions

View File

@@ -74,6 +74,13 @@ public final class FieldSet {
return (String[]) names.toArray();
}
/**
* @return fields wrapped by this '<code>FieldSet</code>' instance as String values.
*/
public String[] getValues() {
return tokens;
}
/**
* Read the {@link String} value at index '<code>index</code>'.
*

View File

@@ -77,7 +77,6 @@ public class DefaultFlatFileInputSource extends SimpleFlatFileInputSource implem
*/
public void restoreFrom(RestartData data) {
//TODO this does not look very nice...
if (data==null ||
data.getProperties() == null ||
data.getProperties().getProperty(READ_STATISTICS_NAME) == null ||

View File

@@ -1,217 +1,265 @@
/*
* Copyright 2006-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.io.file.support;
import java.io.IOException;
import org.springframework.batch.io.InputSource;
import org.springframework.batch.io.exception.FlatFileParsingException;
import org.springframework.batch.io.file.FieldSet;
import org.springframework.batch.io.file.FieldSetMapper;
import org.springframework.batch.io.file.support.separator.RecordSeparatorPolicy;
import org.springframework.batch.io.file.support.transform.DelimitedLineTokenizer;
import org.springframework.batch.io.file.support.transform.LineTokenizer;
import org.springframework.batch.item.ResourceLifecycle;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
/**
* This class represents a basic input source, that reads data from the file and
* returns it as structured tuples in the form of{@link FieldSet} instances.
* The location of the file is defined by the resource property. To separate the
* structure of the file, {@link LineTokenizer} is used to parse data obtained
* from the file. <br/>
*
* A {@link SimpleFlatFileInputSource} is not thread safe because it maintains
* state in the form of a {@link ResourceLineReader}. Be careful to configure a
* {@link SimpleFlatFileInputSource} using an appropriate factory or scope so
* that it is not shared between threads.<br/>
*
* @see FieldSetInputSource
*
* @author Dave Syer
*/
public class SimpleFlatFileInputSource implements InputSource, InitializingBean, DisposableBean {
// default encoding for input files - set to ISO-8859-1
public static final String DEFAULT_CHARSET = "ISO-8859-1";
private Resource resource;
/**
* Encapsulates the state of the input source. If it is null then we are
* uninitialized.
*/
private ResourceLineReader reader;
private RecordSeparatorPolicy recordSeparatorPolicy;
private String[] comments;
private LineTokenizer tokenizer = new DelimitedLineTokenizer();
private FieldSetMapper fieldSetMapper;
private String encoding = DEFAULT_CHARSET;
/**
* Setter for resource property. The location of an input stream that can be
* read.
* @param resource
* @throws IOException
*/
public void setResource(Resource resource) throws IOException {
this.resource = resource;
}
/**
* Public setter for the recordSeparatorPolicy. Used to determine where the
* line endings are and do things like continue over a line ending if inside
* a quoted string.
*
* @param recordSeparatorPolicy the recordSeparatorPolicy to set
*/
public void setRecordSeparatorPolicy(RecordSeparatorPolicy recordSeparatorPolicy) {
this.recordSeparatorPolicy = recordSeparatorPolicy;
}
/**
* Setter for comment prefixes. Can be used to ignore header lines as well
* by using e.g. the first couple of column names as a prefix.
*
* @param comments an array of comment line prefixes.
*/
public void setComments(String[] comments) {
this.comments = new String[comments.length];
System.arraycopy(comments, 0, this.comments, 0, comments.length);
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(resource);
Assert.state(resource.exists(), "Resource must exist: [" + resource + "]");
Assert.notNull(fieldSetMapper, "FieldSetMapper must not be null.");
}
/**
* Initialize the reader if necessary.
*/
public void open() {
if (reader == null) {
reader = new ResourceLineReader(resource, encoding);
if (recordSeparatorPolicy!=null) {
reader.setRecordSeparatorPolicy(recordSeparatorPolicy);
}
if (comments!=null) {
reader.setComments(comments);
}
reader.open();
}
}
/**
* Close and null out the reader.
*
* @see ResourceLifecycle
*/
public void close() {
try {
if (reader != null) {
reader.close();
}
}
finally {
reader = null;
}
}
/**
* Calls close to ensure that bean factories can close and always release
* resources.
*
* @see org.springframework.beans.factory.DisposableBean#destroy()
*/
public void destroy() throws Exception {
close();
}
// Reads first valid line.
protected String readLine() {
return (String) getReader().read();
}
/**
* A wrapper for {@link #readFieldSet()} to make this into a real
* {@link InputSource}.
*
* @see org.springframework.batch.io.InputSource#read()
*/
public Object read() {
String line = readLine();
if (line != null) {
try {
FieldSet tokenizedLine = tokenizer.tokenize(line);
return fieldSetMapper.mapLine(tokenizedLine);
}
catch (RuntimeException ex) {
// add current line count to message and re-throw
throw new FlatFileParsingException("Parsing error", ex, line,
getReader().getCurrentLineCount());
}
}
return null;
}
/**
* Setter for the encoding for this input source. Default value is
* {@value #DEFAULT_CHARSET}.
*
* @param encoding a properties object which possibly contains the encoding
* for this input file;
*/
public void setEncoding(String encoding) {
this.encoding = encoding;
}
/**
* Sets descriptor for this input template.
*/
public void setTokenizer(LineTokenizer lineTokenizer) {
this.tokenizer = lineTokenizer;
}
/**
* Set the FieldSetMapper to be used for each line.
*
* @param fieldSetMapper
*/
public void setFieldSetMapper(FieldSetMapper fieldSetMapper) {
this.fieldSetMapper = fieldSetMapper;
}
// Returns object representing state of the input template.
protected ResourceLineReader getReader() {
if (reader == null) {
open();
// reader is now not null, or else an exception is thrown
}
return reader;
}
}
/*
* Copyright 2006-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.io.file.support;
import java.io.IOException;
import org.springframework.batch.io.InputSource;
import org.springframework.batch.io.exception.FlatFileParsingException;
import org.springframework.batch.io.file.FieldSet;
import org.springframework.batch.io.file.FieldSetMapper;
import org.springframework.batch.io.file.support.separator.RecordSeparatorPolicy;
import org.springframework.batch.io.file.support.transform.AbstractLineTokenizer;
import org.springframework.batch.io.file.support.transform.DelimitedLineTokenizer;
import org.springframework.batch.io.file.support.transform.LineTokenizer;
import org.springframework.batch.item.ResourceLifecycle;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
/**
* This class represents a basic input source, that reads data from the file and
* returns it as structured tuples in the form of{@link FieldSet} instances.
* The location of the file is defined by the resource property. To separate the
* structure of the file, {@link LineTokenizer} is used to parse data obtained
* from the file. <br/>
*
* A {@link SimpleFlatFileInputSource} is not thread safe because it maintains
* state in the form of a {@link ResourceLineReader}. Be careful to configure a
* {@link SimpleFlatFileInputSource} using an appropriate factory or scope so
* that it is not shared between threads.<br/>
*
* @see FieldSetInputSource
*
* @author Dave Syer
*/
public class SimpleFlatFileInputSource implements InputSource,
InitializingBean, DisposableBean {
// default encoding for input files - set to ISO-8859-1
public static final String DEFAULT_CHARSET = "ISO-8859-1";
private Resource resource;
/**
* Encapsulates the state of the input source. If it is null then we are
* uninitialized.
*/
private ResourceLineReader reader;
private RecordSeparatorPolicy recordSeparatorPolicy;
private String[] comments;
private LineTokenizer tokenizer = new DelimitedLineTokenizer();
private FieldSetMapper fieldSetMapper;
private String encoding = DEFAULT_CHARSET;
private boolean firstLineIsHeader = false;
private int linesToSkip = 0;
/**
* Setter for resource property. The location of an input stream that can be
* read.
*
* @param resource
* @throws IOException
*/
public void setResource(Resource resource) throws IOException {
this.resource = resource;
}
/**
* Public setter for the recordSeparatorPolicy. Used to determine where the
* line endings are and do things like continue over a line ending if inside
* a quoted string.
*
* @param recordSeparatorPolicy
* the recordSeparatorPolicy to set
*/
public void setRecordSeparatorPolicy(
RecordSeparatorPolicy recordSeparatorPolicy) {
this.recordSeparatorPolicy = recordSeparatorPolicy;
}
/**
* Setter for comment prefixes. Can be used to ignore header lines as well
* by using e.g. the first couple of column names as a prefix.
*
* @param comments
* an array of comment line prefixes.
*/
public void setComments(String[] comments) {
this.comments = new String[comments.length];
System.arraycopy(comments, 0, this.comments, 0, comments.length);
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(resource);
Assert.state(resource.exists(), "Resource must exist: [" + resource
+ "]");
Assert.notNull(fieldSetMapper, "FieldSetMapper must not be null.");
}
/**
* Initialize the reader if necessary.
*/
public void open() {
if (reader == null) {
reader = new ResourceLineReader(resource, encoding);
if (recordSeparatorPolicy != null) {
reader.setRecordSeparatorPolicy(recordSeparatorPolicy);
}
if (comments != null) {
reader.setComments(comments);
}
reader.open();
}
for (int i = 0; i < linesToSkip; i++) {
readLine();
}
if (firstLineIsHeader) {
// skip the header
String firstLine = readLine();
// set names in tokenizer if they haven't been set already
if (tokenizer instanceof AbstractLineTokenizer
&& !((AbstractLineTokenizer) tokenizer).hasNames()) {
String[] names = tokenizer.tokenize(firstLine).getValues();
((AbstractLineTokenizer) tokenizer).setNames(names);
}
}
}
/**
* Close and null out the reader.
*
* @see ResourceLifecycle
*/
public void close() {
try {
if (reader != null) {
reader.close();
}
} finally {
reader = null;
}
}
/**
* Calls close to ensure that bean factories can close and always release
* resources.
*
* @see org.springframework.beans.factory.DisposableBean#destroy()
*/
public void destroy() throws Exception {
close();
}
// Reads first valid line.
protected String readLine() {
return (String) getReader().read();
}
/**
* A wrapper for {@link #readFieldSet()} to make this into a real
* {@link InputSource}.
*
* @see org.springframework.batch.io.InputSource#read()
*/
public Object read() {
String line = readLine();
if (line != null) {
try {
FieldSet tokenizedLine = tokenizer.tokenize(line);
return fieldSetMapper.mapLine(tokenizedLine);
} catch (RuntimeException ex) {
// add current line count to message and re-throw
throw new FlatFileParsingException("Parsing error", ex, line,
getReader().getCurrentLineCount());
}
}
return null;
}
/**
* Setter for the encoding for this input source. Default value is
* {@value #DEFAULT_CHARSET}.
*
* @param encoding
* a properties object which possibly contains the encoding for
* this input file;
*/
public void setEncoding(String encoding) {
this.encoding = encoding;
}
/**
* Sets descriptor for this input template.
*/
public void setTokenizer(LineTokenizer lineTokenizer) {
this.tokenizer = lineTokenizer;
}
/**
* Set the FieldSetMapper to be used for each line.
*
* @param fieldSetMapper
*/
public void setFieldSetMapper(FieldSetMapper fieldSetMapper) {
this.fieldSetMapper = fieldSetMapper;
}
// Returns object representing state of the input template.
protected ResourceLineReader getReader() {
if (reader == null) {
open();
// reader is now not null, or else an exception is thrown
}
return reader;
}
/**
* Indicates whether first line is a header. If the tokenizer is an
* {@link AbstractLineTokenizer} and the column names haven't been set
* already then the header will be used to setup column names. Default is
* <code>false</code>.
*/
public void setFirstLineIsHeader(boolean firstLineIsHeader) {
this.firstLineIsHeader = firstLineIsHeader;
}
/**
* Public setter for the number of lines to skip at the start of a file. Can
* be used if the file contains a header without useful (column name)
* information, and without a comment delimiter at the beginning of the
* lines.
*
* @param linesToSkip
* the number of lines to skip
*/
public void setLinesToSkip(int linesToSkip) {
this.linesToSkip = linesToSkip;
}
}

View File

@@ -1,67 +1,83 @@
/*
* Copyright 2006-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.io.file.support.transform;
import java.util.ArrayList;
import java.util.List;
import org.springframework.batch.io.file.FieldSet;
public abstract class AbstractLineTokenizer implements LineTokenizer {
protected String[] names = new String[0];
/**
* Setter for column names. Optional, but if set, then all lines must have
* as many or fewer tokens.
*
* @param names
*/
public void setNames(String[] names) {
this.names = names;
}
/**
* Yields the tokens resulting from the splitting of the supplied
* <code>line</code>.
*
* @param line the line to be tokenised (can be <code>null</code>)
*
* @return the resulting tokens
*/
public FieldSet tokenize(String line) {
if (line == null || line.length()==0) {
return new FieldSet(new String[0]);
}
List tokens = new ArrayList(doTokenize(line));
for (int i=tokens.size(); i<names.length; i++) {
tokens.add(null);
}
String[] values = (String[]) tokens.toArray(new String[tokens.size()]);
if (names.length==0) {
return new FieldSet(values);
}
return new FieldSet(values, names);
}
protected abstract List doTokenize(String line);
}
/*
* Copyright 2006-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.io.file.support.transform;
import java.util.ArrayList;
import java.util.List;
import org.springframework.batch.io.file.FieldSet;
/**
* @author Dave Syer
* @author Robert Kasanicky
*
*/
public abstract class AbstractLineTokenizer implements LineTokenizer {
protected String[] names = new String[0];
/**
* Setter for column names. Optional, but if set, then all lines must have
* as many or fewer tokens.
*
* @param names
*/
public void setNames(String[] names) {
this.names = names;
}
/**
* @return <code>true</code> if column names have been specified
* @see #setNames(String[])
*/
public boolean hasNames() {
if (names != null && names.length > 0) {
return true;
}
return false;
}
/**
* Yields the tokens resulting from the splitting of the supplied
* <code>line</code>.
*
* @param line the line to be tokenised (can be <code>null</code>)
*
* @return the resulting tokens
*/
public FieldSet tokenize(String line) {
if (line == null || line.length()==0) {
return new FieldSet(new String[0]);
}
List tokens = new ArrayList(doTokenize(line));
for (int i=tokens.size(); i<names.length; i++) {
tokens.add(null);
}
String[] values = (String[]) tokens.toArray(new String[tokens.size()]);
if (names.length==0) {
return new FieldSet(values);
}
return new FieldSet(values, names);
}
protected abstract List doTokenize(String line);
}

View File

@@ -30,7 +30,7 @@ public interface LineTokenizer {
* Yields the tokens resulting from the splitting of the supplied
* <code>line</code>.
*
* @param line the line to be tokenised (can be <code>null</code>)
* @param line the line to be tokenized (can be <code>null</code>)
*
* @return the resulting tokens
*/

View File

@@ -1,423 +1,431 @@
/*
* Copyright 2006-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.io.file;
import java.math.BigDecimal;
import java.text.ParseException;
import junit.framework.TestCase;
import org.springframework.batch.io.file.FieldSet;
public class FieldSetTests extends TestCase {
FieldSet fieldSet;
String[] tokens;
String[] names;
protected void setUp() throws Exception {
super.setUp();
tokens = new String[] { "TestString", "true", "C", "10", "-472", "354224", "543", "124.3", "424.3", "324",
null, "2007-10-12", "12-10-2007", "" };
names = new String[] { "String", "Boolean", "Char", "Byte", "Short", "Integer", "Long", "Float", "Double",
"BigDecimal", "Null", "Date", "DatePattern", "BlankInput" };
fieldSet = new FieldSet(tokens, names);
assertEquals(14, fieldSet.getFieldCount());
}
public void testNames() throws Exception {
assertEquals(fieldSet.getFieldCount(), fieldSet.getNames().length);
}
public void testNamesNotKnown() throws Exception {
fieldSet = new FieldSet(new String[]{"foo"});
try {
fieldSet.getNames();
fail("Expected IllegalStateException");
} catch (IllegalStateException e) {
// expected
}
}
public void testReadString() throws ParseException {
assertEquals(fieldSet.readString(0), "TestString");
assertEquals(fieldSet.readString("String"), "TestString");
}
public void testReadChar() throws Exception {
assertTrue(fieldSet.readChar(2) == 'C');
assertTrue(fieldSet.readChar("Char") == 'C');
}
public void testReadBooleanTrue() throws Exception {
assertTrue(fieldSet.readBoolean(1));
assertTrue(fieldSet.readBoolean("Boolean"));
}
public void testReadByte() throws Exception {
assertTrue(fieldSet.readByte(3) == 10);
assertTrue(fieldSet.readByte("Byte") == 10);
}
public void testReadShort() throws Exception {
assertTrue(fieldSet.readShort(4) == -472);
assertTrue(fieldSet.readShort("Short") == -472);
}
public void testReadFloat() throws Exception {
assertTrue(fieldSet.readFloat(7) == 124.3F);
assertTrue(fieldSet.readFloat("Float") == 124.3F);
}
public void testReadDouble() throws Exception {
assertTrue(fieldSet.readDouble(8) == 424.3);
assertTrue(fieldSet.readDouble("Double") == 424.3);
}
public void testReadBigDecimal() throws Exception {
BigDecimal bd = new BigDecimal(324);
assertEquals(fieldSet.readBigDecimal(9), bd);
assertEquals(fieldSet.readBigDecimal("BigDecimal"), bd);
}
public void testReadBigDecimalWithDefaultvalue() throws Exception {
BigDecimal bd = new BigDecimal(324);
assertEquals(bd, fieldSet.readBigDecimal(10, bd));
assertEquals(bd, fieldSet.readBigDecimal("Null", bd));
}
public void testReadNonExistentField() throws Exception {
try {
fieldSet.readString("something");
fail("field set returns value even value was never put in!");
}
catch (IllegalArgumentException e) {
assertTrue(e.getMessage().indexOf("something") > 0);
}
}
public void testReadIndexOutOfRange() throws Exception {
try {
fieldSet.readShort(-1);
fail("field set returns value even index is out of range!");
}
catch (IndexOutOfBoundsException e) {
assertTrue(true);
}
try {
fieldSet.readShort(99);
fail("field set returns value even index is out of range!");
}
catch (Exception e) {
assertTrue(true);
}
}
public void testReadBooleanWithTrueValue() {
assertTrue(fieldSet.readBoolean(1, "true"));
assertFalse(fieldSet.readBoolean(1, "incorrect trueValue"));
assertTrue(fieldSet.readBoolean("Boolean", "true"));
assertFalse(fieldSet.readBoolean("Boolean", "incorrect trueValue"));
}
public void testReadBooleanFalse() {
fieldSet = new FieldSet(new String[] { "false" });
assertFalse(fieldSet.readBoolean(0));
}
public void testReadCharException() {
try {
fieldSet.readChar(1);
fail("the value read was not a character, exception expected");
}
catch (IllegalArgumentException expected) {
assertTrue(true);
}
try {
fieldSet.readChar("Boolean");
fail("the value read was not a character, exception expected");
}
catch (IllegalArgumentException expected) {
assertTrue(true);
}
}
public void testReadInt() throws Exception {
assertEquals(354224, fieldSet.readInt(5));
assertEquals(354224, fieldSet.readInt("Integer"));
}
public void testReadBlankInt(){
//Trying to parse a blank field as an integer, but without a default
//value should throw a NumberFormatException
try{
fieldSet.readInt(13);
fail();
}
catch(NumberFormatException ex){
//expected
}
try{
fieldSet.readInt("BlankInput");
fail();
}
catch(NumberFormatException ex){
//expected
}
}
public void testReadLong() throws Exception {
assertEquals(543, fieldSet.readLong(6));
assertEquals(543, fieldSet.readLong("Long"));
}
public void testReadIntWithNullValue() {
assertEquals(5, fieldSet.readInt(10, 5));
assertEquals(5, fieldSet.readInt("Null", 5));
}
public void testReadIntWithDefaultAndNotNull() throws Exception {
assertEquals(354224, fieldSet.readInt(5, 5));
assertEquals(354224, fieldSet.readInt("Integer", 5));
}
public void testReadLongWithNullValue() {
int defaultValue = 5;
int indexOfNull = 10;
int indexNotNull = 6;
String nameNull = "Null";
String nameNotNull = "Long";
long longValueAtIndex = 543;
assertEquals(fieldSet.readLong(indexOfNull, defaultValue), defaultValue);
assertEquals(fieldSet.readLong(indexNotNull, defaultValue), longValueAtIndex);
assertEquals(fieldSet.readLong(nameNull, defaultValue), defaultValue);
assertEquals(fieldSet.readLong(nameNotNull, defaultValue), longValueAtIndex);
}
public void testReadBigDecimalInvalid() {
int index = 0;
try {
fieldSet.readBigDecimal(index);
fail("field value is not a number, exception expected");
}
catch (IllegalArgumentException e) {
assertTrue(e.getMessage().indexOf("TestString") > 0);
}
}
public void testReadBigDecimalByNameInvalid() throws Exception {
try {
fieldSet.readBigDecimal("String");
fail("field value is not a number, exception expected");
}
catch (IllegalArgumentException e) {
assertTrue(e.getMessage().indexOf("TestString") > 0);
assertTrue(e.getMessage().indexOf("name: [String]") > 0);
}
}
public void testReadDate() throws Exception {
assertNotNull(fieldSet.readDate(11));
assertNotNull(fieldSet.readDate("Date"));
}
public void testReadDateInvalid() throws Exception {
try {
fieldSet.readDate(0);
fail("field value is not a date, exception expected");
}
catch (IllegalArgumentException e) {
assertTrue(e.getMessage().indexOf("TestString") > 0);
}
}
public void testReadDateInvalidByName() throws Exception {
try {
fieldSet.readDate("String");
fail("field value is not a date, exception expected");
}
catch (IllegalArgumentException e) {
assertTrue(e.getMessage().indexOf("name: [String]") > 0);
}
}
public void testReadDateInvalidWithPattern() throws Exception {
try {
fieldSet.readDate(0, "dd-MM-yyyy");
fail("field value is not a date, exception expected");
}
catch (IllegalArgumentException e) {
assertTrue(e.getMessage().indexOf("dd-MM-yyyy") > 0);
}
}
public void testReadDateByNameInvalidWithPattern() throws Exception {
try {
fieldSet.readDate("String", "dd-MM-yyyy");
fail("field value is not a date, exception expected");
}
catch (IllegalArgumentException e) {
assertTrue(e.getMessage().indexOf("dd-MM-yyyy") > 0);
assertTrue(e.getMessage().indexOf("String") > 0);
}
}
public void testEquals() {
assertEquals(fieldSet, fieldSet);
assertEquals(fieldSet, new FieldSet(tokens));
String[] tokens1 = new String[] { "token1" };
String[] tokens2 = new String[] { "token1" };
FieldSet fs1 = new FieldSet(tokens1);
FieldSet fs2 = new FieldSet(tokens2);
assertEquals(fs1, fs2);
}
public void testNullField() {
assertEquals(null, fieldSet.readString(10));
}
public void testEqualsNull() {
assertFalse(fieldSet.equals(null));
}
public void testEqualsNullTokens() {
assertFalse(new FieldSet(null).equals(fieldSet));
}
public void testEqualsNotEqual() throws Exception {
String[] tokens1 = new String[] { "token1" };
String[] tokens2 = new String[] { "token1", "token2" };
FieldSet fs1 = new FieldSet(tokens1);
FieldSet fs2 = new FieldSet(tokens2);
assertFalse(fs1.equals(fs2));
}
public void testHashCode() throws Exception {
assertEquals(fieldSet.hashCode(), new FieldSet(tokens).hashCode());
}
public void testHashCodeWithNullTokens() throws Exception {
assertEquals(0, new FieldSet(null).hashCode());
}
public void testConstructor() throws Exception {
try {
new FieldSet(new String[] { "1", "2" }, new String[] { "a" });
fail("Expected IllegalArgumentException");
}
catch (IllegalArgumentException e) {
// expected
}
}
public void testToStringWithNames() throws Exception {
fieldSet = new FieldSet(new String[] { "foo", "bar" }, new String[] { "Foo", "Bar" });
assertTrue(fieldSet.toString().indexOf("Foo=foo") >= 0);
}
public void testToStringWithoutNames() throws Exception {
fieldSet = new FieldSet(new String[] { "foo", "bar" });
assertTrue(fieldSet.toString().indexOf("foo") >= 0);
}
public void testToStringNullTokens() throws Exception {
fieldSet = new FieldSet(null);
assertEquals("", fieldSet.toString());
}
public void testProperties() throws Exception {
assertEquals("foo", new FieldSet(new String[] { "foo", "bar" }, new String[] { "Foo", "Bar" }).getProperties()
.getProperty("Foo"));
}
public void testPropertiesWithNoNames() throws Exception {
try {
new FieldSet(new String[] { "foo", "bar" }).getProperties();
fail("Expected IllegalStateException");
}
catch (IllegalStateException e) {
// expected
}
}
public void testPropertiesWithWhiteSpace() throws Exception{
assertEquals("bar", new FieldSet(new String[] { "foo", "bar " }, new String[] { "Foo", "Bar"}).getProperties().getProperty("Bar"));
}
public void testPropertiesWithNullValues() throws Exception{
fieldSet = new FieldSet(new String[] { null, "bar" }, new String[] { "Foo", "Bar"});
assertEquals("bar", fieldSet.getProperties().getProperty("Bar"));
assertEquals(null, fieldSet.getProperties().getProperty("Foo"));
}
public void testAccessByNameWhenNamesMissing() throws Exception {
try {
new FieldSet(new String[] { "1", "2" }).readInt("a");
fail("Expected IllegalArgumentException");
}
catch (IllegalArgumentException e) {
// expected
}
}
}
/*
* Copyright 2006-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.io.file;
import java.math.BigDecimal;
import java.text.ParseException;
import junit.framework.TestCase;
import org.springframework.batch.io.file.FieldSet;
public class FieldSetTests extends TestCase {
FieldSet fieldSet;
String[] tokens;
String[] names;
protected void setUp() throws Exception {
super.setUp();
tokens = new String[] { "TestString", "true", "C", "10", "-472", "354224", "543", "124.3", "424.3", "324",
null, "2007-10-12", "12-10-2007", "" };
names = new String[] { "String", "Boolean", "Char", "Byte", "Short", "Integer", "Long", "Float", "Double",
"BigDecimal", "Null", "Date", "DatePattern", "BlankInput" };
fieldSet = new FieldSet(tokens, names);
assertEquals(14, fieldSet.getFieldCount());
}
public void testNames() throws Exception {
assertEquals(fieldSet.getFieldCount(), fieldSet.getNames().length);
}
public void testNamesNotKnown() throws Exception {
fieldSet = new FieldSet(new String[]{"foo"});
try {
fieldSet.getNames();
fail("Expected IllegalStateException");
} catch (IllegalStateException e) {
// expected
}
}
public void testReadString() throws ParseException {
assertEquals(fieldSet.readString(0), "TestString");
assertEquals(fieldSet.readString("String"), "TestString");
}
public void testReadChar() throws Exception {
assertTrue(fieldSet.readChar(2) == 'C');
assertTrue(fieldSet.readChar("Char") == 'C');
}
public void testReadBooleanTrue() throws Exception {
assertTrue(fieldSet.readBoolean(1));
assertTrue(fieldSet.readBoolean("Boolean"));
}
public void testReadByte() throws Exception {
assertTrue(fieldSet.readByte(3) == 10);
assertTrue(fieldSet.readByte("Byte") == 10);
}
public void testReadShort() throws Exception {
assertTrue(fieldSet.readShort(4) == -472);
assertTrue(fieldSet.readShort("Short") == -472);
}
public void testReadFloat() throws Exception {
assertTrue(fieldSet.readFloat(7) == 124.3F);
assertTrue(fieldSet.readFloat("Float") == 124.3F);
}
public void testReadDouble() throws Exception {
assertTrue(fieldSet.readDouble(8) == 424.3);
assertTrue(fieldSet.readDouble("Double") == 424.3);
}
public void testReadBigDecimal() throws Exception {
BigDecimal bd = new BigDecimal(324);
assertEquals(fieldSet.readBigDecimal(9), bd);
assertEquals(fieldSet.readBigDecimal("BigDecimal"), bd);
}
public void testReadBigDecimalWithDefaultvalue() throws Exception {
BigDecimal bd = new BigDecimal(324);
assertEquals(bd, fieldSet.readBigDecimal(10, bd));
assertEquals(bd, fieldSet.readBigDecimal("Null", bd));
}
public void testReadNonExistentField() throws Exception {
try {
fieldSet.readString("something");
fail("field set returns value even value was never put in!");
}
catch (IllegalArgumentException e) {
assertTrue(e.getMessage().indexOf("something") > 0);
}
}
public void testReadIndexOutOfRange() throws Exception {
try {
fieldSet.readShort(-1);
fail("field set returns value even index is out of range!");
}
catch (IndexOutOfBoundsException e) {
assertTrue(true);
}
try {
fieldSet.readShort(99);
fail("field set returns value even index is out of range!");
}
catch (Exception e) {
assertTrue(true);
}
}
public void testReadBooleanWithTrueValue() {
assertTrue(fieldSet.readBoolean(1, "true"));
assertFalse(fieldSet.readBoolean(1, "incorrect trueValue"));
assertTrue(fieldSet.readBoolean("Boolean", "true"));
assertFalse(fieldSet.readBoolean("Boolean", "incorrect trueValue"));
}
public void testReadBooleanFalse() {
fieldSet = new FieldSet(new String[] { "false" });
assertFalse(fieldSet.readBoolean(0));
}
public void testReadCharException() {
try {
fieldSet.readChar(1);
fail("the value read was not a character, exception expected");
}
catch (IllegalArgumentException expected) {
assertTrue(true);
}
try {
fieldSet.readChar("Boolean");
fail("the value read was not a character, exception expected");
}
catch (IllegalArgumentException expected) {
assertTrue(true);
}
}
public void testReadInt() throws Exception {
assertEquals(354224, fieldSet.readInt(5));
assertEquals(354224, fieldSet.readInt("Integer"));
}
public void testReadBlankInt(){
//Trying to parse a blank field as an integer, but without a default
//value should throw a NumberFormatException
try{
fieldSet.readInt(13);
fail();
}
catch(NumberFormatException ex){
//expected
}
try{
fieldSet.readInt("BlankInput");
fail();
}
catch(NumberFormatException ex){
//expected
}
}
public void testReadLong() throws Exception {
assertEquals(543, fieldSet.readLong(6));
assertEquals(543, fieldSet.readLong("Long"));
}
public void testReadIntWithNullValue() {
assertEquals(5, fieldSet.readInt(10, 5));
assertEquals(5, fieldSet.readInt("Null", 5));
}
public void testReadIntWithDefaultAndNotNull() throws Exception {
assertEquals(354224, fieldSet.readInt(5, 5));
assertEquals(354224, fieldSet.readInt("Integer", 5));
}
public void testReadLongWithNullValue() {
int defaultValue = 5;
int indexOfNull = 10;
int indexNotNull = 6;
String nameNull = "Null";
String nameNotNull = "Long";
long longValueAtIndex = 543;
assertEquals(fieldSet.readLong(indexOfNull, defaultValue), defaultValue);
assertEquals(fieldSet.readLong(indexNotNull, defaultValue), longValueAtIndex);
assertEquals(fieldSet.readLong(nameNull, defaultValue), defaultValue);
assertEquals(fieldSet.readLong(nameNotNull, defaultValue), longValueAtIndex);
}
public void testReadBigDecimalInvalid() {
int index = 0;
try {
fieldSet.readBigDecimal(index);
fail("field value is not a number, exception expected");
}
catch (IllegalArgumentException e) {
assertTrue(e.getMessage().indexOf("TestString") > 0);
}
}
public void testReadBigDecimalByNameInvalid() throws Exception {
try {
fieldSet.readBigDecimal("String");
fail("field value is not a number, exception expected");
}
catch (IllegalArgumentException e) {
assertTrue(e.getMessage().indexOf("TestString") > 0);
assertTrue(e.getMessage().indexOf("name: [String]") > 0);
}
}
public void testReadDate() throws Exception {
assertNotNull(fieldSet.readDate(11));
assertNotNull(fieldSet.readDate("Date"));
}
public void testReadDateInvalid() throws Exception {
try {
fieldSet.readDate(0);
fail("field value is not a date, exception expected");
}
catch (IllegalArgumentException e) {
assertTrue(e.getMessage().indexOf("TestString") > 0);
}
}
public void testReadDateInvalidByName() throws Exception {
try {
fieldSet.readDate("String");
fail("field value is not a date, exception expected");
}
catch (IllegalArgumentException e) {
assertTrue(e.getMessage().indexOf("name: [String]") > 0);
}
}
public void testReadDateInvalidWithPattern() throws Exception {
try {
fieldSet.readDate(0, "dd-MM-yyyy");
fail("field value is not a date, exception expected");
}
catch (IllegalArgumentException e) {
assertTrue(e.getMessage().indexOf("dd-MM-yyyy") > 0);
}
}
public void testReadDateByNameInvalidWithPattern() throws Exception {
try {
fieldSet.readDate("String", "dd-MM-yyyy");
fail("field value is not a date, exception expected");
}
catch (IllegalArgumentException e) {
assertTrue(e.getMessage().indexOf("dd-MM-yyyy") > 0);
assertTrue(e.getMessage().indexOf("String") > 0);
}
}
public void testEquals() {
assertEquals(fieldSet, fieldSet);
assertEquals(fieldSet, new FieldSet(tokens));
String[] tokens1 = new String[] { "token1" };
String[] tokens2 = new String[] { "token1" };
FieldSet fs1 = new FieldSet(tokens1);
FieldSet fs2 = new FieldSet(tokens2);
assertEquals(fs1, fs2);
}
public void testNullField() {
assertEquals(null, fieldSet.readString(10));
}
public void testEqualsNull() {
assertFalse(fieldSet.equals(null));
}
public void testEqualsNullTokens() {
assertFalse(new FieldSet(null).equals(fieldSet));
}
public void testEqualsNotEqual() throws Exception {
String[] tokens1 = new String[] { "token1" };
String[] tokens2 = new String[] { "token1", "token2" };
FieldSet fs1 = new FieldSet(tokens1);
FieldSet fs2 = new FieldSet(tokens2);
assertFalse(fs1.equals(fs2));
}
public void testHashCode() throws Exception {
assertEquals(fieldSet.hashCode(), new FieldSet(tokens).hashCode());
}
public void testHashCodeWithNullTokens() throws Exception {
assertEquals(0, new FieldSet(null).hashCode());
}
public void testConstructor() throws Exception {
try {
new FieldSet(new String[] { "1", "2" }, new String[] { "a" });
fail("Expected IllegalArgumentException");
}
catch (IllegalArgumentException e) {
// expected
}
}
public void testToStringWithNames() throws Exception {
fieldSet = new FieldSet(new String[] { "foo", "bar" }, new String[] { "Foo", "Bar" });
assertTrue(fieldSet.toString().indexOf("Foo=foo") >= 0);
}
public void testToStringWithoutNames() throws Exception {
fieldSet = new FieldSet(new String[] { "foo", "bar" });
assertTrue(fieldSet.toString().indexOf("foo") >= 0);
}
public void testToStringNullTokens() throws Exception {
fieldSet = new FieldSet(null);
assertEquals("", fieldSet.toString());
}
public void testProperties() throws Exception {
assertEquals("foo", new FieldSet(new String[] { "foo", "bar" }, new String[] { "Foo", "Bar" }).getProperties()
.getProperty("Foo"));
}
public void testPropertiesWithNoNames() throws Exception {
try {
new FieldSet(new String[] { "foo", "bar" }).getProperties();
fail("Expected IllegalStateException");
}
catch (IllegalStateException e) {
// expected
}
}
public void testPropertiesWithWhiteSpace() throws Exception{
assertEquals("bar", new FieldSet(new String[] { "foo", "bar " }, new String[] { "Foo", "Bar"}).getProperties().getProperty("Bar"));
}
public void testPropertiesWithNullValues() throws Exception{
fieldSet = new FieldSet(new String[] { null, "bar" }, new String[] { "Foo", "Bar"});
assertEquals("bar", fieldSet.getProperties().getProperty("Bar"));
assertEquals(null, fieldSet.getProperties().getProperty("Foo"));
}
public void testAccessByNameWhenNamesMissing() throws Exception {
try {
new FieldSet(new String[] { "1", "2" }).readInt("a");
fail("Expected IllegalArgumentException");
}
catch (IllegalArgumentException e) {
// expected
}
}
public void testGetValues() {
String[] values = fieldSet.getValues();
assertEquals(tokens.length, values.length);
for (int i = 0; i < tokens.length; i++) {
assertEquals(tokens[i], values[i]);
}
}
}

View File

@@ -1,249 +1,293 @@
/*
* Copyright 2006-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.io.file.support;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import junit.framework.TestCase;
import org.springframework.batch.io.exception.BatchEnvironmentException;
import org.springframework.batch.io.exception.FlatFileParsingException;
import org.springframework.batch.io.file.FieldSet;
import org.springframework.batch.io.file.FieldSetMapper;
import org.springframework.batch.io.file.support.separator.DefaultRecordSeparatorPolicy;
import org.springframework.batch.io.file.support.transform.LineTokenizer;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
/**
* Tests for {@link SimpleFlatFileInputSourceTests}
*
* @author Dave Syer
*
*/
public class SimpleFlatFileInputSourceTests extends TestCase {
// object under test
private SimpleFlatFileInputSource inputSource = new SimpleFlatFileInputSource();
// common value used for writing to a file
private String TEST_STRING = "FlatFileInputTemplate-TestData";
// simple stub instead of a realistic tokenizer
private LineTokenizer tokenizer = new LineTokenizer() {
public FieldSet tokenize(String line) {
return new FieldSet(new String[] { line });
}
};
private FieldSetMapper fieldSetMapper = new FieldSetMapper(){
public Object mapLine(FieldSet fs) {
return fs;
}
};
/**
* Create inputFile, inject mock/stub dependencies for tested object,
* initialize the tested object
*/
protected void setUp() throws Exception {
inputSource.setResource(getInputResource(TEST_STRING));
inputSource.setTokenizer(tokenizer);
inputSource.setFieldSetMapper(fieldSetMapper);
inputSource.afterPropertiesSet();
// context argument is necessary only for the FileLocator, which
// is mocked
inputSource.open();
}
/**
* Release resources.
*/
protected void tearDown() throws Exception {
inputSource.close();
}
private Resource getInputResource(String input) {
return new ByteArrayResource(input.getBytes());
}
/**
* Regular usage of <code>read</code> method
*/
public void testRead() throws IOException {
assertEquals("[FlatFileInputTemplate-TestData]", inputSource.read().toString());
}
/**
* Regular usage of <code>read</code> method
*/
public void testReadExhausted() throws IOException {
assertEquals("[FlatFileInputTemplate-TestData]", inputSource.read().toString());
assertEquals(null, inputSource.read());
}
/**
* Regular usage of <code>read</code> method
*/
public void testReadWithTokenizerError() throws IOException {
inputSource.setTokenizer(new LineTokenizer() {
public FieldSet tokenize(String line) {
throw new RuntimeException("foo");
}
});
try {
inputSource.read();
fail("Expected ParsingException");
} catch (FlatFileParsingException e) {
assertEquals(e.getInput(), TEST_STRING);
assertEquals(e.getLineNumber(), 1);
}
}
public void testReadWithMapperError() throws IOException {
inputSource.setFieldSetMapper(new FieldSetMapper(){
public Object mapLine(FieldSet fs) {
throw new RuntimeException("foo");
}
});
try {
inputSource.read();
fail("Expected ParsingException");
} catch (FlatFileParsingException e) {
assertEquals(e.getInput(), TEST_STRING);
assertEquals(e.getLineNumber(), 1);
}
}
public void testReadBeforeOpen() throws Exception {
inputSource = new SimpleFlatFileInputSource();
inputSource.setResource(getInputResource(TEST_STRING));
inputSource.setFieldSetMapper(fieldSetMapper);
assertEquals("[FlatFileInputTemplate-TestData]", inputSource.read().toString());
}
public void testCloseBeforeOpen() throws Exception {
inputSource = new SimpleFlatFileInputSource();
inputSource.setResource(getInputResource(TEST_STRING));
inputSource.setFieldSetMapper(fieldSetMapper);
inputSource.close();
// The open still happens automatically on a read...
assertEquals("[FlatFileInputTemplate-TestData]", inputSource.read().toString());
}
public void testCloseOnDestroy() throws Exception {
final List list = new ArrayList();
inputSource = new SimpleFlatFileInputSource() {
public void close() {
list.add("close");
}
};
inputSource.destroy();
assertEquals(1, list.size());
}
public void testInitializationWithNullResource() throws Exception {
inputSource = new SimpleFlatFileInputSource();
try {
inputSource.afterPropertiesSet();
fail("Expected IllegalArgumentException");
}
catch (IllegalArgumentException e) {
// expected
}
}
public void testOpenTwiceHasNoEffect() throws Exception {
inputSource.open();
testRead();
}
public void testSetValidEncoding() throws Exception {
inputSource = new SimpleFlatFileInputSource();
inputSource.setEncoding("UTF-8");
inputSource.setResource(getInputResource(TEST_STRING));
inputSource.setFieldSetMapper(fieldSetMapper);
testRead();
}
public void testSetNullEncoding() throws Exception {
inputSource = new SimpleFlatFileInputSource();
inputSource.setEncoding(null);
inputSource.setResource(getInputResource(TEST_STRING));
try {
inputSource.open();
fail("Expected IllegalArgumentException");
}
catch (IllegalArgumentException e) {
// expected
}
}
public void testSetInvalidEncoding() throws Exception {
inputSource = new SimpleFlatFileInputSource();
inputSource.setEncoding("foo");
inputSource.setResource(getInputResource(TEST_STRING));
try {
inputSource.open();
fail("Expected BatchEnvironmentException");
}
catch (BatchEnvironmentException e) {
// expected
assertEquals("foo", e.getCause().getMessage());
}
}
public void testEncoding() throws Exception {
inputSource.setEncoding("UTF-8");
testRead();
}
public void testRecordSeparator() throws Exception {
inputSource.setRecordSeparatorPolicy(new DefaultRecordSeparatorPolicy());
testRead();
}
public void testComments() throws Exception {
inputSource.setResource(getInputResource("% Comment\n"+TEST_STRING));
inputSource.setComments(new String[] {"%"});
testRead();
}
public void testInvalidFile() throws IOException {
DefaultFlatFileInputSource ffit = new DefaultFlatFileInputSource();
FileSystemResource resource = new FileSystemResource("FooDummy.txt");
assertTrue(!resource.exists());
ffit.setResource(resource);
try {
ffit.open();
fail("File is not existing but exception was not thrown.");
}
catch (BatchEnvironmentException e) {
assertEquals("FooDummy", e.getCause().getMessage().substring(0,8));
}
}
}
/*
* Copyright 2006-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.io.file.support;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import junit.framework.TestCase;
import org.springframework.batch.io.exception.BatchEnvironmentException;
import org.springframework.batch.io.exception.FlatFileParsingException;
import org.springframework.batch.io.file.FieldSet;
import org.springframework.batch.io.file.FieldSetMapper;
import org.springframework.batch.io.file.support.separator.DefaultRecordSeparatorPolicy;
import org.springframework.batch.io.file.support.transform.DelimitedLineTokenizer;
import org.springframework.batch.io.file.support.transform.LineTokenizer;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
/**
* Tests for {@link SimpleFlatFileInputSourceTests}
*
* @author Dave Syer
*
*/
public class SimpleFlatFileInputSourceTests extends TestCase {
// object under test
private SimpleFlatFileInputSource inputSource = new SimpleFlatFileInputSource();
// common value used for writing to a file
private String TEST_STRING = "FlatFileInputTemplate-TestData";
// simple stub instead of a realistic tokenizer
private LineTokenizer tokenizer = new LineTokenizer() {
public FieldSet tokenize(String line) {
return new FieldSet(new String[] { line });
}
};
private FieldSetMapper fieldSetMapper = new FieldSetMapper(){
public Object mapLine(FieldSet fs) {
return fs;
}
};
/**
* Create inputFile, inject mock/stub dependencies for tested object,
* initialize the tested object
*/
protected void setUp() throws Exception {
inputSource.setResource(getInputResource(TEST_STRING));
inputSource.setTokenizer(tokenizer);
inputSource.setFieldSetMapper(fieldSetMapper);
inputSource.afterPropertiesSet();
inputSource.open();
}
/**
* Release resources.
*/
protected void tearDown() throws Exception {
inputSource.close();
}
private Resource getInputResource(String input) {
return new ByteArrayResource(input.getBytes());
}
/**
* Regular usage of <code>read</code> method
*/
public void testRead() throws IOException {
assertEquals("[FlatFileInputTemplate-TestData]", inputSource.read().toString());
}
/**
* Regular usage of <code>read</code> method
*/
public void testReadExhausted() throws IOException {
assertEquals("[FlatFileInputTemplate-TestData]", inputSource.read().toString());
assertEquals(null, inputSource.read());
}
/**
* Regular usage of <code>read</code> method
*/
public void testReadWithTokenizerError() throws IOException {
inputSource.setTokenizer(new LineTokenizer() {
public FieldSet tokenize(String line) {
throw new RuntimeException("foo");
}
});
try {
inputSource.read();
fail("Expected ParsingException");
} catch (FlatFileParsingException e) {
assertEquals(e.getInput(), TEST_STRING);
assertEquals(e.getLineNumber(), 1);
}
}
public void testReadWithMapperError() throws IOException {
inputSource.setFieldSetMapper(new FieldSetMapper(){
public Object mapLine(FieldSet fs) {
throw new RuntimeException("foo");
}
});
try {
inputSource.read();
fail("Expected ParsingException");
} catch (FlatFileParsingException e) {
assertEquals(e.getInput(), TEST_STRING);
assertEquals(e.getLineNumber(), 1);
}
}
public void testReadBeforeOpen() throws Exception {
inputSource = new SimpleFlatFileInputSource();
inputSource.setResource(getInputResource(TEST_STRING));
inputSource.setFieldSetMapper(fieldSetMapper);
assertEquals("[FlatFileInputTemplate-TestData]", inputSource.read().toString());
}
public void testCloseBeforeOpen() throws Exception {
inputSource = new SimpleFlatFileInputSource();
inputSource.setResource(getInputResource(TEST_STRING));
inputSource.setFieldSetMapper(fieldSetMapper);
inputSource.close();
// The open still happens automatically on a read...
assertEquals("[FlatFileInputTemplate-TestData]", inputSource.read().toString());
}
public void testCloseOnDestroy() throws Exception {
final List list = new ArrayList();
inputSource = new SimpleFlatFileInputSource() {
public void close() {
list.add("close");
}
};
inputSource.destroy();
assertEquals(1, list.size());
}
public void testInitializationWithNullResource() throws Exception {
inputSource = new SimpleFlatFileInputSource();
try {
inputSource.afterPropertiesSet();
fail("Expected IllegalArgumentException");
}
catch (IllegalArgumentException e) {
// expected
}
}
public void testOpenTwiceHasNoEffect() throws Exception {
inputSource.open();
testRead();
}
public void testSetValidEncoding() throws Exception {
inputSource = new SimpleFlatFileInputSource();
inputSource.setEncoding("UTF-8");
inputSource.setResource(getInputResource(TEST_STRING));
inputSource.setFieldSetMapper(fieldSetMapper);
testRead();
}
public void testSetNullEncoding() throws Exception {
inputSource = new SimpleFlatFileInputSource();
inputSource.setEncoding(null);
inputSource.setResource(getInputResource(TEST_STRING));
try {
inputSource.open();
fail("Expected IllegalArgumentException");
}
catch (IllegalArgumentException e) {
// expected
}
}
public void testSetInvalidEncoding() throws Exception {
inputSource = new SimpleFlatFileInputSource();
inputSource.setEncoding("foo");
inputSource.setResource(getInputResource(TEST_STRING));
try {
inputSource.open();
fail("Expected BatchEnvironmentException");
}
catch (BatchEnvironmentException e) {
// expected
assertEquals("foo", e.getCause().getMessage());
}
}
public void testEncoding() throws Exception {
inputSource.setEncoding("UTF-8");
testRead();
}
public void testRecordSeparator() throws Exception {
inputSource.setRecordSeparatorPolicy(new DefaultRecordSeparatorPolicy());
testRead();
}
public void testComments() throws Exception {
inputSource.setResource(getInputResource("% Comment\n"+TEST_STRING));
inputSource.setComments(new String[] {"%"});
testRead();
}
public void testInvalidFile() throws IOException {
DefaultFlatFileInputSource ffit = new DefaultFlatFileInputSource();
FileSystemResource resource = new FileSystemResource("FooDummy.txt");
assertTrue(!resource.exists());
ffit.setResource(resource);
try {
ffit.open();
fail("File is not existing but exception was not thrown.");
}
catch (BatchEnvironmentException e) {
assertEquals("FooDummy", e.getCause().getMessage().substring(0,8));
}
}
/**
* Header line is skipped and used to setup fieldSet column names.
*/
public void testColumnNamesInHeader() throws Exception {
final String INPUT = "name1|name2\nvalue1|value2\nvalue3|value4";
inputSource = new SimpleFlatFileInputSource();
inputSource.setResource(getInputResource(INPUT));
inputSource.setTokenizer(new DelimitedLineTokenizer('|'));
inputSource.setFieldSetMapper(fieldSetMapper);
inputSource.setFirstLineIsHeader(true);
inputSource.afterPropertiesSet();
inputSource.open();
FieldSet fs = (FieldSet) inputSource.read();
assertEquals("value1", fs.readString("name1"));
assertEquals("value2", fs.readString("name2"));
fs = (FieldSet) inputSource.read();
assertEquals("value3", fs.readString("name1"));
assertEquals("value4", fs.readString("name2"));
}
/**
* Header line is skipped and used to setup fieldSet column names.
*/
public void testLinesToSkip() throws Exception {
final String INPUT = "foo bar spam\none two\nthree four";
inputSource = new SimpleFlatFileInputSource();
inputSource.setResource(getInputResource(INPUT));
inputSource.setTokenizer(new DelimitedLineTokenizer(' '));
inputSource.setFieldSetMapper(fieldSetMapper);
inputSource.setLinesToSkip(1);
inputSource.afterPropertiesSet();
inputSource.open();
FieldSet fs = (FieldSet) inputSource.read();
assertEquals("one", fs.readString(0));
assertEquals("two", fs.readString(1));
fs = (FieldSet) inputSource.read();
assertEquals("three", fs.readString(0));
assertEquals("four", fs.readString(1));
}
}

View File

@@ -0,0 +1,37 @@
package org.springframework.batch.io.file.support.transform;
import java.util.List;
import junit.framework.TestCase;
/**
* Tests for {@link AbstractLineTokenizer}.
*
* @author Robert Kasanicky
* @author Dave Syer
*/
public class CommonLineTokenizerTests extends TestCase {
/**
* Columns names are considered to be specified if they are not <code>null</code> or empty.
*/
public void testHasNames() {
AbstractLineTokenizer tokenizer = new AbstractLineTokenizer() {
protected List doTokenize(String line) {
return null;
}
};
assertFalse(tokenizer.hasNames());
tokenizer.setNames(null);
assertFalse(tokenizer.hasNames());
tokenizer.setNames(new String[0]);
assertFalse(tokenizer.hasNames());
tokenizer.setNames(new String[]{"name1", "name2"});
assertTrue(tokenizer.hasNames());
}
}

View File

@@ -42,6 +42,10 @@
<bean class="org.springframework.batch.repeat.policy.SimpleCompletionPolicy">
<property name="chunkSize" value="3"/>
</bean>
</property>
<property name="exceptionHandler">
<bean class="org.springframework.batch.repeat.exception.handler.SimpleLimitExceptionHandler"
p:limit="5" p:useParent="true" p:type="java.lang.Exception"/>
</property>
</bean>
</property>