Skip to content

Commit 357039b

Browse files
committed
Start piecing together changes for #97
1 parent 2bfeb11 commit 357039b

File tree

2 files changed

+237
-26
lines changed

2 files changed

+237
-26
lines changed

csv/src/main/java/com/fasterxml/jackson/dataformat/csv/CsvGenerator.java

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import com.fasterxml.jackson.core.json.JsonWriteContext;
1212
import com.fasterxml.jackson.core.io.IOContext;
1313
import com.fasterxml.jackson.dataformat.csv.impl.CsvEncoder;
14+
import com.fasterxml.jackson.dataformat.csv.impl.SimpleTokenWriteContext;
1415

1516
public class CsvGenerator extends GeneratorBase
1617
{
@@ -159,6 +160,14 @@ private Feature(boolean defaultState) {
159160
// note: can not be final since we may need to re-create it for new schema
160161
protected CsvEncoder _writer;
161162

163+
/**
164+
* Current context, in form we can use it (GeneratorBase has
165+
* untyped reference; left as null)
166+
*
167+
* @since 2.11
168+
*/
169+
protected SimpleTokenWriteContext _csvWriteContext;
170+
162171
protected CharacterEscapes _characterEscapes = null;
163172

164173
/*
@@ -216,7 +225,7 @@ private Feature(boolean defaultState) {
216225
*
217226
* @since 2.7
218227
*/
219-
protected JsonWriteContext _skipWithin;
228+
protected SimpleTokenWriteContext _skipWithin;
220229

221230
/*
222231
/**********************************************************
@@ -235,7 +244,7 @@ public CsvGenerator(IOContext ctxt, int jsonFeatures, int csvFeatures,
235244
_formatFeatures = csvFeatures;
236245
_schema = schema;
237246
_writer = new CsvEncoder(ctxt, csvFeatures, out, schema);
238-
247+
_csvWriteContext = SimpleTokenWriteContext.createRootContext(null);
239248
_writer.setOutputEscapes(CsvCharacterEscapes.fromCsvFeatures(csvFeatures).getEscapeCodesForAscii());
240249
}
241250

@@ -246,6 +255,7 @@ public CsvGenerator(IOContext ctxt, int jsonFeatures, int csvFeatures,
246255
_ioContext = ctxt;
247256
_formatFeatures = csvFeatures;
248257
_writer = csvWriter;
258+
_csvWriteContext = SimpleTokenWriteContext.createRootContext(null);
249259
}
250260

251261
/*
@@ -298,6 +308,11 @@ public int getOutputBuffered() {
298308
return _writer.getOutputBuffered();
299309
}
300310

311+
@Override
312+
public SimpleTokenWriteContext getOutputContext() {
313+
return _csvWriteContext;
314+
}
315+
301316
@Override
302317
public void setSchema(FormatSchema schema)
303318
{
@@ -380,7 +395,7 @@ public boolean canOmitFields() {
380395
@Override
381396
public final void writeFieldName(String name) throws IOException
382397
{
383-
if (_writeContext.writeFieldName(name) == JsonWriteContext.STATUS_EXPECT_VALUE) {
398+
if (!_csvWriteContext.writeFieldName(name)) {
384399
_reportError("Can not write a field name, expecting a value");
385400
}
386401
_writeFieldName(name);
@@ -390,7 +405,7 @@ public final void writeFieldName(String name) throws IOException
390405
public final void writeFieldName(SerializableString name) throws IOException
391406
{
392407
// Object is a value, need to verify it's allowed
393-
if (_writeContext.writeFieldName(name.getValue()) == JsonWriteContext.STATUS_EXPECT_VALUE) {
408+
if (!_csvWriteContext.writeFieldName(name.getValue())) {
394409
_reportError("Can not write a field name, expecting a value");
395410
}
396411
_writeFieldName(name.getValue());
@@ -492,10 +507,10 @@ public final void writeStartArray() throws IOException
492507
_verifyValueWrite("start an array");
493508
// Ok to create root-level array to contain Objects/Arrays, but
494509
// can not nest arrays in objects
495-
if (_writeContext.inObject()) {
510+
if (_csvWriteContext.inObject()) {
496511
if ((_skipWithin == null)
497512
&& _skipValue && isEnabled(JsonGenerator.Feature.IGNORE_UNKNOWN)) {
498-
_skipWithin = _writeContext;
513+
_skipWithin = _csvWriteContext;
499514
} else if (!_skipValue) {
500515
// First: column may have its own separator
501516
String sep;
@@ -525,20 +540,20 @@ && _skipValue && isEnabled(JsonGenerator.Feature.IGNORE_UNKNOWN)) {
525540
_reportError("CSV generator does not support nested Array values");
526541
}
527542
}
528-
_writeContext = _writeContext.createChildArrayContext();
543+
_csvWriteContext = _csvWriteContext.createChildArrayContext(null);
529544
// and that's about it, really
530545
}
531546

532547
@Override
533548
public final void writeEndArray() throws IOException
534549
{
535-
if (!_writeContext.inArray()) {
536-
_reportError("Current context not Array but "+_writeContext.typeDesc());
550+
if (!_csvWriteContext.inArray()) {
551+
_reportError("Current context not Array but "+_csvWriteContext.typeDesc());
537552
}
538-
_writeContext = _writeContext.getParent();
553+
_csvWriteContext = _csvWriteContext.getParent();
539554
// 14-Dec-2015, tatu: To complete skipping of ignored structured value, need this:
540555
if (_skipWithin != null) {
541-
if (_writeContext == _skipWithin) {
556+
if (_csvWriteContext == _skipWithin) {
542557
_skipWithin = null;
543558
}
544559
return;
@@ -549,7 +564,7 @@ public final void writeEndArray() throws IOException
549564
}
550565
// 20-Nov-2014, tatu: When doing "untyped"/"raw" output, this means that row
551566
// is now done. But not if writing such an array field, so:
552-
if (!_writeContext.inObject()) {
567+
if (!_csvWriteContext.inObject()) {
553568
finishRow();
554569
}
555570
}
@@ -560,30 +575,30 @@ public final void writeStartObject() throws IOException
560575
_verifyValueWrite("start an object");
561576
// No nesting for objects; can write Objects inside logical root-level arrays.
562577
// 14-Dec-2015, tatu: ... except, should be fine if we are ignoring the property
563-
if (_writeContext.inObject() ||
578+
if (_csvWriteContext.inObject() ||
564579
// 07-Nov-2017, tatu: But we may actually be nested indirectly; so check
565-
(_writeContext.inArray() && !_writeContext.getParent().inRoot())) {
580+
(_csvWriteContext.inArray() && !_csvWriteContext.getParent().inRoot())) {
566581
if (_skipWithin == null) { // new in 2.7
567582
if (_skipValue && isEnabled(JsonGenerator.Feature.IGNORE_UNKNOWN)) {
568-
_skipWithin = _writeContext;
583+
_skipWithin = _csvWriteContext;
569584
} else {
570585
_reportMappingError("CSV generator does not support Object values for properties (nested Objects)");
571586
}
572587
}
573588
}
574-
_writeContext = _writeContext.createChildObjectContext();
589+
_csvWriteContext = _csvWriteContext.createChildObjectContext(null);
575590
}
576591

577592
@Override
578593
public final void writeEndObject() throws IOException
579594
{
580-
if (!_writeContext.inObject()) {
581-
_reportError("Current context not Object but "+_writeContext.typeDesc());
595+
if (!_csvWriteContext.inObject()) {
596+
_reportError("Current context not Object but "+_csvWriteContext.typeDesc());
582597
}
583-
_writeContext = _writeContext.getParent();
598+
_csvWriteContext = _csvWriteContext.getParent();
584599
// 14-Dec-2015, tatu: To complete skipping of ignored structured value, need this:
585600
if (_skipWithin != null) {
586-
if (_writeContext == _skipWithin) {
601+
if (_csvWriteContext == _skipWithin) {
587602
_skipWithin = null;
588603
}
589604
return;
@@ -760,16 +775,16 @@ public void writeNull() throws IOException
760775
if (!_skipValue) {
761776
if (!_arraySeparator.isEmpty()) {
762777
_addToArray(_schema.getNullValueOrEmpty());
763-
} else if (_writeContext.inObject()) {
778+
} else if (_csvWriteContext.inObject()) {
764779
_writer.writeNull(_columnIndex());
765-
} else if (_writeContext.inArray()) {
780+
} else if (_csvWriteContext.inArray()) {
766781
// [dataformat-csv#106]: Need to make sure we don't swallow nulls in arrays either
767782
// 04-Jan-2016, tatu: but check for case of array-wrapping, in which case null stands for absence
768783
// of Object. In this case, could either add an empty row, or skip -- for now, we'll
769784
// just skip; can change, if so desired, to expose "root null" as empty rows, possibly
770785
// based on either schema property, or CsvGenerator.Feature.
771786
// Note: if nulls are to be written that way, would need to call `finishRow()` right after `writeNull()`
772-
if (!_writeContext.getParent().inRoot()) {
787+
if (!_csvWriteContext.getParent().inRoot()) {
773788
_writer.writeNull(_columnIndex());
774789
}
775790

@@ -909,7 +924,7 @@ public void writeOmittedField(String fieldName) throws IOException
909924
// assumed to have been removed from schema too
910925
} else {
911926
// basically combination of "writeFieldName()" and "writeNull()"
912-
if (_writeContext.writeFieldName(fieldName) == JsonWriteContext.STATUS_EXPECT_VALUE) {
927+
if (!_csvWriteContext.writeFieldName(fieldName)) {
913928
_reportError("Can not skip a field, expecting a value");
914929
}
915930
// and all we do is just note index to use for following value write
@@ -929,8 +944,7 @@ public void writeOmittedField(String fieldName) throws IOException
929944
@Override
930945
protected final void _verifyValueWrite(String typeMsg) throws IOException
931946
{
932-
int status = _writeContext.writeValue();
933-
if (status == JsonWriteContext.STATUS_EXPECT_NAME) {
947+
if (!_csvWriteContext.writeValue()) {
934948
_reportError("Can not "+typeMsg+", expecting field name");
935949
}
936950
if (_handleFirstLine) {

0 commit comments

Comments
 (0)