blob: 771b3224c9739f8005132648b18e9d23f068c193 [file] [log] [blame]
package com.fasterxml.jackson.core;
import com.fasterxml.jackson.core.io.InputDecorator;
import com.fasterxml.jackson.core.io.OutputDecorator;
import com.fasterxml.jackson.core.json.JsonReadFeature;
import com.fasterxml.jackson.core.json.JsonWriteFeature;
/**
* Since 2.10, Builder class is offered for creating token stream factories
* with difference configurations: with 3.x they will be fully immutable.
*
* @since 2.10
*/
public abstract class TSFBuilder<F extends JsonFactory,
B extends TSFBuilder<F,B>>
{
/*
/**********************************************************************
/* Constants
/**********************************************************************
*/
/**
* Bitfield (set of flags) of all factory features that are enabled by default.
*/
protected final static int DEFAULT_FACTORY_FEATURE_FLAGS = JsonFactory.Feature.collectDefaults();
/**
* Bitfield (set of flags) of all parser features that are enabled
* by default.
*/
protected final static int DEFAULT_PARSER_FEATURE_FLAGS = JsonParser.Feature.collectDefaults();
/**
* Bitfield (set of flags) of all generator features that are enabled
* by default.
*/
protected final static int DEFAULT_GENERATOR_FEATURE_FLAGS = JsonGenerator.Feature.collectDefaults();
/*
/**********************************************************************
/* Configured features
/**********************************************************************
*/
/**
* Set of {@link com.fasterxml.jackson.core.JsonFactory.Feature}s enabled,
* as bitmask.
*/
protected int _factoryFeatures;
/**
* Set of {@link JsonParser.Feature}s enabled, as bitmask.
*/
protected int _streamReadFeatures;
/**
* Set of {@link JsonGenerator.Feature}s enabled, as bitmask.
*/
protected int _streamWriteFeatures;
/*
/**********************************************************************
/* Other configuration
/**********************************************************************
*/
/**
* Optional helper object that may decorate input sources, to do
* additional processing on input during parsing.
*/
protected InputDecorator _inputDecorator;
/**
* Optional helper object that may decorate output object, to do
* additional processing on output during content generation.
*/
protected OutputDecorator _outputDecorator;
/*
/**********************************************************************
/* Construction
/**********************************************************************
*/
protected TSFBuilder() {
_factoryFeatures = DEFAULT_FACTORY_FEATURE_FLAGS;
_streamReadFeatures = DEFAULT_PARSER_FEATURE_FLAGS;
_streamWriteFeatures = DEFAULT_GENERATOR_FEATURE_FLAGS;
_inputDecorator = null;
_outputDecorator = null;
}
protected TSFBuilder(JsonFactory base)
{
this(base._factoryFeatures,
base._parserFeatures, base._generatorFeatures);
}
protected TSFBuilder(int factoryFeatures,
int parserFeatures, int generatorFeatures)
{
_factoryFeatures = factoryFeatures;
_streamReadFeatures = parserFeatures;
_streamWriteFeatures = generatorFeatures;
}
// // // Accessors
public int factoryFeaturesMask() { return _factoryFeatures; }
public int streamReadFeatures() { return _streamReadFeatures; }
public int streamWriteFeatures() { return _streamWriteFeatures; }
public InputDecorator inputDecorator() { return _inputDecorator; }
public OutputDecorator outputDecorator() { return _outputDecorator; }
// // // Factory features
public B enable(JsonFactory.Feature f) {
_factoryFeatures |= f.getMask();
return _this();
}
public B disable(JsonFactory.Feature f) {
_factoryFeatures &= ~f.getMask();
return _this();
}
public B configure(JsonFactory.Feature f, boolean state) {
return state ? enable(f) : disable(f);
}
// // // StreamReadFeatures (replacement of non-json-specific parser features)
public B enable(StreamReadFeature f) {
_streamReadFeatures |= f.mappedFeature().getMask();
return _this();
}
public B enable(StreamReadFeature first, StreamReadFeature... other) {
_streamReadFeatures |= first.mappedFeature().getMask();
for (StreamReadFeature f : other) {
_streamReadFeatures |= f.mappedFeature().getMask();
}
return _this();
}
public B disable(StreamReadFeature f) {
_streamReadFeatures &= ~f.mappedFeature().getMask();
return _this();
}
public B disable(StreamReadFeature first, StreamReadFeature... other) {
_streamReadFeatures &= ~first.mappedFeature().getMask();
for (StreamReadFeature f : other) {
_streamReadFeatures &= ~f.mappedFeature().getMask();
}
return _this();
}
public B configure(StreamReadFeature f, boolean state) {
return state ? enable(f) : disable(f);
}
// // // StreamWriteFeatures (replacement of non-json-specific generator features)
public B enable(StreamWriteFeature f) {
_streamWriteFeatures |= f.mappedFeature().getMask();
return _this();
}
public B enable(StreamWriteFeature first, StreamWriteFeature... other) {
_streamWriteFeatures |= first.mappedFeature().getMask();
for (StreamWriteFeature f : other) {
_streamWriteFeatures |= f.mappedFeature().getMask();
}
return _this();
}
public B disable(StreamWriteFeature f) {
_streamWriteFeatures &= ~f.mappedFeature().getMask();
return _this();
}
public B disable(StreamWriteFeature first, StreamWriteFeature... other) {
_streamWriteFeatures &= ~first.mappedFeature().getMask();
for (StreamWriteFeature f : other) {
_streamWriteFeatures &= ~f.mappedFeature().getMask();
}
return _this();
}
public B configure(StreamWriteFeature f, boolean state) {
return state ? enable(f) : disable(f);
}
/* 26-Jun-2018, tatu: This should not be needed here, but due to 2.x limitations,
* we do need to include it or require casting.
* Specifically: since `JsonFactory` (and not `TokenStreamFactory`) is base class
* for all backends, it can not expose JSON-specific builder, but this.
* So let's select lesser evil(s).
*/
// // // JSON-specific, reads
public B enable(JsonReadFeature f) {
return _failNonJSON(f);
}
public B enable(JsonReadFeature first, JsonReadFeature... other) {
return _failNonJSON(first);
}
public B disable(JsonReadFeature f) {
return _failNonJSON(f);
}
public B disable(JsonReadFeature first, JsonReadFeature... other) {
return _failNonJSON(first);
}
public B configure(JsonReadFeature f, boolean state) {
return _failNonJSON(f);
}
private B _failNonJSON(Object feature) {
throw new IllegalArgumentException("Feature "+feature.getClass().getName()
+"#"+feature.toString()+" not supported for non-JSON backend");
}
// // // JSON-specific, writes
public B enable(JsonWriteFeature f) {
return _failNonJSON(f);
}
public B enable(JsonWriteFeature first, JsonWriteFeature... other) {
return _failNonJSON(first);
}
public B disable(JsonWriteFeature f) {
return _failNonJSON(f);
}
public B disable(JsonWriteFeature first, JsonWriteFeature... other) {
return _failNonJSON(first);
}
public B configure(JsonWriteFeature f, boolean state) {
return _failNonJSON(f);
}
// // // Other configuration
public B inputDecorator(InputDecorator dec) {
_inputDecorator = dec;
return _this();
}
public B outputDecorator(OutputDecorator dec) {
_outputDecorator = dec;
return _this();
}
// // // Other methods
/**
* Method for constructing actual {@link TokenStreamFactory} instance, given
* configuration.
*/
public abstract F build();
// silly convenience cast method we need
@SuppressWarnings("unchecked")
protected final B _this() { return (B) this; }
// // // Support for subtypes
protected void _legacyEnable(JsonParser.Feature f) {
if (f != null) {
_streamReadFeatures |= f.getMask();
}
}
protected void _legacyDisable(JsonParser.Feature f) {
if (f != null) {
_streamReadFeatures &= ~f.getMask();
}
}
protected void _legacyEnable(JsonGenerator.Feature f) {
if (f != null) {
_streamWriteFeatures |= f.getMask();
}
}
protected void _legacyDisable(JsonGenerator.Feature f) {
if (f != null) {
_streamWriteFeatures &= ~f.getMask();
}
}
}