BATCH-140: Modified file input sources to no longer implemented FieldSet and now accept an injected mapper.

This commit is contained in:
lucasward
2007-10-08 04:28:31 +00:00
parent 407d032bff
commit 4b24ef866c
16 changed files with 488 additions and 715 deletions

View File

@@ -0,0 +1,62 @@
/*
* 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.exception;
/**
* Exception thrown when errors are encountered
* parsing flat files. The original input, typically
* a line, can be passed in, so that latter catches
* can write out the original input to a log, or
* an error table.
*
* @author Lucas Ward
*
*/
public class FlatFileParsingException extends ParsingException {
private String input;
private int lineNumber;
public FlatFileParsingException(String message, String input) {
super(message);
this.input = input;
}
public FlatFileParsingException(String message, String input, int lineNumber) {
super(message);
this.input = input;
this.lineNumber = lineNumber;
}
public FlatFileParsingException(String message, Throwable cause, String input, int lineNumber) {
super(message, cause);
this.input = input;
this.lineNumber = lineNumber;
}
public FlatFileParsingException(Throwable cause, String input) {
super(cause);
this.input = input;
}
public String getInput() {
return input;
}
public int getLineNumber() {
return lineNumber;
}
}

View File

@@ -1,35 +1,38 @@
/*
* 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 org.springframework.batch.io.InputSource;
/**
* Common interface for reading input e.g. from a file or other stream-based
* resource. Providers are expected to use this interface to access an input
* source.<br/>
*
* If we had generics this would be a parameterised input source, but
* for type safety with the current constraints we are going to use this
* interface.
*
*/
public interface FieldSetInputSource extends InputSource {
public FieldSet readFieldSet();
}
/*
* 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.exception;
/**
* Exception indicating that an error has been encountered
* parsing io, typically from a file.
*
* @author Lucas Ward
*
*/
public class ParsingException extends RuntimeException {
public ParsingException(String message) {
super(message);
}
public ParsingException(String message, Throwable cause) {
super(message, cause);
}
public ParsingException(Throwable cause) {
super(cause);
}
}

View File

