/*
* Copyright 2016 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.file.builder;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.separator.DefaultRecordSeparatorPolicy;
import org.springframework.batch.item.file.transform.DefaultFieldSet;
import org.springframework.batch.item.file.transform.FieldSet;
import org.springframework.batch.item.file.transform.FieldSetFactory;
import org.springframework.batch.item.file.transform.Range;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
/**
* @author Michael Minella
*/
public class FlatFileItemReaderBuilderTests {
@Test
public void testSimpleFixedLength() throws Exception {
FlatFileItemReader<Foo> reader = new FlatFileItemReaderBuilder<Foo>()
.name("fooReader")
.resource(getResource("1 2 3"))
.fixedLength()
.columns(new Range[] {new Range(1, 3), new Range(4, 6), new Range(7)})
.names(new String[] {"first", "second", "third"})
.targetType(Foo.class)
.build();
reader.open(new ExecutionContext());
Foo item = reader.read();
assertEquals(1, item.getFirst());
assertEquals(2, item.getSecond());
assertEquals("3", item.getThird());
assertNull(reader.read());
}
@Test
public void testSimpleDelimited() throws Exception {
FlatFileItemReader<Foo> reader = new FlatFileItemReaderBuilder<Foo>()
.name("fooReader")
.resource(getResource("1,2,3"))
.delimited()
.names(new String[] {"first", "second", "third"})
.targetType(Foo.class)
.build();
reader.open(new ExecutionContext());
Foo item = reader.read();
assertEquals(1, item.getFirst());
assertEquals(2, item.getSecond());
assertEquals("3", item.getThird());
assertNull(reader.read());
}
@Test
public void testAdvancedDelimited() throws Exception {
final List<String> skippedLines = new ArrayList<>();
FlatFileItemReader<Foo> reader = new FlatFileItemReaderBuilder<Foo>()
.name("fooReader")
.resource(getResource("1,2,3\n4,5,$1,2,3$\n@this is a comment\n6,7, 8"))
.delimited()
.quoteCharacter('$')
.names(new String[] {"first", "second", "third"})
.targetType(Foo.class)
.linesToSkip(1)
.skippedLinesCallback(skippedLines::add)
.addComment("@")
.build();
ExecutionContext executionContext = new ExecutionContext();
reader.open(executionContext);
Foo item = reader.read();
assertEquals(4, item.getFirst());
assertEquals(5, item.getSecond());
assertEquals("1,2,3", item.getThird());
item = reader.read();
assertEquals(6, item.getFirst());
assertEquals(7, item.getSecond());
assertEquals("8", item.getThird());
reader.update(executionContext);
assertNull(reader.read());
assertEquals("1,2,3", skippedLines.get(0));
assertEquals(1, skippedLines.size());
assertEquals(1, executionContext.size());
}
@Test
public void testAdvancedFixedLength() throws Exception {
FlatFileItemReader<Foo> reader = new FlatFileItemReaderBuilder<Foo>()
.name("fooReader")
.resource(getResource("1 2%\n 3\n4 5%\n 6\n@this is a comment\n7 8%\n 9\n"))
.fixedLength()
.columns(new Range[] {new Range(1, 2), new Range(3, 5), new Range(6)})
.names(new String[] {"first", "second", "third"})
.targetType(Foo.class)
.recordSeparatorPolicy(new DefaultRecordSeparatorPolicy("\"", "%"))
.maxItemCount(2)
.saveState(false)
.build();
ExecutionContext executionContext = new ExecutionContext();
reader.open(executionContext);
Foo item = reader.read();
assertEquals(1, item.getFirst());
assertEquals(2, item.getSecond());
assertEquals("3", item.getThird());
item = reader.read();
assertEquals(4, item.getFirst());
assertEquals(5, item.getSecond());
assertEquals("6", item.getThird());
reader.update(executionContext);
assertNull(reader.read());
assertEquals(0, executionContext.size());
}
@Test
public void testStrict() throws Exception {
FlatFileItemReader<Foo> reader = new FlatFileItemReaderBuilder<Foo>()
.name("fooReader")
.resource(new FileSystemResource("this/file/does/not/exist"))
.delimited()
.names(new String[] {"first", "second", "third"})
.targetType(Foo.class)
.strict(false)
.build();
reader.open(new ExecutionContext());
assertNull(reader.read());
}
@Test
public void testCustomLineTokenizerFieldSetMapper() throws Exception {
FlatFileItemReader<Foo> reader = new FlatFileItemReaderBuilder<Foo>()
.name("fooReader")
.resource(getResource("|1|&|2|&| 3|\n|4|&|5|&|foo|"))
.lineTokenizer(line -> new DefaultFieldSet(line.split("&")))
.fieldSetMapper(fieldSet -> {
Foo item = new Foo();
item.setFirst(Integer.valueOf(fieldSet.readString(0).replaceAll("\\|", "")));
item.setSecond(Integer.valueOf(fieldSet.readString(1).replaceAll("\\|", "")));
item.setThird(fieldSet.readString(2).replaceAll("\\|", ""));
return item;
})
.build();
reader.open(new ExecutionContext());
Foo item = reader.read();
assertEquals(1, item.getFirst());
assertEquals(2, item.getSecond());
assertEquals(" 3", item.getThird());
item = reader.read();
assertEquals(4, item.getFirst());
assertEquals(5, item.getSecond());
assertEquals("foo", item.getThird());
assertNull(reader.read());
}
@Test
public void testComments() throws Exception {
FlatFileItemReader<Foo> reader = new FlatFileItemReaderBuilder<Foo>()
.name("fooReader")
.resource(getResource("1,2,3\n@this is a comment\n+so is this\n4,5,6"))
.comments(new String[] {"@", "+"})
.delimited()
.names(new String[] {"first", "second", "third"})
.targetType(Foo.class)
.build();
reader.open(new ExecutionContext());
Foo item = reader.read();
assertEquals(1, item.getFirst());
assertEquals(2, item.getSecond());
assertEquals("3", item.getThird());
item = reader.read();
assertEquals(4, item.getFirst());
assertEquals(5, item.getSecond());
assertEquals("6", item.getThird());
assertNull(reader.read());
}
@Test
public void testPrototypeBean() throws Exception {
BeanFactory factory = new AnnotationConfigApplicationContext(Beans.class);
FlatFileItemReader<Foo> reader = new FlatFileItemReaderBuilder<Foo>()
.name("fooReader")
.resource(getResource("1,2,3"))
.delimited()
.names(new String[] {"first", "second", "third"})
.prototypeBeanName("foo")
.beanFactory(factory)
.build();
reader.open(new ExecutionContext());
Foo item = reader.read();
assertEquals(1, item.getFirst());
assertEquals(2, item.getSecond());
assertEquals("3", item.getThird());
assertNull(reader.read());
}
@Test
public void testBeanWrapperFieldSetMapperStrict() throws Exception {
FlatFileItemReader<Foo> reader = new FlatFileItemReaderBuilder<Foo>()
.name("fooReader")
.resource(getResource("1,2,3"))
.delimited()
.names(new String[] {"setFirst", "setSecond", "setThird"})
.targetType(Foo.class)
.beanMapperStrict(true)
.build();
reader.open(new ExecutionContext());
Foo item = reader.read();
assertEquals(1, item.getFirst());
assertEquals(2, item.getSecond());
assertEquals("3", item.getThird());
assertNull(reader.read());
}
@Test
public void testDelimitedIncludedFields() throws Exception {
FlatFileItemReader<Foo> reader = new FlatFileItemReaderBuilder<Foo>()
.name("fooReader")
.resource(getResource("1,2,3"))
.delimited()
.includedFields(new Integer[] {new Integer(0), new Integer(2)})
.addIncludedField(1)
.names(new String[] {"first", "second", "third"})
.targetType(Foo.class)
.build();
reader.open(new ExecutionContext());
Foo item = reader.read();
assertEquals(1, item.getFirst());
assertEquals(2, item.getSecond());
assertEquals("3", item.getThird());
assertNull(reader.read());
}
@Test
public void testDelimitedFieldSetFactory() throws Exception {
String[] names = {"first", "second", "third"};
FlatFileItemReader<Foo> reader = new FlatFileItemReaderBuilder<Foo>()
.name("fooReader")
.resource(getResource("1,2,3"))
.delimited()
.fieldSetFactory(new FieldSetFactory() {
private FieldSet fieldSet = new DefaultFieldSet(new String[] {"1", "3", "foo"}, names);
@Override
public FieldSet create(String[] values, String[] names) {
return fieldSet;
}
@Override
public FieldSet create(String[] values) {
return fieldSet;
}
})
.names(names)
.targetType(Foo.class)
.build();
reader.open(new ExecutionContext());
Foo item = reader.read();
assertEquals(1, item.getFirst());
assertEquals(3, item.getSecond());
assertEquals("foo", item.getThird());
assertNull(reader.read());
}
@Test
public void testFixedLengthFieldSetFactory() throws Exception {
String[] names = {"first", "second", "third"};
FlatFileItemReader<Foo> reader = new FlatFileItemReaderBuilder<Foo>()
.name("fooReader")
.resource(getResource("1 2 3"))
.fixedLength()
.fieldSetFactory(new FieldSetFactory() {
private FieldSet fieldSet = new DefaultFieldSet(new String[] {"1", "3", "foo"}, names);
@Override
public FieldSet create(String[] values, String[] names) {
return fieldSet;
}
@Override
public FieldSet create(String[] values) {
return fieldSet;
}
})
.columns(new Range[] {new Range(1, 3), new Range(4, 6), new Range(7)})
.names(new String[] {"first", "second", "third"})
.targetType(Foo.class)
.build();
reader.open(new ExecutionContext());
Foo item = reader.read();
assertEquals(1, item.getFirst());
assertEquals(3, item.getSecond());
assertEquals("foo", item.getThird());
assertNull(reader.read());
}
private Resource getResource(String contents) {
return new ByteArrayResource(contents.getBytes());
}
public static class Foo {
private int first;
private int second;
private String third;
public int getFirst() {
return first;
}
public void setFirst(int first) {
this.first = first;
}
public int getSecond() {
return second;
}
public void setSecond(int second) {
this.second = second;
}
public String getThird() {
return third;
}
public void setThird(String third) {
this.third = third;
}
}
@Configuration
public static class Beans {
@Bean
@Scope("prototype")
public Foo foo() {
return new Foo();
}
}
}