aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/com/fasterxml/jackson/databind/DeserializationConfig.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/fasterxml/jackson/databind/DeserializationConfig.java')
-rw-r--r--src/main/java/com/fasterxml/jackson/databind/DeserializationConfig.java493
1 files changed, 493 insertions, 0 deletions
diff --git a/src/main/java/com/fasterxml/jackson/databind/DeserializationConfig.java b/src/main/java/com/fasterxml/jackson/databind/DeserializationConfig.java
new file mode 100644
index 000000000..183ebc27c
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/databind/DeserializationConfig.java
@@ -0,0 +1,493 @@
+package com.fasterxml.jackson.databind;
+
+import java.text.DateFormat;
+import java.util.*;
+
+import com.fasterxml.jackson.annotation.*;
+import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
+import com.fasterxml.jackson.core.*;
+import com.fasterxml.jackson.databind.cfg.BaseSettings;
+import com.fasterxml.jackson.databind.cfg.HandlerInstantiator;
+import com.fasterxml.jackson.databind.cfg.MapperConfigBase;
+import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler;
+import com.fasterxml.jackson.databind.introspect.ClassIntrospector;
+import com.fasterxml.jackson.databind.introspect.NopAnnotationIntrospector;
+import com.fasterxml.jackson.databind.introspect.VisibilityChecker;
+import com.fasterxml.jackson.databind.jsontype.SubtypeResolver;
+import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import com.fasterxml.jackson.databind.type.ClassKey;
+import com.fasterxml.jackson.databind.type.TypeFactory;
+import com.fasterxml.jackson.databind.util.LinkedNode;
+
+/**
+ * Object that contains baseline configuration for deserialization
+ * process. An instance is owned by {@link ObjectMapper}, which
+ * passes an immutable instance to be used for deserialization process.
+ *<p>
+ * Note that instances are considered immutable and as such no copies
+ * should need to be created (there are some implementation details
+ * with respect to mix-in annotations; where this is guaranteed as
+ * long as caller follow "copy-then-use" pattern)
+ */
+public final class DeserializationConfig
+ extends MapperConfigBase<DeserializationFeature, DeserializationConfig>
+{
+ /**
+ * Set of features enabled; actual type (kind of features)
+ * depends on sub-classes.
+ */
+ protected final int _deserFeatures;
+
+ /**
+ * Linked list that contains all registered problem handlers.
+ * Implementation as front-added linked list allows for sharing
+ * of the list (tail) without copying the list.
+ */
+ protected final LinkedNode<DeserializationProblemHandler> _problemHandlers;
+
+ /**
+ * Factory used for constructing {@link com.fasterxml.jackson.core.JsonNode} instances.
+ */
+ protected final JsonNodeFactory _nodeFactory;
+
+ /*
+ /**********************************************************
+ /* Life-cycle, constructors
+ /**********************************************************
+ */
+
+ /**
+ * Constructor used by ObjectMapper to create default configuration object instance.
+ */
+ public DeserializationConfig(BaseSettings base,
+ SubtypeResolver str, Map<ClassKey,Class<?>> mixins)
+ {
+ super(base, str, mixins);
+ _deserFeatures = collectFeatureDefaults(DeserializationFeature.class);
+ _nodeFactory = JsonNodeFactory.instance;
+ _problemHandlers = null;
+ }
+
+ /**
+ * Copy constructor used to create a non-shared instance with given mix-in
+ * annotation definitions and subtype resolver.
+ */
+ private DeserializationConfig(DeserializationConfig src, SubtypeResolver str)
+ {
+ super(src, str);
+ _deserFeatures = src._deserFeatures;
+ _nodeFactory = src._nodeFactory;
+ _problemHandlers = src._problemHandlers;
+ }
+
+ private DeserializationConfig(DeserializationConfig src,
+ int mapperFeatures, int deserFeatures)
+ {
+ super(src, mapperFeatures);
+ _deserFeatures = deserFeatures;
+ _nodeFactory = src._nodeFactory;
+ _problemHandlers = src._problemHandlers;
+ }
+
+ private DeserializationConfig(DeserializationConfig src, BaseSettings base)
+ {
+ super(src, base);
+ _deserFeatures = src._deserFeatures;
+ _nodeFactory = src._nodeFactory;
+ _problemHandlers = src._problemHandlers;
+ }
+
+ private DeserializationConfig(DeserializationConfig src, JsonNodeFactory f)
+ {
+ super(src);
+ _deserFeatures = src._deserFeatures;
+ _problemHandlers = src._problemHandlers;
+ _nodeFactory = f;
+ }
+
+ private DeserializationConfig(DeserializationConfig src,
+ LinkedNode<DeserializationProblemHandler> problemHandlers)
+ {
+ super(src);
+ _deserFeatures = src._deserFeatures;
+ _problemHandlers = problemHandlers;
+ _nodeFactory = src._nodeFactory;
+ }
+
+ private DeserializationConfig(DeserializationConfig src, String rootName)
+ {
+ super(src, rootName);
+ _deserFeatures = src._deserFeatures;
+ _problemHandlers = src._problemHandlers;
+ _nodeFactory = src._nodeFactory;
+ }
+
+ private DeserializationConfig(DeserializationConfig src, Class<?> view)
+ {
+ super(src, view);
+ _deserFeatures = src._deserFeatures;
+ _problemHandlers = src._problemHandlers;
+ _nodeFactory = src._nodeFactory;
+ }
+
+ /*
+ /**********************************************************
+ /* Life-cycle, factory methods from MapperConfig
+ /**********************************************************
+ */
+
+ @Override
+ public DeserializationConfig with(MapperFeature... features)
+ {
+ int newMapperFlags = _mapperFeatures;
+ for (MapperFeature f : features) {
+ newMapperFlags |= f.getMask();
+ }
+ return (newMapperFlags == _mapperFeatures) ? this :
+ new DeserializationConfig(this, newMapperFlags, _deserFeatures);
+ }
+
+ @Override
+ public DeserializationConfig without(MapperFeature... features)
+ {
+ int newMapperFlags = _mapperFeatures;
+ for (MapperFeature f : features) {
+ newMapperFlags &= ~f.getMask();
+ }
+ return (newMapperFlags == _mapperFeatures) ? this :
+ new DeserializationConfig(this, newMapperFlags, _deserFeatures);
+ }
+
+ @Override
+ public DeserializationConfig withClassIntrospector(ClassIntrospector ci) {
+ return _withBase(_base.withClassIntrospector(ci));
+ }
+
+ @Override
+ public DeserializationConfig withAnnotationIntrospector(AnnotationIntrospector ai) {
+ return _withBase(_base.withAnnotationIntrospector(ai));
+ }
+
+ @Override
+ public DeserializationConfig withVisibilityChecker(VisibilityChecker<?> vc) {
+ return _withBase(_base.withVisibilityChecker(vc));
+ }
+
+ @Override
+ public DeserializationConfig withVisibility(PropertyAccessor forMethod, JsonAutoDetect.Visibility visibility) {
+ return _withBase( _base.withVisibility(forMethod, visibility));
+ }
+
+ @Override
+ public DeserializationConfig withTypeResolverBuilder(TypeResolverBuilder<?> trb) {
+ return _withBase(_base.withTypeResolverBuilder(trb));
+ }
+
+ @Override
+ public DeserializationConfig withSubtypeResolver(SubtypeResolver str) {
+ return (_subtypeResolver == str) ? this : new DeserializationConfig(this, str);
+ }
+
+ @Override
+ public DeserializationConfig withPropertyNamingStrategy(PropertyNamingStrategy pns) {
+ return _withBase(_base.withPropertyNamingStrategy(pns));
+ }
+
+ @Override
+ public DeserializationConfig withRootName(String rootName) {
+ if (rootName == null) {
+ if (_rootName == null) {
+ return this;
+ }
+ } else if (rootName.equals(_rootName)) {
+ return this;
+ }
+ return new DeserializationConfig(this, rootName);
+ }
+
+ @Override
+ public DeserializationConfig withTypeFactory(TypeFactory tf) {
+ return _withBase( _base.withTypeFactory(tf));
+ }
+
+ @Override
+ public DeserializationConfig withDateFormat(DateFormat df) {
+ return _withBase(_base.withDateFormat(df));
+ }
+
+ @Override
+ public DeserializationConfig withHandlerInstantiator(HandlerInstantiator hi) {
+ return _withBase(_base.withHandlerInstantiator(hi));
+ }
+
+ @Override
+ public DeserializationConfig withInsertedAnnotationIntrospector(AnnotationIntrospector ai) {
+ return _withBase(_base.withInsertedAnnotationIntrospector(ai));
+ }
+
+ @Override
+ public DeserializationConfig withAppendedAnnotationIntrospector(AnnotationIntrospector ai) {
+ return _withBase(_base.withAppendedAnnotationIntrospector(ai));
+ }
+
+ @Override
+ public DeserializationConfig withView(Class<?> view) {
+ return (_view == view) ? this : new DeserializationConfig(this, view);
+ }
+
+ private final DeserializationConfig _withBase(BaseSettings newBase) {
+ return (_base == newBase) ? this : new DeserializationConfig(this, newBase);
+ }
+
+ /*
+ /**********************************************************
+ /* Life-cycle, deserialization-specific factory methods
+ /**********************************************************
+ */
+
+ /**
+ * Fluent factory method that will construct a new instance with
+ * specified {@link JsonNodeFactory}
+ */
+ public DeserializationConfig withNodeFactory(JsonNodeFactory f) {
+ if (_nodeFactory == f) {
+ return this;
+ }
+ return new DeserializationConfig(this, f);
+ }
+
+ /**
+ * Method that can be used to add a handler that can (try to)
+ * resolve non-fatal deserialization problems.
+ */
+ public DeserializationConfig withHandler(DeserializationProblemHandler h)
+ {
+ // Sanity check: let's prevent adding same handler multiple times
+ if (LinkedNode.contains(_problemHandlers, h)) {
+ return this;
+ }
+ return new DeserializationConfig(this,
+ new LinkedNode<DeserializationProblemHandler>(h, _problemHandlers));
+ }
+
+ /**
+ * Method for removing all configured problem handlers; usually done to replace
+ * existing handler(s) with different one(s)
+ */
+ public DeserializationConfig withNoProblemHandlers() {
+ if (_problemHandlers == null) {
+ return this;
+ }
+ return new DeserializationConfig(this,
+ (LinkedNode<DeserializationProblemHandler>) null);
+ }
+
+ /**
+ * Fluent factory method that will construct and return a new configuration
+ * object instance with specified features enabled.
+ */
+ public DeserializationConfig with(DeserializationFeature feature)
+ {
+ int newDeserFeatures = (_deserFeatures | feature.getMask());
+ return (newDeserFeatures == _deserFeatures) ? this :
+ new DeserializationConfig(this, _mapperFeatures, newDeserFeatures);
+ }
+
+ /**
+ * Fluent factory method that will construct and return a new configuration
+ * object instance with specified features enabled.
+ */
+ public DeserializationConfig with(DeserializationFeature first,
+ DeserializationFeature... features)
+ {
+ int newDeserFeatures = _deserFeatures | first.getMask();
+ for (DeserializationFeature f : features) {
+ newDeserFeatures |= f.getMask();
+ }
+ return (newDeserFeatures == _deserFeatures) ? this :
+ new DeserializationConfig(this, _mapperFeatures, newDeserFeatures);
+ }
+
+ /**
+ * Fluent factory method that will construct and return a new configuration
+ * object instance with specified features enabled.
+ */
+ public DeserializationConfig withFeatures(DeserializationFeature... features)
+ {
+ int newDeserFeatures = _deserFeatures;
+ for (DeserializationFeature f : features) {
+ newDeserFeatures |= f.getMask();
+ }
+ return (newDeserFeatures == _deserFeatures) ? this :
+ new DeserializationConfig(this, _mapperFeatures, newDeserFeatures);
+ }
+
+ /**
+ * Fluent factory method that will construct and return a new configuration
+ * object instance with specified feature disabled.
+ */
+ public DeserializationConfig without(DeserializationFeature feature)
+ {
+ int newDeserFeatures = _deserFeatures & ~feature.getMask();
+ return (newDeserFeatures == _deserFeatures) ? this :
+ new DeserializationConfig(this, _mapperFeatures, newDeserFeatures);
+ }
+
+ /**
+ * Fluent factory method that will construct and return a new configuration
+ * object instance with specified features disabled.
+ */
+ public DeserializationConfig without(DeserializationFeature first,
+ DeserializationFeature... features)
+ {
+ int newDeserFeatures = _deserFeatures & ~first.getMask();
+ for (DeserializationFeature f : features) {
+ newDeserFeatures &= ~f.getMask();
+ }
+ return (newDeserFeatures == _deserFeatures) ? this :
+ new DeserializationConfig(this, _mapperFeatures, newDeserFeatures);
+ }
+
+ /**
+ * Fluent factory method that will construct and return a new configuration
+ * object instance with specified features disabled.
+ */
+ public DeserializationConfig withoutFeatures(DeserializationFeature... features)
+ {
+ int newDeserFeatures = _deserFeatures;
+ for (DeserializationFeature f : features) {
+ newDeserFeatures &= ~f.getMask();
+ }
+ return (newDeserFeatures == _deserFeatures) ? this :
+ new DeserializationConfig(this, _mapperFeatures, newDeserFeatures);
+ }
+
+ /*
+ /**********************************************************
+ /* MapperConfig implementation
+ /**********************************************************
+ */
+
+ /**
+ * Method for getting {@link AnnotationIntrospector} configured
+ * to introspect annotation values used for configuration.
+ */
+ @Override
+ public AnnotationIntrospector getAnnotationIntrospector()
+ {
+ /* 29-Jul-2009, tatu: it's now possible to disable use of
+ * annotations; can be done using "no-op" introspector
+ */
+ if (isEnabled(MapperFeature.USE_ANNOTATIONS)) {
+ return super.getAnnotationIntrospector();
+ }
+ return NopAnnotationIntrospector.instance;
+ }
+
+ @Override
+ public boolean useRootWrapping()
+ {
+ if (_rootName != null) { // empty String disables wrapping; non-empty enables
+ return (_rootName.length() > 0);
+ }
+ return isEnabled(DeserializationFeature.UNWRAP_ROOT_VALUE);
+ }
+
+ /**
+ * Accessor for getting bean description that only contains class
+ * annotations: useful if no getter/setter/creator information is needed.
+ */
+ @Override
+ public BeanDescription introspectClassAnnotations(JavaType type) {
+ return getClassIntrospector().forClassAnnotations(this, type, this);
+ }
+
+ /**
+ * Accessor for getting bean description that only contains immediate class
+ * annotations: ones from the class, and its direct mix-in, if any, but
+ * not from super types.
+ */
+ @Override
+ public BeanDescription introspectDirectClassAnnotations(JavaType type) {
+ return getClassIntrospector().forDirectClassAnnotations(this, type, this);
+ }
+
+ @Override
+ public VisibilityChecker<?> getDefaultVisibilityChecker()
+ {
+ VisibilityChecker<?> vchecker = super.getDefaultVisibilityChecker();
+ if (!isEnabled(MapperFeature.AUTO_DETECT_SETTERS)) {
+ vchecker = vchecker.withSetterVisibility(Visibility.NONE);
+ }
+ if (!isEnabled(MapperFeature.AUTO_DETECT_CREATORS)) {
+ vchecker = vchecker.withCreatorVisibility(Visibility.NONE);
+ }
+ if (!isEnabled(MapperFeature.AUTO_DETECT_FIELDS)) {
+ vchecker = vchecker.withFieldVisibility(Visibility.NONE);
+ }
+ return vchecker;
+ }
+
+ public final boolean isEnabled(DeserializationFeature f) {
+ return (_deserFeatures & f.getMask()) != 0;
+ }
+
+ /*
+ /**********************************************************
+ /* Other configuration
+ /**********************************************************
+ */
+
+ public final int getDeserializationFeatures() {
+ return _deserFeatures;
+ }
+
+ /**
+ * Method for getting head of the problem handler chain. May be null,
+ * if no handlers have been added.
+ */
+ public LinkedNode<DeserializationProblemHandler> getProblemHandlers() {
+ return _problemHandlers;
+ }
+
+ /**
+ * Method called during deserialization if Base64 encoded content
+ * needs to be decoded. Default version just returns default Jackson
+ * uses, which is modified-mime which does not add linefeeds (because
+ * those would have to be escaped in JSON strings).
+ */
+ public Base64Variant getBase64Variant() {
+ return Base64Variants.getDefaultVariant();
+ }
+
+ public final JsonNodeFactory getNodeFactory() {
+ return _nodeFactory;
+ }
+
+ /*
+ /**********************************************************
+ /* Introspection methods
+ /**********************************************************
+ */
+
+ /**
+ * Method that will introspect full bean properties for the purpose
+ * of building a bean deserializer
+ *
+ * @param type Type of class to be introspected
+ */
+ @SuppressWarnings("unchecked")
+ public <T extends BeanDescription> T introspect(JavaType type) {
+ return (T) getClassIntrospector().forDeserialization(this, type, this);
+ }
+
+ /**
+ * Method that will introspect subset of bean properties needed to
+ * construct bean instance.
+ */
+ @SuppressWarnings("unchecked")
+ public <T extends BeanDescription> T introspectForCreation(JavaType type) {
+ return (T) getClassIntrospector().forCreation(this, type, this);
+ }
+}