@@ -23,7 +23,6 @@ import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.io.Skippable;
import org.springframework.batch.io.file.FieldSetInputSource;
import org.springframework.batch.repeat.synch.BatchTransactionSynchronizationManager;
import org.springframework.batch.restart.GenericRestartData;
import org.springframework.batch.restart.RestartData;
@@ -37,7 +36,7 @@ import org.springframework.transaction.support.TransactionSynchronizationAdapter
* This class is a {@link FieldSetInputSource} that supports restart,
* skipping invalid lines and storing statistics.
* </p>
*
*
* @author Waseem Malik
* @author Tomas Slanina
* @author Robert Kasanicky
@@ -49,13 +48,13 @@ public class DefaultFlatFileInputSource extends SimpleFlatFileInputSource implem
public static final String READ_STATISTICS_NAME = "lines.read.count";
public static final String SKIPPED_STATISTICS_NAME = "skipped.lines.count";
private Set skippedLines = new HashSet();
private TransactionSynchronization transactionSynchronization = new ResourceLineReaderTransactionSynchronization();
private Properties statistics = new Properties();
/**
* Initialize the input source.
*/
@@ -73,14 +72,14 @@ public class DefaultFlatFileInputSource extends SimpleFlatFileInputSource implem
* This method initialises the Input Source for Restart. It opens the input
* file and position the buffer reader according to information provided by
* the restart data
*
*
* @param restartData restartData information
*/
public void restoreFrom(RestartData data) {
//TODO this does not look very nice...
if (data==null ||
data.getProperties() == null ||
if (data==null ||
data.getProperties() == null ||
data.getProperties().getProperty(READ_STATISTICS_NAME) == null ||
getReader()==null) {
// do nothing
@@ -173,7 +172,7 @@ public class DefaultFlatFileInputSource extends SimpleFlatFileInputSource implem
/**
* TransactionSynchronization method indicating that a transaction has
* completed.
*
*
* @param status indicates whether it was a rollback or commit
*/
public void afterCompletion(int status) {

View File

@@ -19,9 +19,10 @@ 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.exception.ValidationException;
import org.springframework.batch.io.file.FieldSet;
import org.springframework.batch.io.file.FieldSetInputSource;
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;
@@ -37,17 +38,17 @@ import org.springframework.util.Assert;
* 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 ResourceLifecycle, FieldSetInputSource, InitializingBean, DisposableBean {
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";
@@ -64,6 +65,8 @@ public class SimpleFlatFileInputSource implements ResourceLifecycle, FieldSetInp
private LineTokenizer tokenizer = new DelimitedLineTokenizer();
private FieldSetMapper fieldSetMapper;
private String encoding = DEFAULT_CHARSET;
/**
@@ -80,7 +83,7 @@ public class SimpleFlatFileInputSource implements ResourceLifecycle, FieldSetInp
* 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) {
@@ -90,6 +93,7 @@ public class SimpleFlatFileInputSource implements ResourceLifecycle, FieldSetInp
public void afterPropertiesSet() throws Exception {
Assert.notNull(resource);
Assert.state(resource.exists(), "Resource must exist: [" + resource + "]");
Assert.notNull(fieldSetMapper, "FieldSetMapper must not be null.");
}
/**
@@ -107,7 +111,7 @@ public class SimpleFlatFileInputSource implements ResourceLifecycle, FieldSetInp
/**
* Close and null out the reader.
*
*
* @see ResourceLifecycle
*/
public void close() {
@@ -124,7 +128,7 @@ public class SimpleFlatFileInputSource implements ResourceLifecycle, FieldSetInp
/**
* 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 {
@@ -139,31 +143,21 @@ public class SimpleFlatFileInputSource implements ResourceLifecycle, FieldSetInp
/**
* A wrapper for {@link #readFieldSet()} to make this into a real
* {@link InputSource}.
*
*
* @see org.springframework.batch.io.InputSource#read()
*/
public final Object read() {
return readFieldSet();
}
/**
* Get the next {@link FieldSet} from the input.
*
* @see org.springframework.batch.io.file.FieldSetInputSource#readFieldSet()
*/
public FieldSet readFieldSet() {
public Object read() {
String line = readLine();
if (line != null) {
try {
return this.tokenizer.tokenize(line);
FieldSet tokenizedLine = tokenizer.tokenize(line);
return fieldSetMapper.mapLine(tokenizedLine);
}
catch (RuntimeException ve) {
catch (RuntimeException ex) {
// add current line count to message and re-throw
// TODO: wrap the exception more carefully to preserve type etc.
ValidationException newVe = new ValidationException("Validation error at line "
+ getReader().getCurrentLineCount() + ": " + ve.getMessage());
throw newVe;
throw new FlatFileParsingException("Parsing error", ex, line,
getReader().getCurrentLineCount());
}
}
return null;
@@ -172,7 +166,7 @@ public class SimpleFlatFileInputSource implements ResourceLifecycle, FieldSetInp
/**
* 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;
*/
@@ -187,6 +181,15 @@ public class SimpleFlatFileInputSource implements ResourceLifecycle, FieldSetInp
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) {

View File

@@ -1,74 +0,0 @@
/*
* 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.item.provider;
import org.springframework.batch.io.file.FieldSet;
import org.springframework.batch.io.file.FieldSetInputSource;
import org.springframework.batch.item.ItemProvider;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
/**
* {@link ItemProvider} based on {@link FieldSetInputSource}. Not restartable
* or transaction aware, but can be used by multiple concurrent threads, so
* useful as a base class or for testing.
*
* @author Rob Harrop
* @author Dave Syer
*/
public abstract class AbstractFieldSetItemProvider extends AbstractItemProvider implements InitializingBean {
protected FieldSetInputSource source;
private Object mutex = new Object();
/**
* Make sure mandatory properties are set.
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
public void afterPropertiesSet() throws Exception {
Assert.notNull(source);
}
/**
* Setter for the input source. Mandatory with no default.
* @param source
*/
public void setSource(FieldSetInputSource source) {
this.source = source;
}
/**
* Get the next field set from the input source, and then call
* {@link #transform(FieldSet)} on the result. Synchronizes access to the
* input source using an internal mutex as a lock.
*
* @see org.springframework.batch.item.ItemProvider#next()
*/
public final Object next() {
FieldSet fieldSet;
synchronized (mutex) {
fieldSet = this.source.readFieldSet();
if (fieldSet != null) {
return transform(fieldSet);
}
}
return null;
}
protected abstract Object transform(FieldSet fieldSet);
}

View File

@@ -1,116 +0,0 @@
/*
* 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.item.provider;
import java.util.Properties;
import org.springframework.batch.io.Skippable;
import org.springframework.batch.io.file.FieldSet;
import org.springframework.batch.io.file.FieldSetMapper;
import org.springframework.batch.item.validator.Validator;
import org.springframework.batch.restart.RestartData;
import org.springframework.batch.restart.Restartable;
import org.springframework.batch.statistics.StatisticsProvider;
/**
*
* Uses a {@link FieldSetMapper} to convert each line from an input source. Also
* adds {@link Restartable} as mandatory behaviour, delegating to the parent
* provider's input source.
*
* @author Dave Syer
*/
public class FlatFileItemProvider extends AbstractFieldSetItemProvider implements Restartable,
StatisticsProvider, Skippable {
private FieldSetMapper mapper;
private Validator validator;
/*
* (non-Javadoc)
* @see org.springframework.batch.item.provider.AbstractFieldSetItemProvider#doNext(org.springframework.batch.io.line.FieldSet)
*/
protected Object transform(FieldSet fieldSet) {
Object value = mapper.mapLine(fieldSet);
if (validator!=null) {
validator.validate(value);
}
return value;
}
/**
* @param mapper the mapper to set
*/
public void setMapper(FieldSetMapper mapper) {
this.mapper = mapper;
}
/**
* @param validator the validator to set
*/
public void setValidator(Validator validator) {
this.validator = validator;
}
/**
* @see Restartable#getRestartData()
* @throws IllegalStateException if the parent template is not itself
* {@link Restartable}.
*/
public RestartData getRestartData() {
if (!(source instanceof Restartable)) {
throw new IllegalStateException("Input Template is not Restartable");
}
return ((Restartable) source).getRestartData();
}
/**
* @see Restartable#restoreFrom(RestartData)
* @throws IllegalStateException if the parent template is not itself
* {@link Restartable}.
*/
public void restoreFrom(RestartData data) {
if (!(source instanceof Restartable)) {
throw new IllegalStateException("Input Template is not Restartable");
}
((Restartable) source).restoreFrom(data);
}
/**
* @return delegates to the parent template of it is a
* {@link StatisticsProvider}, otherwise returns an empty
* {@link Properties} instance.
* @see StatisticsProvider#getStatistics()
*/
public Properties getStatistics() {
if (!(source instanceof StatisticsProvider)) {
return new Properties();
}
return ((StatisticsProvider) source).getStatistics();
}
/**
* @return delegates to the input source if it is a
* {@link Skippable}.
* @see Skippable#skip()
*/
public void skip() {
if (source instanceof Skippable) {
((Skippable) source).skip();
}
}
}

View File

@@ -23,24 +23,29 @@ import org.springframework.batch.io.Skippable;
import org.springframework.batch.restart.RestartData;
import org.springframework.batch.restart.Restartable;
import org.springframework.batch.statistics.StatisticsProvider;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
/**
* Simple wrapper around {@link InputSource}. The input source is expected to
* take care of open and close operations. If necessary it should be registered
* as a step scoped bean to ensure that the lifecycle methods are called.
*
*
* @author Dave Syer
*/
public class InputSourceItemProvider extends AbstractItemProvider implements Restartable, StatisticsProvider, Skippable {
public class InputSourceItemProvider extends AbstractItemProvider implements Restartable, StatisticsProvider, Skippable, InitializingBean{
private InputSource source;
private InputSource inputSource;
public void afterPropertiesSet() throws Exception {
Assert.notNull(inputSource, "InputSource must not be null.");
}
/**
* Get the next object from the input source.
* @see org.springframework.batch.item.ItemProvider#next()
*/
public Object next() {
Object value = source.read();
Object value = inputSource.read();
return value;
}
@@ -50,10 +55,10 @@ public class InputSourceItemProvider extends AbstractItemProvider implements Res
* {@link Restartable}.
*/
public RestartData getRestartData() {
if (!(source instanceof Restartable)) {
if (!(inputSource instanceof Restartable)) {
throw new IllegalStateException("Input Template is not Restartable");
}
return ((Restartable) source).getRestartData();
return ((Restartable) inputSource).getRestartData();
}
/**
@@ -62,10 +67,10 @@ public class InputSourceItemProvider extends AbstractItemProvider implements Res
* {@link Restartable}.
*/
public void restoreFrom(RestartData data) {
if (!(source instanceof Restartable)) {
if (!(inputSource instanceof Restartable)) {
throw new IllegalStateException("Input Template is not Restartable");
}
((Restartable) source).restoreFrom(data);
((Restartable) inputSource).restoreFrom(data);
}
/**
@@ -75,10 +80,10 @@ public class InputSourceItemProvider extends AbstractItemProvider implements Res
* @see StatisticsProvider#getStatistics()
*/
public Properties getStatistics() {
if (!(source instanceof StatisticsProvider)) {
if (!(inputSource instanceof StatisticsProvider)) {
return new Properties();
}
return ((StatisticsProvider) source).getStatistics();
return ((StatisticsProvider) inputSource).getStatistics();
}
/**
@@ -86,12 +91,16 @@ public class InputSourceItemProvider extends AbstractItemProvider implements Res
* @param source
*/
public void setInputSource(InputSource source) {
this.source = source;
this.inputSource = source;
}
public InputSource getInputSource() {
return inputSource;
}
public void skip() {
if (source instanceof Skippable) {
((Skippable)source).skip();
if (inputSource instanceof Skippable) {
((Skippable)inputSource).skip();
}
}
}

View File

@@ -0,0 +1,59 @@
/*
* 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.item.provider;
import org.springframework.batch.item.validator.Validator;
import org.springframework.util.Assert;
/**
* Simple extension of InputsourceItemProvider that provides for
* validation before returning input.
*
* @author Lucas Ward
*
*/
public class ValidatingItemProvider extends InputSourceItemProvider {
private Validator validator;
/* (non-Javadoc)
* @see org.springframework.batch.item.provider.InputSourceItemProvider#afterPropertiesSet()
*/
public void afterPropertiesSet() throws Exception {
super.afterPropertiesSet();
Assert.notNull(validator, "Validator must not be null.");
}
/* (non-Javadoc)
* @see org.springframework.batch.item.provider.InputSourceItemProvider#next()
*/
public Object next() {
Object input = super.next();
if(input != null){
validator.validate(input);
}
return input;
}
/**
* Set the validator used to validate each item.
*
* @param validator
*/
public void setValidator(Validator validator) {
this.validator = validator;
}
}

View File

@@ -21,6 +21,7 @@ import java.io.IOException;
import junit.framework.TestCase;
import org.springframework.batch.io.file.FieldSet;
import org.springframework.batch.io.file.FieldSetMapper;
import org.springframework.batch.io.file.support.DefaultFlatFileInputSource;
import org.springframework.batch.io.file.support.transform.LineTokenizer;
import org.springframework.batch.restart.RestartData;
@@ -30,16 +31,16 @@ import org.springframework.transaction.support.TransactionSynchronization;
/**
* Tests for {@link DefaultFlatFileInputSource}
*
*
* @author robert.kasanicky
*
*
* TODO only regular reading is tested currently, add exception cases, restart,
* skip, validation...
*/
public class DefaultFlatFileInputSourceTests extends TestCase {
// object under test
private DefaultFlatFileInputSource template = new DefaultFlatFileInputSource();
private DefaultFlatFileInputSource inputSource = new DefaultFlatFileInputSource();
// common value used for writing to a file
private String TEST_STRING = "FlatFileInputTemplate-TestData";
@@ -51,25 +52,31 @@ public class DefaultFlatFileInputSourceTests extends TestCase {
}
};
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 {
template.setResource(getInputResource(TEST_STRING));
template.setTokenizer(tokenizer);
inputSource.setResource(getInputResource(TEST_STRING));
inputSource.setTokenizer(tokenizer);
inputSource.setFieldSetMapper(fieldSetMapper);
// context argument is necessary only for the FileLocator, which
// is mocked
template.open();
inputSource.open();
}
/**
* Release resources and delete the temporary file
*/
protected void tearDown() throws Exception {
template.close();
inputSource.close();
}
private Resource getInputResource(String input) {
@@ -82,25 +89,25 @@ public class DefaultFlatFileInputSourceTests extends TestCase {
*/
public void testSkip() throws IOException {
template.close();
template.setResource(getInputResource("testLine1\ntestLine2\ntestLine3\ntestLine4\ntestLine5\ntestLine6"));
template.open();
inputSource.close();
inputSource.setResource(getInputResource("testLine1\ntestLine2\ntestLine3\ntestLine4\ntestLine5\ntestLine6"));
inputSource.open();
// read some records
template.readFieldSet(); // #1
template.readFieldSet(); // #2
inputSource.read(); // #1
inputSource.read(); // #2
// commit them
template.getTransactionSynchronization().afterCompletion(TransactionSynchronization.STATUS_COMMITTED);
inputSource.getTransactionSynchronization().afterCompletion(TransactionSynchronization.STATUS_COMMITTED);
// read next record
template.readFieldSet(); // # 3
inputSource.read(); // # 3
// mark record as skipped
template.skip();
inputSource.skip();
// read next records
template.getTransactionSynchronization().afterCompletion(TransactionSynchronization.STATUS_ROLLED_BACK);
inputSource.getTransactionSynchronization().afterCompletion(TransactionSynchronization.STATUS_ROLLED_BACK);
// we should now process all records after first commit point, that are
// not marked as skipped
assertEquals("[testLine4]", template.readFieldSet().toString());
assertEquals("[testLine4]", inputSource.read().toString());
// TODO update
// Map statistics = template.getStatistics();
@@ -117,14 +124,14 @@ public class DefaultFlatFileInputSourceTests extends TestCase {
*/
public void testTransactionSynchronizationUnknown() throws IOException {
template.close();
template.setResource(getInputResource("testLine1\ntestLine2\ntestLine3\ntestLine4\ntestLine5\ntestLine6"));
template.open();
inputSource.close();
inputSource.setResource(getInputResource("testLine1\ntestLine2\ntestLine3\ntestLine4\ntestLine5\ntestLine6"));
inputSource.open();
// read some records
template.readFieldSet();
template.skip();
template.readFieldSet();
inputSource.read();
inputSource.skip();
inputSource.read();
// TODO
// statistics = template.getStatistics();
// skipped = (String)
@@ -134,7 +141,7 @@ public class DefaultFlatFileInputSourceTests extends TestCase {
// call unknown, which has no influence and therefore statistics should
// be the same
template.getTransactionSynchronization().afterCompletion(TransactionSynchronization.STATUS_UNKNOWN);
inputSource.getTransactionSynchronization().afterCompletion(TransactionSynchronization.STATUS_UNKNOWN);
// TODO
// statistics = template.getStatistics();
// assertEquals(skipped, (String)
@@ -142,51 +149,51 @@ public class DefaultFlatFileInputSourceTests extends TestCase {
// assertEquals(read, (String)
// statistics.get(FlatFileInputTemplate.READ_STATISTICS_NAME));
}
public void testRestartFromNullData() throws Exception {
template.restoreFrom(null);
assertEquals("[FlatFileInputTemplate-TestData]", template.readFieldSet().toString());
inputSource.restoreFrom(null);
assertEquals("[FlatFileInputTemplate-TestData]", inputSource.read().toString());
}
public void testRestartWithNullReader() throws Exception {
template = new DefaultFlatFileInputSource();
template.setResource(getInputResource(TEST_STRING));
inputSource = new DefaultFlatFileInputSource();
inputSource.setResource(getInputResource(TEST_STRING));
// do not open the template...
template.restoreFrom(template.getRestartData());
assertEquals("[FlatFileInputTemplate-TestData]", template.readFieldSet().toString());
inputSource.restoreFrom(inputSource.getRestartData());
assertEquals("[FlatFileInputTemplate-TestData]", inputSource.read().toString());
}
public void testRestart() throws IOException {
template.close();
template.setResource(getInputResource("testLine1\ntestLine2\ntestLine3\ntestLine4\ntestLine5\ntestLine6"));
template.open();
inputSource.close();
inputSource.setResource(getInputResource("testLine1\ntestLine2\ntestLine3\ntestLine4\ntestLine5\ntestLine6"));
inputSource.open();
// read some records
template.readFieldSet();
template.readFieldSet();
inputSource.read();
inputSource.read();
// commit them
template.getTransactionSynchronization().afterCompletion(TransactionSynchronization.STATUS_COMMITTED);
inputSource.getTransactionSynchronization().afterCompletion(TransactionSynchronization.STATUS_COMMITTED);
// read next two records
template.readFieldSet();
template.readFieldSet();
inputSource.read();
inputSource.read();
// get restart data
RestartData restartData = template.getRestartData();
RestartData restartData = inputSource.getRestartData();
// TODO
// assertEquals("4", (String) restartData);
// close input
template.close();
inputSource.close();
template.setResource(getInputResource("testLine1\ntestLine2\ntestLine3\ntestLine4\ntestLine5\ntestLine6"));
inputSource.setResource(getInputResource("testLine1\ntestLine2\ntestLine3\ntestLine4\ntestLine5\ntestLine6"));
// init for restart
template.open();
template.restoreFrom(restartData);
inputSource.open();
inputSource.restoreFrom(restartData);
// read remaining records
assertEquals("[testLine5]", template.readFieldSet().toString());
assertEquals("[testLine6]", template.readFieldSet().toString());
assertEquals("[testLine5]", inputSource.read().toString());
assertEquals("[testLine6]", inputSource.read().toString());
// TODO
// Map statistics = template.getStatistics();

View File

@@ -23,8 +23,10 @@ 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.exception.ValidationException;
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;
@@ -33,14 +35,14 @@ import org.springframework.core.io.Resource;
/**
* Tests for {@link SimpleFlatFileInputSourceTests}
*
*
* @author Dave Syer
*
*
*/
public class SimpleFlatFileInputSourceTests extends TestCase {
// object under test
private SimpleFlatFileInputSource template = new SimpleFlatFileInputSource();
private SimpleFlatFileInputSource inputSource = new SimpleFlatFileInputSource();
// common value used for writing to a file
private String TEST_STRING = "FlatFileInputTemplate-TestData";
@@ -52,101 +54,117 @@ public class SimpleFlatFileInputSourceTests extends TestCase {
}
};
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 {
template.setResource(getInputResource(TEST_STRING));
template.setTokenizer(tokenizer);
template.afterPropertiesSet();
inputSource.setResource(getInputResource(TEST_STRING));
inputSource.setTokenizer(tokenizer);
inputSource.setFieldSetMapper(fieldSetMapper);
inputSource.afterPropertiesSet();
// context argument is necessary only for the FileLocator, which
// is mocked
template.open();
inputSource.open();
}
/**
* Release resources.
*/
protected void tearDown() throws Exception {
template.close();
inputSource.close();
}
private Resource getInputResource(String input) {
return new ByteArrayResource(input.getBytes());
}
/**
* Regular usage of <code>read</code> method
*/
public void testReadFieldSet() throws IOException {
assertEquals("[FlatFileInputTemplate-TestData]", template.readFieldSet().toString());
}
/**
* Regular usage of <code>read</code> method
*/
public void testRead() throws IOException {
assertEquals("[FlatFileInputTemplate-TestData]", template.read().toString());
assertEquals("[FlatFileInputTemplate-TestData]", inputSource.read().toString());
}
/**
* Regular usage of <code>read</code> method
*/
public void testReadExhausted() throws IOException {
assertEquals("[FlatFileInputTemplate-TestData]", template.read().toString());
assertEquals(null, template.read());
assertEquals("[FlatFileInputTemplate-TestData]", inputSource.read().toString());
assertEquals(null, inputSource.read());
}
/**
* Regular usage of <code>read</code> method
*/
public void testReadWithError() throws IOException {
template.setTokenizer(new LineTokenizer() {
public void testReadWithTokenizerError() throws IOException {
inputSource.setTokenizer(new LineTokenizer() {
public FieldSet tokenize(String line) {
throw new RuntimeException("foo");
}
});
try {
template.read();
fail("Expected ValidationException");
} catch (ValidationException e) {
assertTrue(e.getMessage().indexOf("at line")>=0);
assertTrue(e.getMessage().indexOf("at line 1")>=0);
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 {
template = new SimpleFlatFileInputSource();
template.setResource(getInputResource(TEST_STRING));
assertEquals("[FlatFileInputTemplate-TestData]", template.readFieldSet().toString());
inputSource = new SimpleFlatFileInputSource();
inputSource.setResource(getInputResource(TEST_STRING));
assertEquals("[FlatFileInputTemplate-TestData]", inputSource.read().toString());
}
public void testCloseBeforeOpen() throws Exception {
template = new SimpleFlatFileInputSource();
template.setResource(getInputResource(TEST_STRING));
template.close();
inputSource = new SimpleFlatFileInputSource();
inputSource.setResource(getInputResource(TEST_STRING));
inputSource.close();
// The open still happens automatically on a read...
assertEquals("[FlatFileInputTemplate-TestData]", template.readFieldSet().toString());
assertEquals("[FlatFileInputTemplate-TestData]", inputSource.read().toString());
}
public void testCloseOnDestroy() throws Exception {
final List list = new ArrayList();
template = new SimpleFlatFileInputSource() {
inputSource = new SimpleFlatFileInputSource() {
public void close() {
list.add("close");
}
};
template.destroy();
inputSource.destroy();
assertEquals(1, list.size());
}
public void testInitializationWithNullResource() throws Exception {
template = new SimpleFlatFileInputSource();
inputSource = new SimpleFlatFileInputSource();
try {
template.afterPropertiesSet();
inputSource.afterPropertiesSet();
fail("Expected IllegalArgumentException");
}
catch (IllegalArgumentException e) {
@@ -155,23 +173,23 @@ public class SimpleFlatFileInputSourceTests extends TestCase {
}
public void testOpenTwiceHasNoEffect() throws Exception {
template.open();
inputSource.open();
testRead();
}
public void testSetValidEncoding() throws Exception {
template = new SimpleFlatFileInputSource();
template.setEncoding("UTF-8");
template.setResource(getInputResource(TEST_STRING));
inputSource = new SimpleFlatFileInputSource();
inputSource.setEncoding("UTF-8");
inputSource.setResource(getInputResource(TEST_STRING));
testRead();
}
public void testSetNullEncoding() throws Exception {
template = new SimpleFlatFileInputSource();
template.setEncoding(null);
template.setResource(getInputResource(TEST_STRING));
inputSource = new SimpleFlatFileInputSource();
inputSource.setEncoding(null);
inputSource.setResource(getInputResource(TEST_STRING));
try {
template.open();
inputSource.open();
fail("Expected IllegalArgumentException");
}
catch (IllegalArgumentException e) {
@@ -180,11 +198,11 @@ public class SimpleFlatFileInputSourceTests extends TestCase {
}
public void testSetInvalidEncoding() throws Exception {
template = new SimpleFlatFileInputSource();
template.setEncoding("foo");
template.setResource(getInputResource(TEST_STRING));
inputSource = new SimpleFlatFileInputSource();
inputSource.setEncoding("foo");
inputSource.setResource(getInputResource(TEST_STRING));
try {
template.open();
inputSource.open();
fail("Expected BatchEnvironmentException");
}
catch (BatchEnvironmentException e) {
@@ -194,12 +212,12 @@ public class SimpleFlatFileInputSourceTests extends TestCase {
}
public void testEncoding() throws Exception {
template.setEncoding("UTF-8");
inputSource.setEncoding("UTF-8");
testRead();
}
public void testRecordSeparator() throws Exception {
template.setRecordSeparatorPolicy(new DefaultRecordSeparatorPolicy());
inputSource.setRecordSeparatorPolicy(new DefaultRecordSeparatorPolicy());
testRead();
}

View File

@@ -1,59 +0,0 @@
/*
* 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.item.provider;
import junit.framework.TestCase;
import org.springframework.batch.io.file.FieldSet;
import org.springframework.batch.io.file.FieldSetInputSource;
import org.springframework.batch.io.file.support.SimpleFlatFileInputSource;
import org.springframework.core.io.ByteArrayResource;
/**
* @author Dave Syer
*
*/
public class AbstractFieldSetItemProviderTests extends TestCase {
public void testNotOpen() throws Exception {
TestItemProvider provider = new TestItemProvider();
provider.setSource(getInputSource("one\ntwo\nthree"));
assertNotNull(provider.next());
}
public void testAfterPropertiesSet() throws Exception {
TestItemProvider provider = new TestItemProvider();
try {
provider.afterPropertiesSet();
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
// expected
}
}
private static class TestItemProvider extends AbstractFieldSetItemProvider {
protected Object transform(FieldSet fieldSet) {
return fieldSet.toString();
}
}
private FieldSetInputSource getInputSource(String data) throws Exception {
SimpleFlatFileInputSource template = new SimpleFlatFileInputSource();
template.setResource(new ByteArrayResource(data.getBytes()));
template.afterPropertiesSet();
return template;
}
}

View File

@@ -1,54 +0,0 @@
/*
* 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.item.provider;
import junit.framework.TestCase;
import org.springframework.batch.io.file.FieldSet;
import org.springframework.batch.io.file.support.SimpleFlatFileInputSource;
import org.springframework.core.io.ByteArrayResource;
public class FieldSetItemProviderTests extends TestCase {
public void testNotOpen() throws Exception {
TestItemProvider provider = new TestItemProvider("one\ntwo\nthree");
assertNotNull(provider.next());
}
public void testNext() throws Exception {
TestItemProvider provider = new TestItemProvider("one\ntwo\nthree");
assertEquals("[one]", provider.next());
assertEquals("[two]", provider.next());
assertEquals("[three]", provider.next());
assertEquals(null, provider.next());
}
private static class TestItemProvider extends AbstractFieldSetItemProvider {
public TestItemProvider(String data) throws Exception {
super();
SimpleFlatFileInputSource template = new SimpleFlatFileInputSource();
template.setResource(new ByteArrayResource(data.getBytes()));
template.afterPropertiesSet();
setSource(template);
}
protected Object transform(FieldSet fieldSet) {
return fieldSet.toString();
}
}
}

View File

@@ -1,217 +0,0 @@
/*
* 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.item.provider;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import junit.framework.TestCase;
import org.springframework.batch.io.Skippable;
import org.springframework.batch.io.exception.ValidationException;
import org.springframework.batch.io.file.FieldSet;
import org.springframework.batch.io.file.FieldSetInputSource;
import org.springframework.batch.io.file.FieldSetMapper;
import org.springframework.batch.io.file.support.DefaultFlatFileInputSource;
import org.springframework.batch.item.provider.FlatFileItemProvider;
import org.springframework.batch.item.validator.Validator;
import org.springframework.batch.restart.GenericRestartData;
import org.springframework.batch.restart.RestartData;
import org.springframework.batch.restart.Restartable;
import org.springframework.batch.statistics.StatisticsProvider;
import org.springframework.batch.support.PropertiesConverter;
import org.springframework.core.io.ByteArrayResource;
/**
* Unit tests for {@link FlatFileItemProvider}
*
* @author Robert Kasanicky
* @author Dave Syer
*/
public class FlatFileItemProviderTests extends TestCase {
public static String FOO = "foo";
// object under test
private FlatFileItemProvider itemProvider = new FlatFileItemProvider();
// Input source
private DefaultFlatFileInputSource source;
// mock mapper
private FieldSetMapper mapper;
private List list = new ArrayList();
// create mock objects and inject them into data provider
protected void setUp() throws Exception {
source = new DefaultFlatFileInputSource() {
public void skip() {
super.skip();
list.add("skipped");
}
};
source.setResource(new ByteArrayResource("a,b".getBytes()));
mapper = new FieldSetMapper() {
public Object mapLine(FieldSet fs) {
return FOO;
}
};
itemProvider.setSource(source);
itemProvider.setMapper(mapper);
assertTrue(Restartable.class
.isAssignableFrom(DefaultFlatFileInputSource.class));
assertTrue(Skippable.class
.isAssignableFrom(DefaultFlatFileInputSource.class));
assertTrue(FieldSetInputSource.class
.isAssignableFrom(DefaultFlatFileInputSource.class));
assertTrue(StatisticsProvider.class
.isAssignableFrom(DefaultFlatFileInputSource.class));
}
/**
* Uses input template to provide the domain object.
*/
public void testNext() {
Object result = itemProvider.next();
assertSame("domain object is provided by the input template", FOO,
result);
}
/**
* Uses input template to provide the domain object.
*/
public void testNextWithValidator() {
itemProvider.setValidator(new Validator() {
public void validate(Object value) throws ValidationException {
list.add(value);
}
});
itemProvider.next();
assertSame("domain object is provided by the input template", FOO, list
.get(0));
}
/**
* Uses input template to provide the domain object.
*/
public void testNextWithValidatorAndInvalidData() {
itemProvider.setValidator(new Validator() {
public void validate(Object value) throws ValidationException {
throw new ValidationException("Invalid input");
}
});
try {
itemProvider.next();
fail("Expected ValidationException");
} catch (ValidationException e) {
// expected
assertEquals("Invalid input", e.getMessage());
}
}
/**
* Gets statistics from the input template
*/
public void testGetStatistics() {
Properties statistics = ((StatisticsProvider) source).getStatistics();
assertEquals(statistics, itemProvider.getStatistics());
}
/**
* Gets statistics from the input template
*/
public void testGetStatisticsWithoutStatisticsProvider() {
itemProvider.setSource(null);
Properties props = itemProvider.getStatistics();
assertEquals(null, props.getProperty("a"));
}
/**
* Gets restart data from the input template
*/
public void testGetRestartData() {
RestartData data = ((Restartable) source).getRestartData();
assertEquals(data.getProperties(), itemProvider.getRestartData()
.getProperties());
}
/**
* Forwarded restart data to input template
*/
public void testRestoreFrom() {
final List list = new ArrayList();
RestartData data = new RestartData() {
public Properties getProperties() {
list.add(FOO);
return ((Restartable) source).getRestartData().getProperties();
}
};
itemProvider.restoreFrom(data);
// assertEquals(1, list.size()); getProperties are called multiple times
// due to null checks
assertTrue(list.size() > 0);
}
/**
* Forward restart data to input template
*
* @throws Exception
*/
public void testRestoreFromWithoutRestartable() throws Exception {
itemProvider.setSource(null);
try {
itemProvider.restoreFrom(new GenericRestartData(PropertiesConverter
.stringToProperties("value=bar")));
fail("Expected IllegalStateException");
} catch (IllegalStateException e) {
// expected
}
}
/**
* Forward restart data to input template
*
* @throws Exception
*/
public void testGetRestartDataWithoutRestartable() throws Exception {
itemProvider.setSource(null);
try {
itemProvider.getRestartData();
fail("Expected IllegalStateException");
} catch (IllegalStateException e) {
// expected
}
}
/**
* Forward restart data to input template
*
* @throws Exception
*/
public void testSkippable() throws Exception {
assertEquals(0, list.size());
itemProvider.skip();
assertEquals(1, list.size());
}
}

View File

@@ -31,7 +31,7 @@ import org.springframework.batch.support.PropertiesConverter;
/**
* Unit test for {@link InputSourceItemProvider}
*
*
* @author Robert Kasanicky
*/
public class InputSourceItemProviderTests extends TestCase {
@@ -47,6 +47,21 @@ public class InputSourceItemProviderTests extends TestCase {
itemProvider.setInputSource(source);
}
public void testAfterPropertiesSet()throws Exception{
//shouldn't throw an exception since the input source is set
itemProvider.afterPropertiesSet();
}
public void testNullInputSource(){
try{
itemProvider.setInputSource(null);
itemProvider.afterPropertiesSet();
fail();
}catch(Exception ex){
assertTrue(ex instanceof IllegalArgumentException);
}
}
/**
* Uses input template to provide the domain object.
*/
@@ -78,7 +93,7 @@ public class InputSourceItemProviderTests extends TestCase {
itemProvider.restoreFrom(new GenericRestartData(PropertiesConverter.stringToProperties("value=bar")));
assertEquals("bar", itemProvider.next());
}
public void testSkip() {
itemProvider.skip();
assertEquals("after skip", itemProvider.next());
@@ -87,7 +102,7 @@ public class InputSourceItemProviderTests extends TestCase {
private class MockInputSource implements InputSource, StatisticsProvider, Restartable, Skippable {
private Object value;
public Properties getStatistics() {
return PropertiesConverter.stringToProperties("a=b");
}

View File

@@ -0,0 +1,114 @@
/*
* 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.item.provider;
import org.easymock.MockControl;
import org.springframework.batch.io.InputSource;
import org.springframework.batch.io.exception.ValidationException;
import org.springframework.batch.item.validator.Validator;
import junit.framework.TestCase;
/**
* @author Lucas Ward
*
*/
public class ValidatingItemProviderTests extends TestCase {
InputSource inputSource;
ValidatingItemProvider itemProvider;
Validator validator;
MockControl validatorControl = MockControl.createControl(Validator.class);
/* (non-Javadoc)
* @see junit.framework.TestCase#setUp()
*/
protected void setUp() throws Exception {
super.setUp();
inputSource = new MockInputSource(this);
validator = (Validator)validatorControl.getMock();
itemProvider = new ValidatingItemProvider();
itemProvider.setInputSource(inputSource);
itemProvider.setValidator(validator);
}
/*
* Super class' afterPropertieSet should be called to
* ensure InputSource is set.
*/
public void testInputSourcePropertiesSet(){
try{
itemProvider.setInputSource(null);
itemProvider.afterPropertiesSet();
fail();
}catch(Exception ex){
assertTrue(ex instanceof IllegalArgumentException);
}
}
public void testValidatorPropertesSet(){
try{
itemProvider.setValidator(null);
itemProvider.afterPropertiesSet();
fail();
}catch(Exception ex){
assertTrue(ex instanceof IllegalArgumentException);
}
}
public void testValidation(){
validator.validate(this);
validatorControl.replay();
assertEquals(itemProvider.next(), this);
validatorControl.verify();
}
public void testValidationException(){
validator.validate(this);
validatorControl.setThrowable(new ValidationException(""));
validatorControl.replay();
try{
itemProvider.next();
fail();
}catch(ValidationException ex){
//expected
}
}
public void testNullInput(){
validatorControl.replay();
itemProvider.setInputSource(new MockInputSource(null));
assertNull(itemProvider.next());
//assert validator wasn't called.
validatorControl.verify();
}
private class MockInputSource implements InputSource{
Object value;
public MockInputSource(Object value){
this.value = value;
}
public Object read() {
return value;
}
}
}

View File

@@ -19,17 +19,18 @@ package org.springframework.batch.repeat.support;
import junit.framework.TestCase;
import org.springframework.batch.io.file.FieldSet;
import org.springframework.batch.io.file.FieldSetMapper;
import org.springframework.batch.io.file.support.SimpleFlatFileInputSource;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.provider.AbstractFieldSetItemProvider;
import org.springframework.batch.item.provider.InputSourceItemProvider;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
/**
* Base class for simple tests with small trade data set.
*
*
* @author Dave Syer
*
*
*/
public abstract class AbstractTradeBatchTests extends TestCase {
@@ -46,18 +47,21 @@ public abstract class AbstractTradeBatchTests extends TestCase {
provider = new TradeItemProvider(resource);
}
protected static class TradeItemProvider extends AbstractFieldSetItemProvider {
protected static class TradeItemProvider extends InputSourceItemProvider {
protected TradeItemProvider(Resource resource) throws Exception {
super();
SimpleFlatFileInputSource template = new SimpleFlatFileInputSource();
template.setResource(resource);
template.afterPropertiesSet();
setSource(template);
SimpleFlatFileInputSource inputSource = new SimpleFlatFileInputSource();
inputSource.setResource(resource);
inputSource.setFieldSetMapper(new TradeMapper());
inputSource.afterPropertiesSet();
setInputSource(inputSource);
}
}
protected Object transform(FieldSet fieldSet) {
return new Trade(fieldSet);
protected static class TradeMapper implements FieldSetMapper{
public Object mapLine(FieldSet fs) {
return new Trade(fs);
}
}