Skip to content

Commit 8b279da

Browse files
committed
Add SimpleTokenWriteContext
1 parent ed79f76 commit 8b279da

File tree

1 file changed

+198
-0
lines changed

1 file changed

+198
-0
lines changed
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
package com.fasterxml.jackson.core.util;
2+
3+
import com.fasterxml.jackson.core.*;
4+
import com.fasterxml.jackson.core.json.DupDetector;
5+
6+
/**
7+
* Basic implementation of {@code TokenStreamContext} useful for most
8+
* format backends (with notable exception of JSON that needs bit more
9+
* advanced state).
10+
*
11+
* @since 3.0
12+
*/
13+
public final class SimpleTokenWriteContext extends TokenStreamContext
14+
{
15+
/**
16+
* Parent context for this context; null for root context.
17+
*/
18+
protected final SimpleTokenWriteContext _parent;
19+
20+
// // // Optional duplicate detection
21+
22+
protected DupDetector _dups;
23+
24+
/*
25+
/**********************************************************
26+
/* Simple instance reuse slots; speed up things a bit (10-15%)
27+
/* for docs with lots of small arrays/objects
28+
/**********************************************************
29+
*/
30+
31+
protected SimpleTokenWriteContext _childToRecycle;
32+
33+
/*
34+
/**********************************************************
35+
/* Location/state information (minus source reference)
36+
/**********************************************************
37+
*/
38+
39+
/**
40+
* Name of the field of which value is to be written; only
41+
* used for OBJECT contexts
42+
*/
43+
protected String _currentName;
44+
45+
protected Object _currentValue;
46+
47+
/**
48+
* Marker used to indicate that we just wrote a field name
49+
* and now expect a value to write
50+
*/
51+
protected boolean _gotFieldId;
52+
53+
/*
54+
/**********************************************************************
55+
/* Life-cycle
56+
/**********************************************************************
57+
*/
58+
59+
protected SimpleTokenWriteContext(int type, SimpleTokenWriteContext parent, DupDetector dups,
60+
Object currentValue) {
61+
super();
62+
_type = type;
63+
_parent = parent;
64+
_dups = dups;
65+
_index = -1;
66+
_currentValue = currentValue;
67+
}
68+
69+
private SimpleTokenWriteContext reset(int type, Object currentValue) {
70+
_type = type;
71+
_index = -1;
72+
// as long as _gotFieldId false, current name/id can be left as-is
73+
_gotFieldId = false;
74+
_currentValue = currentValue;
75+
if (_dups != null) { _dups.reset(); }
76+
return this;
77+
}
78+
79+
public SimpleTokenWriteContext withDupDetector(DupDetector dups) {
80+
_dups = dups;
81+
return this;
82+
}
83+
84+
@Override
85+
public Object getCurrentValue() {
86+
return _currentValue;
87+
}
88+
89+
@Override
90+
public void setCurrentValue(Object v) {
91+
_currentValue = v;
92+
}
93+
94+
/*
95+
/**********************************************************************
96+
/* Factory methods
97+
/**********************************************************************
98+
*/
99+
100+
public static SimpleTokenWriteContext createRootContext(DupDetector dd) {
101+
return new SimpleTokenWriteContext(TYPE_ROOT, null, dd, null);
102+
}
103+
104+
public SimpleTokenWriteContext createChildArrayContext(Object currentValue) {
105+
SimpleTokenWriteContext ctxt = _childToRecycle;
106+
if (ctxt == null) {
107+
_childToRecycle = ctxt = new SimpleTokenWriteContext(TYPE_ARRAY, this,
108+
(_dups == null) ? null : _dups.child(), currentValue);
109+
return ctxt;
110+
}
111+
return ctxt.reset(TYPE_ARRAY, currentValue);
112+
}
113+
114+
public SimpleTokenWriteContext createChildObjectContext(Object currentValue) {
115+
SimpleTokenWriteContext ctxt = _childToRecycle;
116+
if (ctxt == null) {
117+
_childToRecycle = ctxt = new SimpleTokenWriteContext(TYPE_OBJECT, this,
118+
(_dups == null) ? null : _dups.child(), currentValue);
119+
return ctxt;
120+
}
121+
return ctxt.reset(TYPE_OBJECT, currentValue);
122+
}
123+
124+
/*
125+
/**********************************************************************
126+
/* Accessors
127+
/**********************************************************************
128+
*/
129+
130+
@Override public final SimpleTokenWriteContext getParent() { return _parent; }
131+
@Override public final String currentName() {
132+
if (_gotFieldId) {
133+
return _currentName;
134+
}
135+
return null;
136+
}
137+
138+
@Override public boolean hasCurrentName() { return _gotFieldId; }
139+
140+
/**
141+
* Method that can be used to both clear the accumulated references
142+
* (specifically value set with {@link #setCurrentValue(Object)})
143+
* that should not be retained, and returns parent (as would
144+
* {@link #getParent()} do). Typically called when closing the active
145+
* context when encountering {@link JsonToken#END_ARRAY} or
146+
* {@link JsonToken#END_OBJECT}.
147+
*/
148+
public SimpleTokenWriteContext clearAndGetParent() {
149+
_currentValue = null;
150+
// could also clear the current name, but seems cheap enough to leave?
151+
return _parent;
152+
}
153+
154+
public DupDetector getDupDetector() {
155+
return _dups;
156+
}
157+
158+
/*
159+
/**********************************************************************
160+
/* State changing
161+
/**********************************************************************
162+
*/
163+
164+
/**
165+
* Method that writer is to call before it writes a field name.
166+
*
167+
* @return Ok if name writing should proceed
168+
*/
169+
public boolean writeFieldName(String name) throws JsonProcessingException {
170+
if ((_type != TYPE_OBJECT) || _gotFieldId) {
171+
return false;
172+
}
173+
_gotFieldId = true;
174+
_currentName = name;
175+
if (_dups != null) { _checkDup(_dups, name); }
176+
return true;
177+
}
178+
179+
private final void _checkDup(DupDetector dd, String name) throws JsonProcessingException {
180+
if (dd.isDup(name)) {
181+
Object src = dd.getSource();
182+
throw new JsonGenerationException("Duplicate field '"+name+"'",
183+
((src instanceof JsonGenerator) ? ((JsonGenerator) src) : null));
184+
}
185+
}
186+
187+
public boolean writeValue() {
188+
// Only limitation is with OBJECTs:
189+
if (_type == TYPE_OBJECT) {
190+
if (!_gotFieldId) {
191+
return false;
192+
}
193+
_gotFieldId = false;
194+
}
195+
++_index;
196+
return true;
197+
}
198+
}

0 commit comments

Comments
 (0)