RESOLVED - issue BATCH-1429: Allow DelimitedLineTokenizer to handle malformed file/lines gracefully.
This commit is contained in:
@@ -32,8 +32,35 @@ public abstract class AbstractLineTokenizer implements LineTokenizer {
|
||||
|
||||
protected String[] names = new String[0];
|
||||
|
||||
private boolean strict = true;
|
||||
|
||||
private String emptyToken = "";
|
||||
|
||||
private FieldSetFactory fieldSetFactory = new DefaultFieldSetFactory();
|
||||
|
||||
/**
|
||||
* Public setter for the strict flag. If true (the default) then number of
|
||||
* tokens in line must match the number of tokens defined
|
||||
* (by {@link Range}, columns, etc.) in {@link LineTokenizer}.
|
||||
* If false then lines with less tokens will be tolerated and padded with
|
||||
* empty columns, and lines with more tokens will
|
||||
* simply be truncated.
|
||||
*
|
||||
* @param strict the strict flag to set
|
||||
*/
|
||||
public void setStrict(boolean strict) {
|
||||
this.strict = strict;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides access to the strict flag for subclasses if needed.
|
||||
*
|
||||
* @return the strict flag value
|
||||
*/
|
||||
protected boolean isStrict() {
|
||||
return strict;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory for {@link FieldSet} instances. Can be injected by clients to
|
||||
* customize the default number and date formats.
|
||||
@@ -80,7 +107,12 @@ public abstract class AbstractLineTokenizer implements LineTokenizer {
|
||||
}
|
||||
|
||||
List<String> tokens = new ArrayList<String>(doTokenize(line));
|
||||
|
||||
|
||||
// if names are set and strict flag is false
|
||||
if ( ( names.length != 0 ) && ( ! strict ) ) {
|
||||
adjustTokenCountIfNecessary( tokens );
|
||||
}
|
||||
|
||||
String[] values = (String[]) tokens.toArray(new String[tokens.size()]);
|
||||
|
||||
if (names.length == 0) {
|
||||
@@ -93,5 +125,36 @@ public abstract class AbstractLineTokenizer implements LineTokenizer {
|
||||
}
|
||||
|
||||
protected abstract List<String> doTokenize(String line);
|
||||
|
||||
/**
|
||||
* Adds empty tokens or truncates existing token list to match expected
|
||||
* (configured) number of tokens in {@link LineTokenizer}.
|
||||
*
|
||||
* @param tokens - list of tokens
|
||||
*/
|
||||
private void adjustTokenCountIfNecessary( List<String> tokens ) {
|
||||
|
||||
int nameLength = names.length;
|
||||
int tokensSize = tokens.size();
|
||||
|
||||
// if the number of tokens is not what expected
|
||||
if ( nameLength != tokensSize ) {
|
||||
|
||||
if ( nameLength > tokensSize ) {
|
||||
|
||||
// add empty tokens until the token list size matches
|
||||
// the expected number of tokens
|
||||
for ( int i = 0; i < ( nameLength - tokensSize ); i++ ) {
|
||||
tokens.add( emptyToken );
|
||||
}
|
||||
|
||||
} else {
|
||||
// truncate token list to match the number of expected tokens
|
||||
for ( int i = tokensSize - 1; i >= nameLength; i-- ) {
|
||||
tokens.remove(i);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,22 +37,6 @@ public class FixedLengthTokenizer extends AbstractLineTokenizer {
|
||||
|
||||
boolean open = false;
|
||||
|
||||
private boolean strict = true;
|
||||
|
||||
/**
|
||||
* Public setter for the strict flag. If true (the default) then lines must
|
||||
* be precisely the length specified by the columns. If false then shorter
|
||||
* lines will be tolerated and padded with empty columns, and longer strings
|
||||
* will simply be truncated.
|
||||
*
|
||||
* @see #setColumns(Range[])
|
||||
*
|
||||
* @param strict the strict to set
|
||||
*/
|
||||
public void setStrict(boolean strict) {
|
||||
this.strict = strict;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the column ranges. Used in conjunction with the
|
||||
* {@link RangeArrayPropertyEditor} this property can be set in the form of
|
||||
@@ -118,11 +102,11 @@ public class FixedLengthTokenizer extends AbstractLineTokenizer {
|
||||
|
||||
lineLength = line.length();
|
||||
|
||||
if (lineLength < maxRange && strict) {
|
||||
if (lineLength < maxRange && isStrict()) {
|
||||
throw new IncorrectLineLengthException("Line is shorter than max range " + maxRange, maxRange, lineLength);
|
||||
}
|
||||
|
||||
if (!open && lineLength > maxRange && strict) {
|
||||
if (!open && lineLength > maxRange && isStrict()) {
|
||||
throw new IncorrectLineLengthException("Line is longer than max range " + maxRange, maxRange, lineLength);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user