package com.fasterxml.jackson.dataformat.cbor;

import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.core.json.DupDetector;

Replacement for JsonWriteContext, needed to support alternative numeric field id for Integer-valued Maps that CBOR allows.
Since:2.10
/** * Replacement for {@code JsonWriteContext}, needed to support alternative * numeric field id for Integer-valued Maps that CBOR allows. * * @since 2.10 */
public final class CBORWriteContext extends JsonStreamContext {
Parent context for this context; null for root context.
/** * Parent context for this context; null for root context. */
protected final CBORWriteContext _parent; // // // Optional duplicate detection protected DupDetector _dups; /* /********************************************************** /* Simple instance reuse slots; speed up things a bit (10-15%) /* for docs with lots of small arrays/objects /********************************************************** */ protected CBORWriteContext _childToRecycle; /* /********************************************************** /* Location/state information (minus source reference) /********************************************************** */
Name of the field of which value is to be written; only used for OBJECT contexts
/** * Name of the field of which value is to be written; only * used for OBJECT contexts */
protected String _currentName; protected Object _currentValue;
Alternative to _currentName used for integer/long-valued Maps.
/** * Alternative to {@code _currentName} used for integer/long-valued Maps. */
protected long _currentFieldId;
Marker used to indicate that we just wrote a field name (or Map name / id) and now expect a value to write
/** * Marker used to indicate that we just wrote a field name (or Map name / id) * and now expect a value to write */
protected boolean _gotFieldId; /* /********************************************************** /* Life-cycle /********************************************************** */ protected CBORWriteContext(int type, CBORWriteContext parent, DupDetector dups, Object currentValue) { super(); _type = type; _parent = parent; _dups = dups; _index = -1; _currentValue = currentValue; } private CBORWriteContext reset(int type, Object currentValue) { _type = type; _index = -1; // as long as _gotFieldId false, current name/id can be left as-is _gotFieldId = false; _currentValue = currentValue; if (_dups != null) { _dups.reset(); } return this; } public CBORWriteContext withDupDetector(DupDetector dups) { _dups = dups; return this; } @Override public Object getCurrentValue() { return _currentValue; } @Override public void setCurrentValue(Object v) { _currentValue = v; } /* /********************************************************** /* Factory methods /********************************************************** */ public static CBORWriteContext createRootContext(DupDetector dd) { return new CBORWriteContext(TYPE_ROOT, null, dd, null); } public CBORWriteContext createChildArrayContext(Object currentValue) { CBORWriteContext ctxt = _childToRecycle; if (ctxt == null) { _childToRecycle = ctxt = new CBORWriteContext(TYPE_ARRAY, this, (_dups == null) ? null : _dups.child(), currentValue); return ctxt; } return ctxt.reset(TYPE_ARRAY, currentValue); } public CBORWriteContext createChildObjectContext(Object currentValue) { CBORWriteContext ctxt = _childToRecycle; if (ctxt == null) { _childToRecycle = ctxt = new CBORWriteContext(TYPE_OBJECT, this, (_dups == null) ? null : _dups.child(), currentValue); return ctxt; } return ctxt.reset(TYPE_OBJECT, currentValue); } @Override public final CBORWriteContext getParent() { return _parent; } @Override public final String getCurrentName() { if (_gotFieldId) { if (_currentName != null) { return _currentName; } return String.valueOf(_currentFieldId); } return null; } @Override public boolean hasCurrentName() { return _gotFieldId; }
Method that can be used to both clear the accumulated references (specifically value set with setCurrentValue(Object)) that should not be retained, and returns parent (as would getParent() do). Typically called when closing the active context when encountering JsonToken.END_ARRAY or JsonToken.END_OBJECT.
/** * Method that can be used to both clear the accumulated references * (specifically value set with {@link #setCurrentValue(Object)}) * that should not be retained, and returns parent (as would * {@link #getParent()} do). Typically called when closing the active * context when encountering {@link JsonToken#END_ARRAY} or * {@link JsonToken#END_OBJECT}. */
public CBORWriteContext clearAndGetParent() { _currentValue = null; // could also clear the current name, but seems cheap enough to leave? return _parent; } public DupDetector getDupDetector() { return _dups; }
Method that writer is to call before it writes a field name.
Returns:Ok if name writing should proceed
/** * Method that writer is to call before it writes a field name. * * @return Ok if name writing should proceed */
public boolean writeFieldName(String name) throws JsonProcessingException { if ((_type != TYPE_OBJECT) || _gotFieldId) { return false; } _gotFieldId = true; _currentName = name; if (_dups != null) { _checkDup(_dups, name); } return true; } public boolean writeFieldId(long fieldId) throws JsonProcessingException { if ((_type != TYPE_OBJECT) || _gotFieldId) { return false; } _gotFieldId = true; _currentFieldId = fieldId; // 14-Aug-2019, tatu: No dup deps for non-String keys, for now at least return true; } private final void _checkDup(DupDetector dd, String name) throws JsonProcessingException { if (dd.isDup(name)) { Object src = dd.getSource(); throw new JsonGenerationException("Duplicate field '"+name+"'", ((src instanceof JsonGenerator) ? ((JsonGenerator) src) : null)); } } public boolean writeValue() { // Only limitation is with OBJECTs: if (_type == TYPE_OBJECT) { if (!_gotFieldId) { return false; } _gotFieldId = false; } ++_index; return true; } }