Added builder for the FlatFileItemReader
This commit adds a builder for the `FlatFileItemReader` and commonly used releated components (`BeanWrapperFieldSetMapper`, `DelimitedLineTokenizer`, and `FixedLengthTokenizer`). Resolves BATCH-2549
This commit is contained in:
@@ -15,11 +15,15 @@
|
||||
*/
|
||||
package org.springframework.batch.item.file.builder;
|
||||
|
||||
import java.beans.PropertyEditor;
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.batch.item.file.FlatFileItemReader;
|
||||
@@ -36,11 +40,17 @@ import org.springframework.batch.item.file.transform.FieldSetFactory;
|
||||
import org.springframework.batch.item.file.transform.FixedLengthTokenizer;
|
||||
import org.springframework.batch.item.file.transform.LineTokenizer;
|
||||
import org.springframework.batch.item.file.transform.Range;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* A builder implementation for the {@link FlatFileItemReader}.
|
||||
*
|
||||
* @author Michael Minella
|
||||
* @since 4.0
|
||||
* @see FlatFileItemReader
|
||||
*/
|
||||
public class FlatFileItemReaderBuilder<T> {
|
||||
|
||||
@@ -71,94 +81,319 @@ public class FlatFileItemReaderBuilder<T> {
|
||||
|
||||
private FixedLengthBuilder<T> fixedLengthBuilder;
|
||||
|
||||
private Class<? extends T> beanMapperClass;
|
||||
private Class<? extends T> targetType;
|
||||
|
||||
private String prototypeBeanName;
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
private Map<Class<?>, PropertyEditor> customEditors = new HashMap<>();
|
||||
|
||||
private int distanceLimit = 5;
|
||||
|
||||
private boolean beanMapperStrict = true;
|
||||
|
||||
private boolean saveState = true;
|
||||
|
||||
public FlatFileItemReaderBuilder<T> strict(boolean strict) {
|
||||
this.strict = strict;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FlatFileItemReaderBuilder<T> recordSeparatorPolicy(RecordSeparatorPolicy policy) {
|
||||
this.recordSeparatorPolicy = policy;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FlatFileItemReaderBuilder<T> resource(Resource resource) {
|
||||
this.resource = resource;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FlatFileItemReaderBuilder<T> maxItemCount(int maxItemCount) {
|
||||
this.maxItemCount = maxItemCount;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FlatFileItemReaderBuilder<T> comments(String[] comments) {
|
||||
this.comments.addAll(Arrays.asList(comments));
|
||||
return this;
|
||||
}
|
||||
private BigInteger tokenizerValidator = new BigInteger("0");
|
||||
|
||||
/**
|
||||
* Add a string to the list of Strings that indicate commented lines.
|
||||
*
|
||||
* @param comment the string to define a commented line.
|
||||
* @return The current instance of the builder.
|
||||
* @see FlatFileItemReader#setComments(String[])
|
||||
*/
|
||||
public FlatFileItemReaderBuilder<T> addComment(String comment) {
|
||||
this.comments.add(comment);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* An array of Strings that indicate lines that are comments (and therefore skipped by
|
||||
* the reader.
|
||||
*
|
||||
* @param comments an array of strings to identify comments.
|
||||
* @return The current instance of the builder.
|
||||
* @see FlatFileItemReader#setComments(String[])
|
||||
*/
|
||||
public FlatFileItemReaderBuilder<T> comments(String[] comments) {
|
||||
this.comments.addAll(Arrays.asList(comments));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the max number of items to be read.
|
||||
*
|
||||
* @param maxItemCount the max items to be read
|
||||
* @return The current instance of the builder.
|
||||
* @see FlatFileItemReader#setMaxItemCount(int)
|
||||
*/
|
||||
public FlatFileItemReaderBuilder<T> maxItemCount(int maxItemCount) {
|
||||
this.maxItemCount = maxItemCount;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure a custom {@link RecordSeparatorPolicy} for the reader.
|
||||
*
|
||||
* @param policy custom policy
|
||||
* @return The current instance of the builder.
|
||||
* @see FlatFileItemReader#setRecordSeparatorPolicy(RecordSeparatorPolicy)
|
||||
*/
|
||||
public FlatFileItemReaderBuilder<T> recordSeparatorPolicy(RecordSeparatorPolicy policy) {
|
||||
this.recordSeparatorPolicy = policy;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link Resource} to be used as input.
|
||||
*
|
||||
* @param resource the input to the reader.
|
||||
* @return The current instance of the builder.
|
||||
* @see FlatFileItemReader#setResource(Resource)
|
||||
*/
|
||||
public FlatFileItemReaderBuilder<T> resource(Resource resource) {
|
||||
this.resource = resource;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure if the reader should be in strict mode (require the input {@link Resource}
|
||||
* to exist).
|
||||
*
|
||||
* @param strict true if the input file is required to exist.
|
||||
* @return The current instance of the builder.
|
||||
* @see FlatFileItemReader#setStrict(boolean)
|
||||
*/
|
||||
public FlatFileItemReaderBuilder<T> strict(boolean strict) {
|
||||
this.strict = strict;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The number of lines to skip at the beginning of reading the file.
|
||||
*
|
||||
* @param linesToSkip number of lines to be skipped.
|
||||
* @return The current instance of the builder.
|
||||
* @see FlatFileItemReader#setLinesToSkip(int)
|
||||
*/
|
||||
public FlatFileItemReaderBuilder<T> linesToSkip(int linesToSkip) {
|
||||
this.linesToSkip = linesToSkip;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* A callback to be called for each line that is skipped.
|
||||
*
|
||||
* @param callback the callback
|
||||
* @return The current instance of the builder.
|
||||
* @see FlatFileItemReader#setSkippedLinesCallback(LineCallbackHandler)
|
||||
*/
|
||||
public FlatFileItemReaderBuilder<T> skippedLinesCallback(LineCallbackHandler callback) {
|
||||
this.skippedLinesCallback = callback;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link LineMapper} implementation to be used.
|
||||
*
|
||||
* @param lineMapper {@link LineMapper}
|
||||
* @return The current instance of the builder.
|
||||
* @see FlatFileItemReader#setLineMapper(LineMapper)
|
||||
*/
|
||||
public FlatFileItemReaderBuilder<T> lineMapper(LineMapper<T> lineMapper) {
|
||||
this.lineMapper = lineMapper;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link FieldSetMapper} implementation to be used.
|
||||
*
|
||||
* @param mapper a {@link FieldSetMapper}
|
||||
* @return The current instance of the builder.
|
||||
* @see DefaultLineMapper#setFieldSetMapper(FieldSetMapper)
|
||||
*/
|
||||
public FlatFileItemReaderBuilder<T> fieldSetMapper(FieldSetMapper<T> mapper) {
|
||||
this.fieldSetMapper = mapper;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link LineTokenizer} implementation to be used.
|
||||
*
|
||||
* @param tokenizer a {@link LineTokenizer}
|
||||
* @return The current instance of the builder.
|
||||
* @see DefaultLineMapper#setLineTokenizer(LineTokenizer)
|
||||
*/
|
||||
public FlatFileItemReaderBuilder<T> lineTokenizer(LineTokenizer tokenizer) {
|
||||
updateTokenizerValidation(tokenizer, 0);
|
||||
|
||||
this.lineTokenizer = tokenizer;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instance of a {@link DelimitedBuilder} for building a
|
||||
* {@link DelimitedLineTokenizer}. The {@link DelimitedLineTokenizer} configured by
|
||||
* this builder will only be used if one is not explicitly configured via
|
||||
* {@link FlatFileItemReaderBuilder#lineTokenizer}
|
||||
*
|
||||
* @return a {@link DelimitedBuilder}
|
||||
*
|
||||
*/
|
||||
public DelimitedBuilder<T> delimited() {
|
||||
this.delimitedBuilder = new DelimitedBuilder<>(this);
|
||||
updateTokenizerValidation(this.delimitedBuilder, 1);
|
||||
return this.delimitedBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instance of a {@link FixedLengthBuilder} for building a
|
||||
* {@link FixedLengthTokenizer}. The {@link FixedLengthTokenizer} configured by this
|
||||
* builder will only be used if the {@link FlatFileItemReaderBuilder#lineTokenizer}
|
||||
* has not been configured.
|
||||
*
|
||||
* @return a {@link FixedLengthBuilder}
|
||||
*/
|
||||
public FixedLengthBuilder<T> fixedLength() {
|
||||
this.fixedLengthBuilder = new FixedLengthBuilder<>(this);
|
||||
updateTokenizerValidation(this.fixedLengthBuilder, 2);
|
||||
return this.fixedLengthBuilder;
|
||||
}
|
||||
|
||||
public FlatFileItemReaderBuilder<T> beanMapperClass(Class beanMapperClass) {
|
||||
this.beanMapperClass = beanMapperClass;
|
||||
/**
|
||||
* The class that will represent the "item" to be returned from the reader. This
|
||||
* class is used via the {@link BeanWrapperFieldSetMapper}. If more complex logic is
|
||||
* required, providing your own {@link FieldSetMapper} via
|
||||
* {@link FlatFileItemReaderBuilder#fieldSetMapper} is required.
|
||||
*
|
||||
* @param targetType The class to map to
|
||||
* @return The current instance of the builder.
|
||||
* @see BeanWrapperFieldSetMapper#setTargetType(Class)
|
||||
*/
|
||||
public FlatFileItemReaderBuilder<T> targetType(Class<? extends T> targetType) {
|
||||
this.targetType = targetType;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the id of a prototype scoped bean to be used as the item returned by the
|
||||
* reader.
|
||||
*
|
||||
* @param prototypeBeanName the name of a prototype scoped bean
|
||||
* @return The current instance of the builder.
|
||||
* @see BeanWrapperFieldSetMapper#setPrototypeBeanName(String)
|
||||
*/
|
||||
public FlatFileItemReaderBuilder<T> prototypeBeanName(String prototypeBeanName) {
|
||||
this.prototypeBeanName = prototypeBeanName;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the {@link BeanFactory} used to create the beans that are returned as
|
||||
* items.
|
||||
*
|
||||
* @param beanFactory a {@link BeanFactory}
|
||||
* @return The current instance of the builder.
|
||||
* @see BeanWrapperFieldSetMapper#setBeanFactory(BeanFactory)
|
||||
*/
|
||||
public FlatFileItemReaderBuilder<T> beanFactory(BeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register custom type converters for beans being mapped.
|
||||
*
|
||||
* @param customEditors a {@link Map} of editors
|
||||
* @return The current instance of the builder.
|
||||
* @see BeanWrapperFieldSetMapper#setCustomEditors(Map)
|
||||
*/
|
||||
public FlatFileItemReaderBuilder<T> customEditors(Map<Class<?>, PropertyEditor> customEditors) {
|
||||
if(customEditors != null) {
|
||||
this.customEditors.putAll(customEditors);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the maximum tolerance between the actual spelling of a field's name and
|
||||
* the property's name.
|
||||
*
|
||||
* @param distanceLimit distance limit to set
|
||||
* @return The current instance of the builder.
|
||||
* @see BeanWrapperFieldSetMapper#setDistanceLimit(int)
|
||||
*/
|
||||
public FlatFileItemReaderBuilder<T> distanceLimit(int distanceLimit) {
|
||||
this.distanceLimit = distanceLimit;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* If set to true, mapping will fail if the {@link org.springframework.batch.item.file.transform.FieldSet}
|
||||
* contains fields that cannot be mapped to the bean.
|
||||
*
|
||||
* @param beanMapperStrict defaults to false
|
||||
* @return The current instance of the builder.
|
||||
* @see BeanWrapperFieldSetMapper#setStrict(boolean)
|
||||
*/
|
||||
public FlatFileItemReaderBuilder<T> beanMapperStrict(boolean beanMapperStrict) {
|
||||
this.beanMapperStrict = beanMapperStrict;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure if the state of the {@link FlatFileItemReader} should be persisted within
|
||||
* the {@link org.springframework.batch.item.ExecutionContext} for restart purposes.
|
||||
*
|
||||
* @param saveState defaults to true
|
||||
* @return The current instance of the builder.
|
||||
* @see FlatFileItemReader#setSaveState(boolean)
|
||||
*/
|
||||
public FlatFileItemReaderBuilder<T> saveState(boolean saveState) {
|
||||
this.saveState = saveState;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The name used to calculate the key within the
|
||||
* {@link org.springframework.batch.item.ExecutionContext}. Required if
|
||||
* {@link FlatFileItemReaderBuilder#saveState(boolean)} is set to true.
|
||||
*
|
||||
* @param name name of the reader instance
|
||||
* @return The current instance of the builder.
|
||||
* @see FlatFileItemReader#setName(String)
|
||||
*/
|
||||
public FlatFileItemReaderBuilder<T> name(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the {@link FlatFileItemReader}.
|
||||
*
|
||||
* @return a {@link FlatFileItemReader}
|
||||
* @throws Exception
|
||||
*/
|
||||
public FlatFileItemReader<T> build() throws Exception {
|
||||
if(this.saveState) {
|
||||
Assert.state(StringUtils.hasText(this.name),
|
||||
"A name is required when saveSate is set to true.");
|
||||
}
|
||||
Assert.notNull(this.resource, "A resource is required.");
|
||||
Assert.notNull(this.recordSeparatorPolicy, "A RecordSeparatorPolicy is required.");
|
||||
int validatorValue = this.tokenizerValidator.intValue();
|
||||
Assert.state(validatorValue == 1 || validatorValue == 2 || validatorValue == 4,
|
||||
"Only one LineTokenizer option may be configured");
|
||||
|
||||
FlatFileItemReader<T> reader = new FlatFileItemReader<>();
|
||||
|
||||
reader.setName(this.name);
|
||||
if(StringUtils.hasText(this.name)) {
|
||||
reader.setName(this.name);
|
||||
}
|
||||
|
||||
reader.setResource(this.resource);
|
||||
|
||||
if(this.lineMapper != null) {
|
||||
@@ -167,9 +402,8 @@ public class FlatFileItemReaderBuilder<T> {
|
||||
else {
|
||||
DefaultLineMapper<T> lineMapper = new DefaultLineMapper<>();
|
||||
|
||||
if(this.lineTokenizer != null) {
|
||||
if(this.lineTokenizer != null && this.fieldSetMapper != null) {
|
||||
lineMapper.setLineTokenizer(this.lineTokenizer);
|
||||
lineMapper.setFieldSetMapper(this.fieldSetMapper);
|
||||
}
|
||||
else if(this.fixedLengthBuilder != null) {
|
||||
lineMapper.setLineTokenizer(this.fixedLengthBuilder.build());
|
||||
@@ -178,22 +412,37 @@ public class FlatFileItemReaderBuilder<T> {
|
||||
lineMapper.setLineTokenizer(this.delimitedBuilder.build());
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("No LineTokenizer implementation was provided");
|
||||
throw new IllegalStateException("No LineTokenizer implementation was provided.");
|
||||
}
|
||||
|
||||
if(this.beanMapperClass != null) {
|
||||
BeanWrapperFieldSetMapper mapper = new BeanWrapperFieldSetMapper();
|
||||
mapper.setTargetType(this.beanMapperClass);
|
||||
if(this.targetType != null || StringUtils.hasText(this.prototypeBeanName)) {
|
||||
BeanWrapperFieldSetMapper<T> mapper = new BeanWrapperFieldSetMapper<>();
|
||||
mapper.setTargetType(this.targetType);
|
||||
mapper.setPrototypeBeanName(this.prototypeBeanName);
|
||||
mapper.setStrict(this.beanMapperStrict);
|
||||
mapper.setBeanFactory(this.beanFactory);
|
||||
mapper.setDistanceLimit(this.distanceLimit);
|
||||
mapper.setCustomEditors(this.customEditors);
|
||||
mapper.afterPropertiesSet();
|
||||
|
||||
lineMapper.setFieldSetMapper(mapper);
|
||||
}
|
||||
else if(this.fieldSetMapper != null) {
|
||||
lineMapper.setFieldSetMapper(this.fieldSetMapper);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("No FieldSetMapper implementation was provided.");
|
||||
}
|
||||
|
||||
reader.setLineMapper(lineMapper);
|
||||
}
|
||||
|
||||
reader.setLinesToSkip(this.linesToSkip);
|
||||
reader.setComments(this.comments.toArray(new String[this.comments.size()]));
|
||||
|
||||
if(!this.comments.isEmpty()) {
|
||||
reader.setComments(this.comments.toArray(new String[this.comments.size()]));
|
||||
}
|
||||
|
||||
reader.setSkippedLinesCallback(this.skippedLinesCallback);
|
||||
reader.setRecordSeparatorPolicy(this.recordSeparatorPolicy);
|
||||
reader.setMaxItemCount(this.maxItemCount);
|
||||
@@ -203,6 +452,20 @@ public class FlatFileItemReaderBuilder<T> {
|
||||
return reader;
|
||||
}
|
||||
|
||||
private void updateTokenizerValidation(Object tokenizer, int index) {
|
||||
if(tokenizer != null) {
|
||||
this.tokenizerValidator = this.tokenizerValidator.flipBit(index);
|
||||
}
|
||||
else {
|
||||
this.tokenizerValidator = this.tokenizerValidator.clearBit(index);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A builder for constructing a {@link DelimitedLineTokenizer}
|
||||
*
|
||||
* @param <T> the type of the parent {@link FlatFileItemReaderBuilder}
|
||||
*/
|
||||
public static class DelimitedBuilder<T> {
|
||||
private FlatFileItemReaderBuilder<T> parent;
|
||||
|
||||
@@ -218,41 +481,95 @@ public class FlatFileItemReaderBuilder<T> {
|
||||
|
||||
private boolean strict = true;
|
||||
|
||||
public DelimitedBuilder(FlatFileItemReaderBuilder<T> parent) {
|
||||
protected DelimitedBuilder(FlatFileItemReaderBuilder<T> parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the delimiter for the file.
|
||||
*
|
||||
* @param delimiter String used as a delimiter between fields.
|
||||
* @return The instance of the builder for chaining.
|
||||
* @see DelimitedLineTokenizer#setDelimiter(String)
|
||||
*/
|
||||
public DelimitedBuilder<T> delimiter(String delimiter) {
|
||||
this.delimiter = delimiter;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the character used to quote fields.
|
||||
*
|
||||
* @param quoteCharacter char used to define quoted fields
|
||||
* @return The instance of the builder for chaining.
|
||||
* @see DelimitedLineTokenizer#setQuoteCharacter(char)
|
||||
*/
|
||||
public DelimitedBuilder<T> quoteCharacter(char quoteCharacter) {
|
||||
this.quoteCharacter = quoteCharacter;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* A list of indices of the fields within a delimited file to be included
|
||||
*
|
||||
* @param fields indices of the fields
|
||||
* @return The instance of the builder for chaining.
|
||||
* @see DelimitedLineTokenizer#setIncludedFields(int[])
|
||||
*/
|
||||
public DelimitedBuilder<T> includedFields(Integer[] fields) {
|
||||
this.includedFields.addAll(Arrays.asList(fields));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an index to the list of fields to be included from the file
|
||||
*
|
||||
* @param field the index to be included
|
||||
* @return The instance of the builder for chaining.
|
||||
* @see DelimitedLineTokenizer#setIncludedFields(int[])
|
||||
*/
|
||||
public DelimitedBuilder<T> addIncludedField(int field) {
|
||||
this.includedFields.add(field);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* A factory for creating the resulting
|
||||
* {@link org.springframework.batch.item.file.transform.FieldSet}. Defaults to
|
||||
* {@link DefaultFieldSetFactory}.
|
||||
*
|
||||
* @param fieldSetFactory Factory for creating {@link org.springframework.batch.item.file.transform.FieldSet}
|
||||
* @return The instance of the builder for chaining.
|
||||
* @see DelimitedLineTokenizer#setFieldSetFactory(FieldSetFactory)
|
||||
*/
|
||||
public DelimitedBuilder<T> fieldSetFactory(FieldSetFactory fieldSetFactory) {
|
||||
this.fieldSetFactory = fieldSetFactory;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Names of each of the fields within the fields that are returned in the order
|
||||
* they occur within the delimited file. Required.
|
||||
*
|
||||
* @param names names of each field
|
||||
* @return The parent {@link FlatFileItemReaderBuilder}
|
||||
* @see DelimitedLineTokenizer#setNames(String[])
|
||||
*/
|
||||
public FlatFileItemReaderBuilder<T> names(String [] names) {
|
||||
this.names.addAll(Arrays.asList(names));
|
||||
return this.parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link DelimitedLineTokenizer}
|
||||
*
|
||||
* @return {@link DelimitedLineTokenizer}
|
||||
* @throws Exception
|
||||
*/
|
||||
public DelimitedLineTokenizer build() throws Exception {
|
||||
Assert.notNull(this.fieldSetFactory, "A FieldSetFactory is required.");
|
||||
Assert.notEmpty(this.names, "A list of field names is required");
|
||||
|
||||
DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer();
|
||||
|
||||
tokenizer.setNames(this.names.toArray(new String[this.names.size()]));
|
||||
@@ -288,59 +605,111 @@ public class FlatFileItemReaderBuilder<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A builder for constructing a {@link FixedLengthTokenizer}
|
||||
*
|
||||
* @param <T> the type of the parent {@link FlatFileItemReaderBuilder}
|
||||
*/
|
||||
public static class FixedLengthBuilder<T> {
|
||||
private FlatFileItemReaderBuilder<T> parent;
|
||||
|
||||
private List<Range> ranges = new ArrayList<>();
|
||||
|
||||
private int maxRange = 0;
|
||||
|
||||
private List<String> names = new ArrayList<>();
|
||||
|
||||
private boolean strict = true;
|
||||
|
||||
private FieldSetFactory fieldSetFactory = new DefaultFieldSetFactory();
|
||||
|
||||
public FixedLengthBuilder(FlatFileItemReaderBuilder<T> parent) {
|
||||
protected FixedLengthBuilder(FlatFileItemReaderBuilder<T> parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public FixedLengthBuilder<T> ranges(Range[] ranges) {
|
||||
/**
|
||||
* The column ranges for each field
|
||||
*
|
||||
* @param ranges column ranges
|
||||
* @return This instance for chaining
|
||||
* @see FixedLengthTokenizer#setColumns(Range[])
|
||||
*/
|
||||
public FixedLengthBuilder<T> columns(Range[] ranges) {
|
||||
this.ranges.addAll(Arrays.asList(ranges));
|
||||
return this;
|
||||
}
|
||||
|
||||
public FixedLengthBuilder<T> addRange(Range range) {
|
||||
/**
|
||||
* Add a column range to the existing list
|
||||
*
|
||||
* @param range a new column range
|
||||
* @return This instance for chaining
|
||||
* @see FixedLengthTokenizer#setColumns(Range[])
|
||||
*/
|
||||
public FixedLengthBuilder<T> addColumns(Range range) {
|
||||
this.ranges.add(range);
|
||||
return this;
|
||||
}
|
||||
|
||||
public FixedLengthBuilder<T> addRange(Range range, int index) {
|
||||
/**
|
||||
* Insert a column range to the existing list
|
||||
*
|
||||
* @param range a new column range
|
||||
* @param index index to add it at
|
||||
* @return This instance for chaining
|
||||
* @see FixedLengthTokenizer#setColumns(Range[])
|
||||
*/
|
||||
public FixedLengthBuilder<T> addColumns(Range range, int index) {
|
||||
this.ranges.add(index, range);
|
||||
return this;
|
||||
}
|
||||
|
||||
public FixedLengthBuilder<T> maxRange(int maxRange) {
|
||||
this.maxRange = maxRange;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The names of the fields to be parsed from the file. Required.
|
||||
*
|
||||
* @param names names of fields
|
||||
* @return The parent builder
|
||||
* @see FixedLengthTokenizer#setNames(String[])
|
||||
*/
|
||||
public FlatFileItemReaderBuilder<T> names(String [] names) {
|
||||
this.names.addAll(Arrays.asList(names));
|
||||
return this.parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Boolean indicating if the number of tokens in a line must match the number of
|
||||
* fields (ranges) configured. Defaults to true.
|
||||
*
|
||||
* @param strict defaults to true
|
||||
* @return This instance for chaining
|
||||
* @see FixedLengthTokenizer#setStrict(boolean)
|
||||
*/
|
||||
public FixedLengthBuilder<T> strict(boolean strict) {
|
||||
this.strict = strict;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FixedLengthBuilder<T> fieldSetFactory(FieldSetFactory factory) {
|
||||
this.fieldSetFactory = factory;
|
||||
/**
|
||||
* A factory for creating the resulting
|
||||
* {@link org.springframework.batch.item.file.transform.FieldSet}. Defaults to
|
||||
* {@link DefaultFieldSetFactory}.
|
||||
* @param fieldSetFactory Factory for creating {@link org.springframework.batch.item.file.transform.FieldSet}
|
||||
* @return The instance of the builder for chaining.
|
||||
* @see FixedLengthTokenizer#setFieldSetFactory(FieldSetFactory)
|
||||
*/
|
||||
public FixedLengthBuilder<T> fieldSetFactory(FieldSetFactory fieldSetFactory) {
|
||||
this.fieldSetFactory = fieldSetFactory;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link FixedLengthTokenizer}
|
||||
*
|
||||
* @return a {@link FixedLengthTokenizer}
|
||||
*/
|
||||
public FixedLengthTokenizer build() {
|
||||
Assert.notNull(this.fieldSetFactory, "A FieldSetFactory is required.");
|
||||
Assert.notEmpty(this.names, "A list of field names is required.");
|
||||
Assert.notEmpty(this.ranges, "A list of column ranges is required.");
|
||||
|
||||
FixedLengthTokenizer tokenizer = new FixedLengthTokenizer();
|
||||
|
||||
tokenizer.setNames(this.names.toArray(new String[this.names.size()]));
|
||||
|
||||
Reference in New Issue
Block a user