diff options
Diffstat (limited to 'src/main/java/com/fasterxml/jackson/databind/DeserializationConfig.java')
-rw-r--r-- | src/main/java/com/fasterxml/jackson/databind/DeserializationConfig.java | 493 |
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); + } +} |