AvroParser.java
package tools.jackson.dataformat.avro;
import java.io.IOException;
import java.io.Writer;
import tools.jackson.core.*;
import tools.jackson.core.base.ParserBase;
import tools.jackson.core.io.IOContext;
import tools.jackson.core.util.ByteArrayBuilder;
import tools.jackson.core.util.JacksonFeatureSet;
import tools.jackson.core.util.SimpleStreamReadContext;
import tools.jackson.core.util.VersionUtil;
import tools.jackson.dataformat.avro.deser.AvroReadContext;
import tools.jackson.dataformat.avro.deser.MissingReader;
/**
* {@link JsonParser} implementation for decoding Avro content and
* exposing at as a stream of {@link JsonToken}s, to be used
* for data binding.
*/
public abstract class AvroParser extends ParserBase
{
// @since 2.14 - require some overrides
protected final static JacksonFeatureSet<StreamReadCapability> AVRO_READ_CAPABILITIES =
DEFAULT_READ_CAPABILITIES.with(StreamReadCapability.EXACT_FLOATS);
/*
/**********************************************************************
/* Configuration
/**********************************************************************
*/
protected AvroSchema _rootSchema;
protected int _formatFeatures;
/*
/**********************************************************************
/* State
/**********************************************************************
*/
/**
* Information about parser context, context in which
* the next token is to be parsed (root, array, object).
*/
protected SimpleStreamReadContext _streamReadContext;
protected AvroReadContext _avroContext;
/*
/**********************************************************************
/* Life-cycle
/**********************************************************************
*/
protected AvroParser(ObjectReadContext readCtxt, IOContext ioCtxt,
int parserFeatures, int avroFeatures)
{
super(readCtxt, ioCtxt, parserFeatures);
_formatFeatures = avroFeatures;
// null -> No dup checks in Avro (would only be relevant for Maps)
_streamReadContext = SimpleStreamReadContext.createRootContext(null);
_avroContext = MissingReader.instance;
}
@Override
public abstract Object streamReadInputSource();
/*
/**********************************************************************
/* Versioned
/**********************************************************************
*/
@Override
public Version version() {
return PackageVersion.VERSION;
}
/*
/**********************************************************************
/* Capability introspection
/**********************************************************************
*/
@Override
public boolean canReadTypeId() {
return true;
}
@Override
public JacksonFeatureSet<StreamReadCapability> streamReadCapabilities() {
return AVRO_READ_CAPABILITIES;
}
/*
/**********************************************************************
/* ParserBase method impls
/**********************************************************************
*/
@Override public TokenStreamContext streamReadContext() { return _streamReadContext; }
@Override public void assignCurrentValue(Object v) { _streamReadContext.assignCurrentValue(v); }
@Override public Object currentValue() { return _streamReadContext.currentValue(); }
@Override
protected abstract void _closeInput() throws IOException;
/*
/**********************************************************************
/* Public API, configuration
/**********************************************************************
*/
/**
* Method for enabling specified Avro feature
* (check {@link AvroReadFeature} for list of features)
*/
public JsonParser enable(AvroReadFeature f) {
_formatFeatures |= f.getMask();
return this;
}
/**
* Method for disabling specified Avro feature
* (check {@link AvroReadFeature} for list of features)
*/
public JsonParser disable(AvroReadFeature f) {
_formatFeatures &= ~f.getMask();
return this;
}
/**
* Method for enabling or disabling specified Avro feature
* (check {@link AvroReadFeature} for list of features)
*/
public JsonParser configure(AvroReadFeature f, boolean state)
{
if (state) {
enable(f);
} else {
disable(f);
}
return this;
}
/**
* Method for checking whether specified Avro {@link AvroReadFeature}
* is enabled.
*/
public boolean isEnabled(AvroReadFeature f) {
return (_formatFeatures & f.getMask()) != 0;
}
@Override public AvroSchema getSchema() {
return _rootSchema;
}
protected void setSchema(AvroSchema schema) throws JacksonException
{
if (_rootSchema == schema) {
return;
}
_initSchema((AvroSchema) schema);
}
protected abstract void _initSchema(AvroSchema schema) throws JacksonException;
@Override
public Object getTypeId() throws JacksonException {
return _avroContext != null ? _avroContext.getTypeId() : null;
}
/*
/**********************************************************************
/* Location info
/**********************************************************************
*/
@Override
public TokenStreamLocation currentTokenLocation() {
// !!! TODO
return null;
}
@Override
public TokenStreamLocation currentLocation() {
// !!! TODO
return null;
}
/*
/**********************************************************************
/* Parsing
/**********************************************************************
*/
// public abstract JsonToken nextToken() throws JacksonException;
/*
/**********************************************************************
/* String value handling
/**********************************************************************
*/
@Override
public abstract boolean hasStringCharacters();
@Override
public abstract String getString() throws JacksonException;
@Override
public abstract int getString(Writer writer) throws JacksonException;
@Override
public String currentName() throws JacksonException {
return _avroContext.currentName();
}
@Override
public char[] getStringCharacters() throws JacksonException {
String text = getString();
return (text == null) ? null : text.toCharArray();
}
@Override
public int getStringLength() throws JacksonException {
String text = getString();
return (text == null) ? 0 : text.length();
}
@Override
public int getStringOffset() throws JacksonException {
return 0;
}
/*
/**********************************************************************
/* Binary (base64)
/**********************************************************************
*/
@Override
public Object getEmbeddedObject() throws JacksonException {
return _binaryValue;
}
@Override
public byte[] getBinaryValue(Base64Variant variant) throws JacksonException
{
// Usually we get properly declared byte[], and _binaryValue non null.
// But we also support base64-encoded String as fallback
if (_binaryValue == null) {
if (_currToken != JsonToken.VALUE_STRING) {
_reportError("Current token ("+_currToken+") not VALUE_STRING, can not access as binary");
}
@SuppressWarnings("resource")
ByteArrayBuilder builder = _getByteArrayBuilder();
_decodeBase64(getString(), builder, variant);
_binaryValue = builder.toByteArray();
}
return _binaryValue;
}
/*
/**********************************************************************
/* And methods we shouldn't really need...
/**********************************************************************
*/
// We should never end up here, as all numeric values are eagerly decoded...
@Override
protected void _parseNumericValue(int expType) throws JacksonException {
VersionUtil.throwInternal();
}
@Override
protected int _parseIntValue() throws JacksonException {
VersionUtil.throwInternal();
return 0;
}
}