Create a kinda of CompositeLineMapper
where you store a different LineMapper
implementation specific for every type of class you need to manage.
This CompositeLineMapper
, for every line in your file, will look-ahead discriminator column and dispatch to right LineMapper
implementation.
I can't give you code because I'm not using SB atm,so I left to you the implementation.
EDIT: Adding an example of how to classify items
Here is a composite line mapper based on a Classifier
:
import org.springframework.batch.item.file.LineMapper;
import org.springframework.classify.Classifier;
public class ClassifierCompositeLineMapper implements LineMapper<Object> {
private Classifier<String, LineMapper<?>> classifier;
public ClassifierCompositeLineMapper(Classifier<String, LineMapper<?>> classifier) {
this.classifier = classifier;
}
@Override
public Object mapLine(String line, int lineNumber) throws Exception {
return classifier.classify(line).mapLine(line, lineNumber);
}
}
And here is how to use it:
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.springframework.batch.item.file.LineMapper;
import org.springframework.batch.item.file.mapping.PassThroughLineMapper;
import org.springframework.classify.Classifier;
public class ClassifierCompositeLineMapperTest {
private ClassifierCompositeLineMapper compositeLineMapper;
@Before
public void setUp() {
Classifier<String, LineMapper<?>> classifier = new Classifier<String, LineMapper<? extends Object>>() {
@Override
public LineMapper<?> classify(String classifiable) {
if (classifiable.contains("Class1")) {
return new Class1LineMapper();
}
if (classifiable.contains("Class2")) {
return new Class2LineMapper();
}
return new PassThroughLineMapper(); // or any other default line mapper
}
};
compositeLineMapper = new ClassifierCompositeLineMapper(classifier);
}
@Test
public void mapLine() throws Exception {
Object line1 = compositeLineMapper.mapLine("00|0|56||Class1|25|001|0", 1);
Assert.assertTrue(line1 instanceof Class1);
Object line2 = compositeLineMapper.mapLine("02|23|11||Class2|65|ENG|ENG|", 2);
Assert.assertTrue(line2 instanceof Class2);
}
static class Class1 {}
static class Class1LineMapper implements LineMapper<Class1> {
@Override
public Class1 mapLine(String line, int lineNumber) throws Exception {
return new Class1(); // TODO mapping logic
}
}
static class Class2 {}
static class Class2LineMapper implements LineMapper<Class2> {
@Override
public Class2 mapLine(String line, int lineNumber) throws Exception {
return new Class2(); // TODO mapping logic
}
}
}
PatternMatchingCompositeLineMapper
which can be used here too with patterns like*Class1*
and*Class2*
, etc. But I edited the answer by @Luca Basso Ricci with an example because his answer is correct and he deserves the credit ! – Mahmoud Ben Hassine