Skip to content
This repository has been archived by the owner on Jan 22, 2019. It is now read-only.

Commit

Permalink
Fix minor issues wry #79
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed May 21, 2015
1 parent 59a3639 commit 6c74cb4
Show file tree
Hide file tree
Showing 13 changed files with 121 additions and 33 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ abstractions.

<properties>
<jackson.version.annotations>2.6.0-rc1</jackson.version.annotations>
<jackson.version.core>2.6.0-rc1</jackson.version.core>
<jackson.version.core>2.6.0-rc2-SNAPSHOT</jackson.version.core>
<!-- Generate PackageVersion.java into this directory. -->
<packageVersion.dir>com/fasterxml/jackson/dataformat/csv</packageVersion.dir>
<packageVersion.package>${project.groupId}.csv</packageVersion.package>
Expand Down
33 changes: 29 additions & 4 deletions src/main/java/com/fasterxml/jackson/dataformat/csv/CsvParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.fasterxml.jackson.core.json.DupDetector;
import com.fasterxml.jackson.core.json.JsonReadContext;
import com.fasterxml.jackson.core.util.ByteArrayBuilder;

import com.fasterxml.jackson.dataformat.csv.impl.CsvDecoder;
import com.fasterxml.jackson.dataformat.csv.impl.CsvIOContext;
import com.fasterxml.jackson.dataformat.csv.impl.TextBuffer;
Expand Down Expand Up @@ -138,14 +139,23 @@ private Feature(boolean defaultState) {
*/
protected final static int STATE_IN_ARRAY = 5;

/**
* State in which we have encountered more column values than there should be,
* and need to basically skip extra values if callers tries to advance parser
* state.
*
* @since 2.6
*/
protected final static int STATE_SKIP_EXTRA_COLUMNS = 6;

/**
* State in which end marker is returned; either
* null (if no array wrapping), or
* {@link JsonToken#END_ARRAY} for wrapping.
* This step will loop, returning series of nulls
* if {@link #nextToken} is called multiple times.
*/
protected final static int STATE_DOC_END = 6;
protected final static int STATE_DOC_END = 7;

/*
/**********************************************************************
Expand Down Expand Up @@ -476,6 +486,19 @@ public JsonToken nextToken() throws IOException
return (_currToken = _handleUnnamedValue());
case STATE_IN_ARRAY:
return (_currToken = _handleArrayValue());
case STATE_SKIP_EXTRA_COLUMNS:
// Need to just skip whatever remains
_state = STATE_RECORD_START;
while (_reader.nextString() != null) { }

// But once we hit the end of the logical line, get out
// NOTE: seems like we should always be within Object, but let's be conservative
// and check just in case
_parsingContext = _parsingContext.getParent();
_state = _reader.startNewLine() ? STATE_RECORD_START : STATE_DOC_END;
return (_currToken = _parsingContext.inArray()
? JsonToken.END_ARRAY : JsonToken.END_OBJECT);

case STATE_DOC_END:
_reader.close();
if (_parsingContext.inRoot()) {
Expand Down Expand Up @@ -645,7 +668,9 @@ protected JsonToken _handleNextEntry() throws IOException
return _handleNextEntryExpectEOL();
}
}
_reportError("Too many entries: expected at most "+_columnCount+" (value #"+_columnCount+" ("+next.length()+" chars) \""+next+"\")");
// 21-May-2015, tatu: Need to enter recovery mode, to skip remainder of the line
_state = STATE_SKIP_EXTRA_COLUMNS;
_reportCsvError("Too many entries: expected at most "+_columnCount+" (value #"+_columnCount+" ("+next.length()+" chars) \""+next+"\")");
}
_currentName = _schema.columnName(_columnIndex);
return JsonToken.FIELD_NAME;
Expand All @@ -656,7 +681,7 @@ protected JsonToken _handleNextEntryExpectEOL() throws IOException
String next = _reader.nextString();

if (next != null) { // should end of record or input
_reportError("Too many entries: expected at most "+_columnCount+" (value #"+_columnCount+" ("+next.length()+" chars) \""+next+"\")");
_reportCsvError("Too many entries: expected at most "+_columnCount+" (value #"+_columnCount+" ("+next.length()+" chars) \""+next+"\")");
}
_parsingContext = _parsingContext.getParent();
if (!_reader.startNewLine()) {
Expand Down Expand Up @@ -923,7 +948,7 @@ public void _reportCsvError(String msg) throws JsonParseException {
public void _reportUnexpectedCsvChar(int ch, String msg) throws JsonParseException {
super._reportUnexpectedChar(ch, msg);
}

/*
/**********************************************************************
/* Internal methods
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,12 @@ protected int _skipCommentLines() throws IOException
}
return -1; // end of input
}


/**
* Method called to blindly skip a single line of content, without considering
* aspects like quoting or escaping. Used currently simply to skip the first
* line of input document, if instructed to do so.
*/
public boolean skipLine() throws IOException
{
if (_pendingLF != 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public void testWithoutComments() throws Exception

// First, with comments disabled:

MappingIterator<String[]> it = mapper.reader(String[].class)
MappingIterator<String[]> it = mapper.readerFor(String[].class)
.with(mapper.schema().withoutComments()).readValues(CSV_WITH_COMMENTS);

row = it.nextValue();
Expand Down Expand Up @@ -61,7 +61,7 @@ public void testSimpleComments() throws Exception
// should not be needed but seems to be...
mapper.enable(CsvParser.Feature.WRAP_AS_ARRAY);

MappingIterator<String[]> it = mapper.reader(String[].class)
MappingIterator<String[]> it = mapper.readerFor(String[].class)
.with(mapper.schema().withComments()).readValues(CSV_WITH_COMMENTS);

// first row the same
Expand All @@ -88,7 +88,7 @@ public void testLeadingComments() throws Exception
// should not be needed but seems to be...
mapper.enable(CsvParser.Feature.WRAP_AS_ARRAY);

MappingIterator<String[]> it = mapper.reader(String[].class)
MappingIterator<String[]> it = mapper.readerFor(String[].class)
.with(mapper.schema().withComments()).readValues("# first\n#second\n1,2\n");

// first row the same
Expand All @@ -105,7 +105,7 @@ public void testLeadingComments() throws Exception
public void testCommentsWithHeaderRow() throws Exception
{
CsvMapper mapper = mapperForCsv();
MappingIterator<Map<String,String>> it = mapper.reader(Map.class)
MappingIterator<Map<String,String>> it = mapper.readerFor(Map.class)
.with(mapper.schema().withComments().withHeader())
.readValues("# headers:\nid,value\n# values:\nab#c,#13\n");

Expand All @@ -128,7 +128,7 @@ public void testSimpleCommentsWithDefaultProp() throws Exception
mapper.enable(CsvParser.Feature.WRAP_AS_ARRAY);
final String CSV = "# comment!\na,b\n";

MappingIterator<String[]> it = mapper.reader(String[].class)
MappingIterator<String[]> it = mapper.readerFor(String[].class)
.readValues(CSV);
String[] row = it.nextValue();
// assertEquals(2, row.length);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import java.util.*;

import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.MappingIterator;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.dataformat.csv.*;
Expand All @@ -12,7 +14,7 @@
* Tests for verifying behavior of enclosing input stream as
* a logical array.
*/
public class TestParserSequences extends ModuleTestBase
public class ReadSequencesTest extends ModuleTestBase
{
@JsonPropertyOrder({"x", "y"})
protected static class Entry {
Expand Down Expand Up @@ -65,6 +67,62 @@ public void testAsSequence() throws Exception
it.close();
}

public void testSequenceRecovery() throws Exception
{
CsvMapper mapper = mapperForCsv();
mapper.disable(CsvParser.Feature.WRAP_AS_ARRAY);
MappingIterator<Entry> it = mapper.readerWithSchemaFor(Entry.class).readValues(
"1,2\n3,invalid\n5,6\n1,2,3,5\n13,-4\ngarbage\n");
Entry entry;

assertTrue(it.hasNext());
assertNotNull(entry = it.nextValue());
assertEquals(1, entry.x);
assertEquals(2, entry.y);
assertTrue(it.hasNext());

// second row, invalid:
try {
it.nextValue();
fail("Shouldn't have passed");
} catch (JsonMappingException e) {
verifyException(e, "'invalid': not a valid");
}

// but third is fine again
assertNotNull(entry = it.nextValue());
assertEquals(5, entry.x);
assertEquals(6, entry.y);

// fourth not
assertTrue(it.hasNext());
try {
it.nextValue();
fail("Shouldn't have passed");
} catch (JsonProcessingException e) {
// !!! TODO, maybe: Would be nicer to get a JsonMappingException?
verifyException(e, "Too many entries");
}

// fifth ok
assertTrue(it.hasNext());
assertNotNull(entry = it.nextValue());
assertEquals(13, entry.x);
assertEquals(-4, entry.y);

// and sixth busted again
assertTrue(it.hasNext());
try {
it.nextValue();
fail("Shouldn't have passed");
} catch (JsonMappingException e) {
verifyException(e, "String value 'garbage'");
}
assertFalse(it.hasNext());
it.close();
}


// Test using sequence of entries wrapped in a logical array.
public void testAsWrappedArray() throws Exception
{
Expand Down Expand Up @@ -97,7 +155,7 @@ public void testLongerUnwrapped() throws Exception
final int EXPECTED_BYTES = 97640;
assertEquals(EXPECTED_BYTES, bytes.length);

MappingIterator<Entry> it = mapper.reader(Entry.class).with(schema).readValues(bytes, 0, bytes.length);
MappingIterator<Entry> it = mapper.readerFor(Entry.class).with(schema).readValues(bytes, 0, bytes.length);
verifySame(it, entries);
bytes = null;

Expand All @@ -106,7 +164,7 @@ public void testLongerUnwrapped() throws Exception
assertEquals(EXPECTED_BYTES, text.length());
it.close();

it = mapper.reader(Entry.class).with(schema).readValues(text);
it = mapper.readerFor(Entry.class).with(schema).readValues(text);
verifySame(it, entries);
it.close();

Expand All @@ -118,7 +176,7 @@ public void testRawObjectArrays() throws Exception
CsvMapper mapper = new CsvMapper();
mapper.enable(CsvParser.Feature.WRAP_AS_ARRAY);
final String CSV = "a,b\nc,d\ne,f\n";
MappingIterator<Object[]> it = mapper.reader(Object[].class).readValues(CSV);
MappingIterator<Object[]> it = mapper.readerFor(Object[].class).readValues(CSV);

assertTrue(it.hasNext());
Object[] row = it.next();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public void testWithJsonView() throws Exception

// plus read back?
final String INPUT = "a,aa,b\n5,6,7\n";
Bean result = mapper.reader(Bean.class).with(schema).withView(ViewB.class).readValue(INPUT);
Bean result = mapper.readerFor(Bean.class).with(schema).withView(ViewB.class).readValue(INPUT);
assertEquals("5", result.a);
// due to filtering, ought to use default
assertEquals("2", result.aa);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ private void _testMapsWithLinefeeds(boolean useBytes) throws Exception
+"data41,\"data42 data42\r\ndata42\",data43\n";

CsvSchema cs = CsvSchema.emptySchema().withHeader();
ObjectReader or = mapper.reader(HashMap.class).with(cs);
ObjectReader or = mapper.readerFor(HashMap.class).with(cs);

MappingIterator<Map<String,String>> mi;

Expand Down Expand Up @@ -186,7 +186,7 @@ public void testEmptyHandlingForInteger() throws Exception
CsvSchema schema = mapper.typedSchemaFor(Point.class).withoutHeader();

// First: empty value, to be considered as null
Point result = mapper.reader(Point.class).with(schema).readValue(",,\n");
Point result = mapper.readerFor(Point.class).with(schema).readValue(",,\n");
assertEquals(0, result.x);
assertNull(result.y);
assertNull(result.z);
Expand All @@ -198,7 +198,7 @@ public void testStringNullHandlingForInteger() throws Exception
CsvSchema schema = mapper.typedSchemaFor(Point.class).withoutHeader();

// First: empty value, to be considered as null
Point result = mapper.reader(Point.class).with(schema).readValue("null,null,null\n");
Point result = mapper.readerFor(Point.class).with(schema).readValue("null,null,null\n");
assertEquals(0, result.x);
assertNull(result.y);
assertNull(result.z);
Expand All @@ -211,7 +211,7 @@ public void testIncorrectDups41() throws Exception
CsvSchema schema = CsvSchema.builder().addColumn("Col1").addColumn("Col2")
.addColumn("Col3").build();

MappingIterator<Object> iter = new CsvMapper().reader(Object.class)
MappingIterator<Object> iter = new CsvMapper().readerFor(Object.class)
.with(schema).readValues(INPUT);

Map<?,?> m = (Map<?,?>) iter.next();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public void testEscapesAtStartInUnquoted() throws Exception
final String id = "\\|abcdef"; // doubled for javac
final String desc = "Desc with\\\nlinefeed";
String input = id+"|"+desc+"\n";
Desc result = mapper.reader(schema).withType(Desc.class).readValue(input);
Desc result = mapper.reader(schema).forType(Desc.class).readValue(input);
assertEquals("|abcdef", result.id);
assertEquals("Desc with\nlinefeed", result.desc);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public void testUntypedAsSequence() throws Exception
final String CSV = "1,null\nfoobar\n7,true\n";
CsvParser cp = mapper.getFactory().createParser(CSV);

MappingIterator<Object[]> it = mapper.reader(Object[].class).readValues(cp);
MappingIterator<Object[]> it = mapper.readerFor(Object[].class).readValues(cp);

Object[] row;
assertTrue(it.hasNext());
Expand Down Expand Up @@ -63,7 +63,7 @@ public void testUntypedAsObjectArray() throws Exception
CsvMapper mapper = mapperForCsv();
mapper.enable(CsvParser.Feature.WRAP_AS_ARRAY);
// when wrapped as an array, we'll get array of Lists:
Object[] rows = mapper.reader(Object[].class).readValue(
Object[] rows = mapper.readerFor(Object[].class).readValue(
"1,\"xyz\"\n\ntrue,\n"
);
assertEquals(3, rows.length);
Expand Down Expand Up @@ -112,7 +112,7 @@ public void testUntypedWithHeaderAsMap() throws Exception
{
CsvMapper mapper = mapperForCsv();
MappingIterator<Map<String,String>> it = mapper
.reader(Map.class)
.readerFor(Map.class)
.with(mapper.schemaWithHeader())
.readValues("a,b\n1,2\n3,4\n");

Expand Down Expand Up @@ -145,7 +145,7 @@ public void testUntypedAsSequenceVarLengths() throws Exception
final String CSV = "1,2\n1,2,3,4\n";
CsvParser cp = mapper.getFactory().createParser(CSV);

MappingIterator<String[]> it = mapper.reader(String[].class).readValues(cp);
MappingIterator<String[]> it = mapper.readerFor(String[].class).readValues(cp);

Object[] row;
assertTrue(it.hasNext());
Expand Down Expand Up @@ -181,7 +181,7 @@ public void testDelimiterAtBufferBoundary() throws Exception
final String col2 = "H";

CsvParser cp = mapper.getFactory().createParser(col1 + " ," + col2 +"\n" + col2 + "," + col1 + "\n");
MappingIterator<Object[]> it = mapper.reader(Object[].class).readValues(cp);
MappingIterator<Object[]> it = mapper.readerFor(Object[].class).readValues(cp);

Object[] row;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public void testSimpleQuotes() throws Exception
CsvMapper mapper = mapperForCsv();
mapper.disable(CsvParser.Feature.WRAP_AS_ARRAY);
CsvSchema schema = CsvSchema.emptySchema().withHeader();
Entry entry = mapper.reader(Entry.class).with(schema).readValue(
Entry entry = mapper.readerFor(Entry.class).with(schema).readValue(
"name,age,\"cute\" \nLeo,4,true\n");
assertEquals("Leo", entry.name);
assertEquals(4, entry.age);
Expand All @@ -62,7 +62,7 @@ public void testSkipFirstDataLine() throws Exception
CsvMapper mapper = mapperForCsv();
mapper.disable(CsvParser.Feature.WRAP_AS_ARRAY);
CsvSchema schema = mapper.schemaFor(Entry.class).withSkipFirstDataRow(true);
MappingIterator<Entry> it = mapper.reader(Entry.class).with(schema).readValues(
MappingIterator<Entry> it = mapper.readerFor(Entry.class).with(schema).readValues(
"12354\n6,Lila,true");
Entry entry;

Expand Down Expand Up @@ -149,7 +149,7 @@ public void testInvalidMissingHeader() throws Exception
{
CsvMapper mapper = mapperForCsv();
try {
mapper.reader(Entry.class).with(CsvSchema.emptySchema().withHeader()).readValue(" \nJoseph,57,false");
mapper.readerFor(Entry.class).with(CsvSchema.emptySchema().withHeader()).readValue(" \nJoseph,57,false");
fail("Should have failed with exception");
} catch (Exception e) {
verifyException(e, "Empty header line");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public void testObjectMapper() throws IOException

assertEquals(EXP_CSV, mapper2.writerFor(MyPojo.class)
.with(SCHEMA_POJO).writeValueAsString(p).trim());
MyPojo p2 = mapper2.reader(MyPojo.class).with(SCHEMA_POJO).readValue(EXP_CSV);
MyPojo p2 = mapper2.readerFor(MyPojo.class).with(SCHEMA_POJO).readValue(EXP_CSV);
assertEquals(p.x, p2.x);
assertEquals(p.y, p2.y);

Expand Down
Loading

0 comments on commit 6c74cb4

Please sign in to comment.