diff --git a/common/source/java/ch/systemsx/cisd/common/parser/DefaultParser.java b/common/source/java/ch/systemsx/cisd/common/parser/DefaultParser.java index e2a7fc8f76616c9acbafc3b2f1fa0c456990c8b4..7b18b9cef3745774b95723dbfdca223d1962f810 100644 --- a/common/source/java/ch/systemsx/cisd/common/parser/DefaultParser.java +++ b/common/source/java/ch/systemsx/cisd/common/parser/DefaultParser.java @@ -58,23 +58,6 @@ public class DefaultParser<E> implements IParser<E> return factory.createObject(tokens); } - /** - * Parses given <code>line</code> into an element. - * <p> - * Uses <code>ILineTokenizer</code> to do its job. - * </p> - * - * @param lineNumber line number. - */ - private final String[] parseLine(final int lineNumber, final String line) - { - return lineTokenizer.tokenize(line); - } - - // - // Parser - // - public final List<E> parse(final Iterator<Line> lineIterator, final ILineFilter lineFilter, final int headerLength) throws ParsingException { @@ -89,12 +72,8 @@ public class DefaultParser<E> implements IParser<E> final int number = line.getNumber(); if (lineFilter.acceptLine(nextLine, number)) { - final String[] tokens = parseLine(number, nextLine); E object = null; - if (tokens.length != headerLength) - { - throw new ColumnSizeMismatchException(tokens, number, headerLength); - } + String[] tokens = parseLine(number, nextLine, headerLength); try { object = createObject(tokens); @@ -108,11 +87,30 @@ public class DefaultParser<E> implements IParser<E> lineTokenizer.destroy(); return elements; } - } public final void setObjectFactory(final IParserObjectFactory<E> factory) { this.factory = factory; } -} \ No newline at end of file + + private String[] parseLine(final int lineNumber, final String nextLine, final int headerLength) + { + String[] tokens = lineTokenizer.tokenize(nextLine); + if (tokens.length > headerLength) + { + throw new ColumnSizeMismatchException(tokens, lineNumber, headerLength); + } + if (tokens.length < headerLength) + { + String[] newTokens = new String[headerLength]; + System.arraycopy(tokens, 0, newTokens, 0, tokens.length); + for (int i = tokens.length; i < headerLength; i++) + { + newTokens[i] = ""; + } + tokens = newTokens; + } + return tokens; + } +} diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/parser/DefaultParserTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/parser/DefaultParserTest.java index 688145ca88375b8ae93888df2e8fa13b8451b6ae..4cb61a6bacb9d3a2d6e205cbaeb98cedfe89f5b8 100644 --- a/common/sourceTest/java/ch/systemsx/cisd/common/parser/DefaultParserTest.java +++ b/common/sourceTest/java/ch/systemsx/cisd/common/parser/DefaultParserTest.java @@ -37,6 +37,16 @@ public final class DefaultParserTest "Charles\tDarwin\tHumboldt Ave. 1865\t4242 Somewhere", "Albert\tEinstein\tNewton Road 1905\t4711 Princton"); + private final static List<String> textWithTab = + Arrays.asList("", "# This is a comment", "firstName\tlastName\taddress\tcity", + "Charles\tDarwin\tHumboldt Ave. 1865\t4242 Somewhere", + "Albert\t\tNewton Road 1905\t"); + + private final static List<String> textWithMissingLastCells = + Arrays.asList("", "# This is a comment", "firstName\tlastName\taddress\tcity", + "\tDarwin\tHumboldt Ave. 1865", + "Albert\tEinstein"); + private final static int HEADER_LENGTH = 4; private final static IParser<String[]> createParser() @@ -51,7 +61,7 @@ public final class DefaultParserTest { final IParser<String[]> parser = createParser(); final List<String[]> result = - parser.parse(createLineIterator(), new HeaderLineFilter(), HEADER_LENGTH); + parser.parse(createLineIterator(text), new HeaderLineFilter(), HEADER_LENGTH); assertEquals(3, result.size()); assertEquals(result.get(0)[0], "firstName"); assertEquals(result.get(1)[1], "Darwin"); @@ -64,11 +74,41 @@ public final class DefaultParserTest { final IParser<String[]> parser = createParser(); final List<String[]> result = - parser.parse(createLineIterator(), new HeaderLineFilter(3), HEADER_LENGTH); + parser.parse(createLineIterator(text), new HeaderLineFilter(3), HEADER_LENGTH); assertEquals(2, result.size()); assertEquals(result.get(0)[0], "Charles"); assertEquals(result.get(1)[1], "Einstein"); } + + @Test + public final void testParseFileWithTabs() + { + final IParser<String[]> parser = createParser(); + final List<String[]> result = + parser.parse(createLineIterator(textWithTab), new HeaderLineFilter(), HEADER_LENGTH); + assertEquals(3, result.size()); + assertEquals("Albert", result.get(2)[0]); + assertEquals("", result.get(2)[1]); + assertEquals("Newton Road 1905", result.get(2)[2]); + assertEquals("", result.get(2)[3]); + } + + @Test + public final void testParseFileWithMissingLastCells() + { + final IParser<String[]> parser = createParser(); + final List<String[]> result = + parser.parse(createLineIterator(textWithMissingLastCells), new HeaderLineFilter(), HEADER_LENGTH); + assertEquals(3, result.size()); + assertEquals("", result.get(1)[0]); + assertEquals("Darwin", result.get(1)[1]); + assertEquals("Humboldt Ave. 1865", result.get(1)[2]); + assertEquals("", result.get(1)[3]); + assertEquals("Albert", result.get(2)[0]); + assertEquals("Einstein", result.get(2)[1]); + assertEquals("", result.get(2)[2]); + assertEquals("", result.get(2)[3]); + } @Test public final void testParseWithColumnSizeMismatching() @@ -76,7 +116,7 @@ public final class DefaultParserTest final IParser<String[]> parser = createParser(); try { - parser.parse(createLineIterator(), new HeaderLineFilter(3), HEADER_LENGTH + 1); + parser.parse(createLineIterator(text), new HeaderLineFilter(3), HEADER_LENGTH + 1); } catch (final ColumnSizeMismatchException ex) { assertEquals( @@ -104,7 +144,7 @@ public final class DefaultParserTest parser.setObjectFactory(IParserObjectFactory.STRING_ARRAY_OBJECT_FACTORY); try { - parser.parse(createLineIterator(), new HeaderLineFilter(2), HEADER_LENGTH); + parser.parse(createLineIterator(text), new HeaderLineFilter(2), HEADER_LENGTH); fail(String.format("'%s' exception expected.", ParsingException.class)); } catch (final ParsingException ex) { @@ -115,11 +155,11 @@ public final class DefaultParserTest } } - private Iterator<Line> createLineIterator() + private Iterator<Line> createLineIterator(final List<String> lines) { return new Iterator<Line>() { - private final Iterator<String> iterator = text.iterator(); + private final Iterator<String> iterator = lines.iterator(); private int lineNumber;