| package org.codehaus.jackson.map; |
| |
| import java.text.DateFormat; |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| import org.codehaus.jackson.annotate.JsonAutoDetect; |
| import org.codehaus.jackson.annotate.JsonMethod; |
| import org.codehaus.jackson.map.introspect.Annotated; |
| import org.codehaus.jackson.map.introspect.VisibilityChecker; |
| import org.codehaus.jackson.map.jsontype.SubtypeResolver; |
| import org.codehaus.jackson.map.jsontype.TypeIdResolver; |
| import org.codehaus.jackson.map.jsontype.TypeResolverBuilder; |
| import org.codehaus.jackson.map.jsontype.impl.StdSubtypeResolver; |
| import org.codehaus.jackson.map.type.ClassKey; |
| import org.codehaus.jackson.map.type.TypeBindings; |
| import org.codehaus.jackson.map.type.TypeFactory; |
| import org.codehaus.jackson.map.util.ClassUtil; |
| import org.codehaus.jackson.map.util.StdDateFormat; |
| import org.codehaus.jackson.type.JavaType; |
| import org.codehaus.jackson.type.TypeReference; |
| |
| /** |
| * Interface that defines functionality accessible through both |
| * serialization and deserialization configuration objects; |
| * accessors to mode-independent configuration settings |
| * and such. |
| *<p> |
| * As of version 1.9, the goal is to make this class eventually immutable. |
| * Because of this, existing methods that allow changing state of this |
| * instance are deprecated in favor of methods that create new instances |
| * with different configuration ("fluent factories"). |
| * One major remaining issue is that of handling mix-in annotations, which |
| * still represent a bit of mutable state; may need to implement a |
| * functional-style immutable map for storing those. |
| * |
| * @since 1.2 -- major change in 1.8, changed from interface to |
| * abstract class |
| */ |
| public abstract class MapperConfig<T extends MapperConfig<T>> |
| implements ClassIntrospector.MixInResolver |
| { |
| /* |
| /********************************************************** |
| /* Constants, default values |
| /********************************************************** |
| */ |
| |
| /** |
| * This is the default {@link DateFormat} used unless overridden by |
| * custom implementation. |
| */ |
| protected final static DateFormat DEFAULT_DATE_FORMAT = StdDateFormat.instance; |
| |
| /* |
| /********************************************************** |
| /* Simple immutable basic settings |
| /********************************************************** |
| */ |
| |
| /** |
| * Immutable container object for simple configuration settings. |
| *<p> |
| * Note: ideally this would be final, but until we can eliminate |
| * mutators, must keep it mutable. |
| */ |
| protected Base _base; |
| |
| /* |
| /********************************************************** |
| /* Mix-in annotations |
| /********************************************************** |
| */ |
| |
| /** |
| * Mapping that defines how to apply mix-in annotations: key is |
| * the type to received additional annotations, and value is the |
| * type that has annotations to "mix in". |
| *<p> |
| * Annotations associated with the value classes will be used to |
| * override annotations of the key class, associated with the |
| * same field or method. They can be further masked by sub-classes: |
| * you can think of it as injecting annotations between the target |
| * class and its sub-classes (or interfaces) |
| * |
| * @since 1.2 |
| */ |
| protected HashMap<ClassKey,Class<?>> _mixInAnnotations; |
| |
| /** |
| * Flag used to detect when a copy if mix-in annotations is |
| * needed: set when current copy is shared, cleared when a |
| * fresh copy is made |
| * |
| * @since 1.2 |
| */ |
| protected boolean _mixInAnnotationsShared; |
| |
| /* |
| /********************************************************** |
| /* "Late bound" settings |
| /********************************************************** |
| */ |
| |
| /** |
| * Registered concrete subtypes that can be used instead of (or |
| * in addition to) ones declared using annotations. |
| * Unlike most other settings, it is not configured as early |
| * as it is set, but rather only when a non-shared instance |
| * is constructed by <code>ObjectMapper</code> (or -Reader |
| * or -Writer) |
| *<p> |
| * Note: this is the only property left as non-final, to allow |
| * lazy construction of the instance as necessary. |
| * |
| * @since 1.6 |
| */ |
| protected SubtypeResolver _subtypeResolver; |
| |
| /* |
| /********************************************************** |
| /* Life-cycle: constructors |
| /********************************************************** |
| */ |
| |
| protected MapperConfig(ClassIntrospector<? extends BeanDescription> ci, AnnotationIntrospector ai, |
| VisibilityChecker<?> vc, SubtypeResolver str, PropertyNamingStrategy pns, TypeFactory tf, |
| HandlerInstantiator hi) |
| { |
| _base = new Base(ci, ai, vc, pns, tf, null, DEFAULT_DATE_FORMAT, hi); |
| _subtypeResolver = str; |
| // by default, assumed to be shared; only cleared when explicit copy is made |
| _mixInAnnotationsShared = true; |
| } |
| |
| /** |
| * Simple copy constructor |
| * |
| * @since 1.8 |
| */ |
| protected MapperConfig(MapperConfig<T> src) { |
| this(src, src._base, src._subtypeResolver); |
| } |
| |
| /** |
| * @since 1.8 |
| */ |
| protected MapperConfig(MapperConfig<T> src, MapperConfig.Base base, SubtypeResolver str) |
| { |
| _base = base; |
| _subtypeResolver = str; |
| // by default, assumed to be shared; only cleared when explicit copy is made |
| _mixInAnnotationsShared = true; |
| _mixInAnnotations = src._mixInAnnotations; |
| } |
| |
| /* |
| /********************************************************** |
| /* Life-cycle: factory methods |
| /********************************************************** |
| */ |
| |
| /** |
| * Method that checks class annotations that the argument Object has, |
| * and modifies settings of this configuration object accordingly, |
| * similar to how those annotations would affect actual value classes |
| * annotated with them, but with global scope. Note that not all |
| * annotations have global significance, and thus only subset of |
| * Jackson annotations will have any effect. |
| * |
| * @deprecated Since 1.9, it is preferably to explicitly configure |
| * instances; this method also modifies existing instance which is |
| * against immutable design goals of this class. |
| */ |
| @Deprecated |
| public abstract void fromAnnotations(Class<?> cls); |
| |
| /** |
| * Method to use for constructing an instance that is not shared |
| * between multiple operations but only used for a single one |
| * (which may be this instance, if it is immutable; if not, a copy |
| * is constructed with same settings) |
| * |
| * @since 1.8 |
| */ |
| public abstract T createUnshared(SubtypeResolver subtypeResolver); |
| |
| /** |
| * Method for constructing and returning a new instance with different |
| * {@link ClassIntrospector} |
| * to use. |
| *<p> |
| * NOTE: make sure to register new instance with <code>ObjectMapper</code> |
| * if directly calling this method. |
| * |
| * @since 1.8 |
| */ |
| public abstract T withClassIntrospector(ClassIntrospector<? extends BeanDescription> ci); |
| |
| /** |
| * Method for constructing and returning a new instance with different |
| * {@link AnnotationIntrospector} to use (replacing old one). |
| *<p> |
| * NOTE: make sure to register new instance with <code>ObjectMapper</code> |
| * if directly calling this method. |
| * |
| * @since 1.8 |
| */ |
| public abstract T withAnnotationIntrospector(AnnotationIntrospector ai); |
| |
| /** |
| * Method for constructing and returning a new instance with different |
| * {@link VisibilityChecker} |
| * to use. |
| *<p> |
| * NOTE: make sure to register new instance with <code>ObjectMapper</code> |
| * if directly calling this method. |
| * |
| * @since 1.8 |
| */ |
| public abstract T withVisibilityChecker(VisibilityChecker<?> vc); |
| |
| /** |
| * Method for constructing and returning a new instance with different |
| * minimal visibility level for specified property type |
| *<p> |
| * NOTE: make sure to register new instance with <code>ObjectMapper</code> |
| * if directly calling this method. |
| * |
| * @since 1.9 |
| */ |
| public abstract T withVisibility(JsonMethod forMethod, JsonAutoDetect.Visibility visibility); |
| |
| /** |
| * Method for constructing and returning a new instance with different |
| * {@link TypeResolverBuilder} |
| * to use. |
| *<p> |
| * NOTE: make sure to register new instance with <code>ObjectMapper</code> |
| * if directly calling this method. |
| * |
| * @since 1.8 |
| */ |
| public abstract T withTypeResolverBuilder(TypeResolverBuilder<?> trb); |
| |
| /** |
| * Method for constructing and returning a new instance with different |
| * {@link SubtypeResolver} |
| * to use. |
| *<p> |
| * NOTE: make sure to register new instance with <code>ObjectMapper</code> |
| * if directly calling this method. |
| * |
| * @since 1.8 |
| */ |
| public abstract T withSubtypeResolver(SubtypeResolver str); |
| |
| /** |
| * Method for constructing and returning a new instance with different |
| * {@link PropertyNamingStrategy} |
| * to use. |
| *<p> |
| * NOTE: make sure to register new instance with <code>ObjectMapper</code> |
| * if directly calling this method. |
| * |
| * @since 1.8 |
| */ |
| public abstract T withPropertyNamingStrategy(PropertyNamingStrategy strategy); |
| |
| /** |
| * Method for constructing and returning a new instance with different |
| * {@link TypeFactory} |
| * to use. |
| *<p> |
| * NOTE: make sure to register new instance with <code>ObjectMapper</code> |
| * if directly calling this method. |
| * |
| * @since 1.8 |
| */ |
| public abstract T withTypeFactory(TypeFactory typeFactory); |
| |
| /** |
| * Method for constructing and returning a new instance with different |
| * {@link DateFormat} |
| * to use. |
| *<p> |
| * NOTE: make sure to register new instance with <code>ObjectMapper</code> |
| * if directly calling this method. |
| * |
| * @since 1.8 |
| */ |
| public abstract T withDateFormat(DateFormat df); |
| |
| /** |
| * Method for constructing and returning a new instance with different |
| * {@link HandlerInstantiator} |
| * to use. |
| *<p> |
| * NOTE: make sure to register new instance with <code>ObjectMapper</code> |
| * if directly calling this method. |
| * |
| * @since 1.8 |
| */ |
| public abstract T withHandlerInstantiator(HandlerInstantiator hi); |
| |
| /** |
| * Method for constructing and returning a new instance with additional |
| * {@link AnnotationIntrospector} inserted (as the highest priority one) |
| * |
| * @since 1.9 |
| */ |
| public abstract T withInsertedAnnotationIntrospector(AnnotationIntrospector introspector); |
| |
| /** |
| * Method for constructing and returning a new instance with additional |
| * {@link AnnotationIntrospector} appended (as the lowest priority one) |
| * |
| * @since 1.9 |
| */ |
| public abstract T withAppendedAnnotationIntrospector(AnnotationIntrospector introspector); |
| |
| /* |
| /********************************************************** |
| /* Configuration: simple features |
| /********************************************************** |
| */ |
| |
| /** |
| * Method for checking whether given feature is enabled or not |
| */ |
| public abstract boolean isEnabled(ConfigFeature f); |
| |
| /** |
| * Method for determining whether annotation processing is enabled or not |
| * (default settings are typically that it is enabled; must explicitly disable). |
| * |
| * @return True if annotation processing is enabled; false if not |
| * |
| * @since 1.8 |
| */ |
| public abstract boolean isAnnotationProcessingEnabled(); |
| |
| /** |
| * Accessor for determining whether it is ok to try to force override of access |
| * modifiers to be able to get or set values of non-public Methods, Fields; |
| * to invoke non-public Constructors, Methods; or to instantiate non-public |
| * Classes. By default this is enabled, but on some platforms it needs to be |
| * prevented since if this would violate security constraints and cause failures. |
| * |
| * @return True if access modifier overriding is allowed (and may be done for |
| * any Field, Method, Constructor or Class); false to prevent any attempts |
| * to override. |
| * |
| * @since 1.8 |
| */ |
| public abstract boolean canOverrideAccessModifiers(); |
| |
| /** |
| * Accessor for checking whether default settings for property handling |
| * indicate that properties should be alphabetically ordered or not. |
| * |
| * @since 1.9 |
| */ |
| public abstract boolean shouldSortPropertiesAlphabetically(); |
| |
| /* |
| /********************************************************** |
| /* Configuration: introspectors, mix-ins |
| /********************************************************** |
| */ |
| |
| public ClassIntrospector<? extends BeanDescription> getClassIntrospector() { |
| return _base.getClassIntrospector(); |
| } |
| |
| /** |
| * Method for getting {@link AnnotationIntrospector} configured |
| * to introspect annotation values used for configuration. |
| *<p> |
| * Non-final since it is actually overridden by sub-classes (for now?) |
| */ |
| public AnnotationIntrospector getAnnotationIntrospector() { |
| return _base.getAnnotationIntrospector(); |
| } |
| |
| /** |
| * Method for registering specified {@link AnnotationIntrospector} as the highest |
| * priority introspector (will be chained with existing introspector(s) which |
| * will be used as fallbacks for cases this introspector does not handle) |
| * |
| * @param introspector Annotation introspector to register. |
| * |
| * @since 1.7 |
| * |
| * @deprecated Since 1.9 use {@link #withInsertedAnnotationIntrospector(AnnotationIntrospector)} instead; |
| * this method is deprecated as it changes state, preventing immutability of instances |
| */ |
| @Deprecated |
| public final void insertAnnotationIntrospector(AnnotationIntrospector introspector) { |
| _base = _base.withAnnotationIntrospector(AnnotationIntrospector.Pair.create(introspector, |
| getAnnotationIntrospector())); |
| } |
| |
| /** |
| * Method for registering specified {@link AnnotationIntrospector} as the lowest |
| * priority introspector, chained with existing introspector(s) and called |
| * as fallback for cases not otherwise handled. |
| * |
| * @param introspector Annotation introspector to register. |
| * |
| * @since 1.7 |
| * |
| * @deprecated Since 1.9 use {@link #withAppendedAnnotationIntrospector(AnnotationIntrospector)} instead; |
| * this method is deprecated as it changes state, preventing immutability of instances |
| */ |
| @Deprecated |
| public final void appendAnnotationIntrospector(AnnotationIntrospector introspector) { |
| _base = _base.withAnnotationIntrospector(AnnotationIntrospector.Pair.create(getAnnotationIntrospector(), |
| introspector)); |
| } |
| |
| /** |
| * Accessor for object used for determining whether specific property elements |
| * (method, constructors, fields) can be auto-detected based on |
| * their visibility (access modifiers). Can be changed to allow |
| * different minimum visibility levels for auto-detection. Note |
| * that this is the global handler; individual types (classes) |
| * can further override active checker used (using |
| * {@link JsonAutoDetect} annotation) |
| * |
| * @since 1.5 |
| */ |
| public VisibilityChecker<?> getDefaultVisibilityChecker() { |
| return _base.getVisibilityChecker(); |
| } |
| |
| /** |
| * @since 1.8 |
| */ |
| public final PropertyNamingStrategy getPropertyNamingStrategy() { |
| return _base.getPropertyNamingStrategy(); |
| } |
| |
| /** |
| * @since 1.8 |
| */ |
| public final HandlerInstantiator getHandlerInstantiator() { |
| return _base.getHandlerInstantiator(); |
| } |
| |
| /* |
| /********************************************************** |
| /* Configuration: mix-in annotations |
| /********************************************************** |
| */ |
| |
| /** |
| * Method to use for defining mix-in annotations to use for augmenting |
| * annotations that processable (serializable / deserializable) |
| * classes have. |
| * Mixing in is done when introspecting class annotations and properties. |
| * Map passed contains keys that are target classes (ones to augment |
| * with new annotation overrides), and values that are source classes |
| * (have annotations to use for augmentation). |
| * Annotations from source classes (and their supertypes) |
| * will <b>override</b> |
| * annotations that target classes (and their super-types) have. |
| * |
| * @since 1.2 |
| */ |
| public final void setMixInAnnotations(Map<Class<?>, Class<?>> sourceMixins) |
| { |
| HashMap<ClassKey,Class<?>> mixins = null; |
| if (sourceMixins != null && sourceMixins.size() > 0) { |
| mixins = new HashMap<ClassKey,Class<?>>(sourceMixins.size()); |
| for (Map.Entry<Class<?>,Class<?>> en : sourceMixins.entrySet()) { |
| mixins.put(new ClassKey(en.getKey()), en.getValue()); |
| } |
| } |
| _mixInAnnotationsShared = false; |
| _mixInAnnotations = mixins; |
| } |
| |
| /** |
| * Method to use for adding mix-in annotations to use for augmenting |
| * specified class or interface. All annotations from |
| * <code>mixinSource</code> are taken to override annotations |
| * that <code>target</code> (or its supertypes) has. |
| * |
| * @since 1.2 |
| * |
| * @param target Class (or interface) whose annotations to effectively override |
| * @param mixinSource Class (or interface) whose annotations are to |
| * be "added" to target's annotations, overriding as necessary |
| */ |
| public final void addMixInAnnotations(Class<?> target, Class<?> mixinSource) |
| { |
| if (_mixInAnnotations == null) { |
| _mixInAnnotationsShared = false; |
| _mixInAnnotations = new HashMap<ClassKey,Class<?>>(); |
| } else if (_mixInAnnotationsShared) { |
| _mixInAnnotationsShared = false; |
| _mixInAnnotations = new HashMap<ClassKey,Class<?>>(_mixInAnnotations); |
| } |
| _mixInAnnotations.put(new ClassKey(target), mixinSource); |
| } |
| |
| // ClassIntrospector.MixInResolver impl: |
| |
| /** |
| * Method that will check if there are "mix-in" classes (with mix-in |
| * annotations) for given class |
| * |
| * @since 1.2 |
| */ |
| @Override |
| public final Class<?> findMixInClassFor(Class<?> cls) { |
| return (_mixInAnnotations == null) ? null : _mixInAnnotations.get(new ClassKey(cls)); |
| } |
| |
| /** |
| * @since 1.8.1 |
| */ |
| public final int mixInCount() { |
| return (_mixInAnnotations == null) ? 0 : _mixInAnnotations.size(); |
| } |
| |
| /* |
| /********************************************************** |
| /* Configuration: type and subtype handling |
| /********************************************************** |
| */ |
| |
| /** |
| * Method called to locate a type info handler for types that do not have |
| * one explicitly declared via annotations (or other configuration). |
| * If such default handler is configured, it is returned; otherwise |
| * null is returned. |
| * |
| * @since 1.5 |
| */ |
| public final TypeResolverBuilder<?> getDefaultTyper(JavaType baseType) { |
| return _base.getTypeResolverBuilder(); |
| } |
| |
| /** |
| * Accessor for object used for finding out all reachable subtypes |
| * for supertypes; needed when a logical type name is used instead |
| * of class name (or custom scheme). |
| * |
| * @since 1.6 |
| */ |
| public final SubtypeResolver getSubtypeResolver() { |
| if (_subtypeResolver == null) { |
| _subtypeResolver = new StdSubtypeResolver(); |
| } |
| return _subtypeResolver; |
| } |
| |
| /** |
| * @since 1.8 |
| */ |
| public final TypeFactory getTypeFactory() { |
| return _base.getTypeFactory(); |
| } |
| |
| /** |
| * Helper method that will construct {@link JavaType} for given |
| * raw class. |
| * This is a simple short-cut for: |
| *<pre> |
| * getTypeFactory().constructType(cls); |
| *</pre> |
| * |
| * @since 1.8 |
| */ |
| public final JavaType constructType(Class<?> cls) { |
| return getTypeFactory().constructType(cls, (TypeBindings) null); |
| } |
| |
| /** |
| * Helper method that will construct {@link JavaType} for given |
| * type reference |
| * This is a simple short-cut for: |
| *<pre> |
| * getTypeFactory().constructType(valueTypeRef); |
| *</pre> |
| * |
| * @since 1.9 |
| */ |
| public final JavaType constructType(TypeReference<?> valueTypeRef) { |
| return getTypeFactory().constructType(valueTypeRef.getType(), (TypeBindings) null); |
| } |
| |
| /** |
| * @since 1.9.1 |
| */ |
| public JavaType constructSpecializedType(JavaType baseType, Class<?> subclass) { |
| return getTypeFactory().constructSpecializedType(baseType, subclass); |
| } |
| |
| /* |
| /********************************************************** |
| /* Configuration: other |
| /********************************************************** |
| */ |
| |
| /** |
| * Method for accessing currently configured (textual) date format |
| * that will be used for reading or writing date values (in case |
| * of writing, only if textual output is configured; not if dates |
| * are to be serialized as time stamps). |
| *<p> |
| * Note that typically {@link DateFormat} instances are <b>not thread-safe</b> |
| * (at least ones provided by JDK): |
| * this means that calling code should clone format instance before |
| * using it. |
| *<p> |
| * This method is usually only called by framework itself, since there |
| * are convenience methods available via |
| * {@link DeserializationContext} and {@link SerializerProvider} that |
| * take care of cloning and thread-safe reuse. |
| */ |
| public final DateFormat getDateFormat() { return _base.getDateFormat(); } |
| |
| /** |
| * Accessor for getting bean description that only contains class |
| * annotations: useful if no getter/setter/creator information is needed. |
| * |
| * @since 1.7 |
| */ |
| @SuppressWarnings("unchecked") |
| public <DESC extends BeanDescription> DESC introspectClassAnnotations(Class<?> cls) { |
| return (DESC) introspectClassAnnotations(constructType(cls)); |
| } |
| |
| /** |
| * Accessor for getting bean description that only contains class |
| * annotations: useful if no getter/setter/creator information is needed. |
| * |
| * @since 1.9 |
| */ |
| public abstract <DESC extends BeanDescription> DESC introspectClassAnnotations(JavaType type); |
| |
| /** |
| * 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. |
| * |
| * @since 1.7 |
| */ |
| @SuppressWarnings("unchecked") |
| public <DESC extends BeanDescription> DESC introspectDirectClassAnnotations(Class<?> cls) { |
| return (DESC) introspectDirectClassAnnotations(constructType(cls)); |
| } |
| /** |
| * 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. |
| */ |
| public abstract <DESC extends BeanDescription> DESC introspectDirectClassAnnotations(JavaType type); |
| |
| /* |
| /********************************************************** |
| /* Methods for instantiating handlers |
| /********************************************************** |
| */ |
| |
| /** |
| * Method that can be called to obtain an instance of <code>TypeIdResolver</code> of |
| * specified type. |
| * |
| * @since 1.8 |
| */ |
| public TypeResolverBuilder<?> typeResolverBuilderInstance(Annotated annotated, |
| Class<? extends TypeResolverBuilder<?>> builderClass) |
| { |
| HandlerInstantiator hi = getHandlerInstantiator(); |
| if (hi != null) { |
| TypeResolverBuilder<?> builder = hi.typeResolverBuilderInstance(this, annotated, builderClass); |
| if (builder != null) { |
| return builder; |
| } |
| } |
| return (TypeResolverBuilder<?>) ClassUtil.createInstance(builderClass, canOverrideAccessModifiers()); |
| } |
| |
| /** |
| * Method that can be called to obtain an instance of <code>TypeIdResolver</code> of |
| * specified type. |
| * |
| * @since 1.8 |
| */ |
| public TypeIdResolver typeIdResolverInstance(Annotated annotated, |
| Class<? extends TypeIdResolver> resolverClass) |
| { |
| HandlerInstantiator hi = getHandlerInstantiator(); |
| if (hi != null) { |
| TypeIdResolver builder = hi.typeIdResolverInstance(this, annotated, resolverClass); |
| if (builder != null) { |
| return builder; |
| } |
| } |
| return (TypeIdResolver) ClassUtil.createInstance(resolverClass, canOverrideAccessModifiers()); |
| } |
| |
| /* |
| /********************************************************** |
| /* Deprecated methods |
| /********************************************************** |
| */ |
| |
| /** |
| * Method for replacing existing annotation introspector(s) with specified |
| * introspector. |
| * Since this method modifies state of configuration object directly, its use |
| * is not recommended. |
| * |
| * @deprecated Since 1.8, use either |
| * {@link #withAnnotationIntrospector(AnnotationIntrospector)} or |
| * Module API instead |
| */ |
| @Deprecated |
| public final void setAnnotationIntrospector(AnnotationIntrospector ai) { |
| _base = _base.withAnnotationIntrospector(ai); |
| } |
| |
| /** |
| * Method that will define specific date format to use for reading/writing |
| * Date and Calendar values. |
| * If null is passed, will use {@link StdDateFormat}. |
| * Instance is used as is, without creating a clone. |
| * Format object in use can be accessed using {@link #getDateFormat}. |
| * |
| * @param df Date format to use, if not null; if null, the default format |
| * will be used |
| * |
| * @deprecated As of version 1.8, it is preferable to call method in |
| * {@link ObjectMapper} instead; or construct new instance with |
| * {@link #withDateFormat(DateFormat)} |
| */ |
| @Deprecated |
| public void setDateFormat(DateFormat df) { |
| if (df == null) { |
| df = DEFAULT_DATE_FORMAT; |
| } |
| _base = _base.withDateFormat(df); |
| } |
| |
| /* |
| /********************************************************** |
| /* Helper interface used with simple on/off features |
| /********************************************************** |
| */ |
| |
| /** |
| * Interface that actual Feature enumerations used by |
| * {@link MapperConfig} implementations must implement. |
| * Necessary since enums can not be extended using normal |
| * inheritance, but can implement interfaces |
| * |
| * @since 1.9 |
| */ |
| public interface ConfigFeature |
| { |
| /** |
| * Accessor for checking whether this feature is enabled by default. |
| */ |
| public boolean enabledByDefault(); |
| |
| /** |
| * Returns bit mask for this feature instance |
| */ |
| public int getMask(); |
| } |
| |
| /* |
| /********************************************************** |
| /* Helper class to contain basic state needed to implement |
| /* MapperConfig. |
| /********************************************************** |
| */ |
| |
| /** |
| * Immutable container class used to store simple configuration |
| * settings. Since instances are fully immutable, instances can |
| * be freely shared and used without synchronization. |
| */ |
| public static class Base |
| { |
| /* |
| /********************************************************** |
| /* Configuration settings; introspection, related |
| /********************************************************** |
| */ |
| |
| /** |
| * Introspector used to figure out Bean properties needed for bean serialization |
| * and deserialization. Overridable so that it is possible to change low-level |
| * details of introspection, like adding new annotation types. |
| */ |
| protected final ClassIntrospector<? extends BeanDescription> _classIntrospector; |
| |
| /** |
| * Introspector used for accessing annotation value based configuration. |
| */ |
| protected final AnnotationIntrospector _annotationIntrospector; |
| |
| /** |
| * Object used for determining whether specific property elements |
| * (method, constructors, fields) can be auto-detected based on |
| * their visibility (access modifiers). Can be changed to allow |
| * different minimum visibility levels for auto-detection. Note |
| * that this is the global handler; individual types (classes) |
| * can further override active checker used (using |
| * {@link JsonAutoDetect} annotation) |
| * |
| * @since 1.5 |
| */ |
| protected final VisibilityChecker<?> _visibilityChecker; |
| |
| /** |
| * Custom property naming strategy in use, if any. |
| * |
| * @since 1.8 |
| */ |
| protected final PropertyNamingStrategy _propertyNamingStrategy; |
| |
| /** |
| * Specific factory used for creating {@link JavaType} instances; |
| * needed to allow modules to add more custom type handling |
| * (mostly to support types of non-Java JVM languages) |
| */ |
| protected final TypeFactory _typeFactory; |
| |
| /* |
| /********************************************************** |
| /* Configuration settings; type resolution |
| /********************************************************** |
| */ |
| |
| /** |
| * Type information handler used for "untyped" values (ones declared |
| * to have type <code>Object.class</code>) |
| * |
| * @since 1.5 |
| */ |
| protected final TypeResolverBuilder<?> _typeResolverBuilder; |
| |
| /* |
| /********************************************************** |
| /* Configuration settings; other |
| /********************************************************** |
| */ |
| |
| /** |
| * Custom date format to use for de-serialization. If specified, will be |
| * used instead of {@link org.codehaus.jackson.map.util.StdDateFormat}. |
| *<p> |
| * Note that the configured format object will be cloned once per |
| * deserialization process (first time it is needed) |
| */ |
| protected final DateFormat _dateFormat; |
| |
| /** |
| * Object used for creating instances of handlers (serializers, deserializers, |
| * type and type id resolvers), given class to instantiate. This is typically |
| * used to do additional configuration (with dependency injection, for example) |
| * beyond simply construction of instances; or to use alternative constructors. |
| */ |
| protected final HandlerInstantiator _handlerInstantiator; |
| |
| /* |
| /********************************************************** |
| /* Construction |
| /********************************************************** |
| */ |
| |
| public Base(ClassIntrospector<? extends BeanDescription> ci, AnnotationIntrospector ai, |
| VisibilityChecker<?> vc, PropertyNamingStrategy pns, TypeFactory tf, |
| TypeResolverBuilder<?> typer, DateFormat dateFormat, HandlerInstantiator hi) |
| { |
| _classIntrospector = ci; |
| _annotationIntrospector = ai; |
| _visibilityChecker = vc; |
| _propertyNamingStrategy = pns; |
| _typeFactory = tf; |
| _typeResolverBuilder = typer; |
| _dateFormat = dateFormat; |
| _handlerInstantiator = hi; |
| } |
| |
| /* |
| /********************************************************** |
| /* Factory methods |
| /********************************************************** |
| */ |
| |
| public Base withClassIntrospector(ClassIntrospector<? extends BeanDescription> ci) { |
| return new Base(ci, _annotationIntrospector, _visibilityChecker, _propertyNamingStrategy, _typeFactory, |
| _typeResolverBuilder, _dateFormat, _handlerInstantiator); |
| } |
| |
| public Base withAnnotationIntrospector(AnnotationIntrospector ai) { |
| return new Base(_classIntrospector, ai, _visibilityChecker, _propertyNamingStrategy, _typeFactory, |
| _typeResolverBuilder, _dateFormat, _handlerInstantiator); |
| } |
| |
| public Base withInsertedAnnotationIntrospector(AnnotationIntrospector ai) { |
| return withAnnotationIntrospector(AnnotationIntrospector.Pair.create(ai, _annotationIntrospector)); |
| } |
| |
| public Base withAppendedAnnotationIntrospector(AnnotationIntrospector ai) { |
| return withAnnotationIntrospector(AnnotationIntrospector.Pair.create(_annotationIntrospector, ai)); |
| } |
| |
| public Base withVisibilityChecker(VisibilityChecker<?> vc) { |
| return new Base(_classIntrospector, _annotationIntrospector, vc, _propertyNamingStrategy, _typeFactory, |
| _typeResolverBuilder, _dateFormat, _handlerInstantiator); |
| } |
| |
| public Base withVisibility(JsonMethod forMethod, JsonAutoDetect.Visibility visibility) { |
| return new Base(_classIntrospector, _annotationIntrospector, |
| _visibilityChecker.withVisibility(forMethod, visibility), |
| _propertyNamingStrategy, _typeFactory, |
| _typeResolverBuilder, _dateFormat, _handlerInstantiator); |
| } |
| |
| public Base withPropertyNamingStrategy(PropertyNamingStrategy pns) { |
| return new Base(_classIntrospector, _annotationIntrospector, _visibilityChecker, pns, _typeFactory, |
| _typeResolverBuilder, _dateFormat, _handlerInstantiator); |
| } |
| |
| public Base withTypeFactory(TypeFactory tf) { |
| return new Base(_classIntrospector, _annotationIntrospector, _visibilityChecker, _propertyNamingStrategy, tf, |
| _typeResolverBuilder, _dateFormat, _handlerInstantiator); |
| } |
| |
| public Base withTypeResolverBuilder(TypeResolverBuilder<?> typer) { |
| return new Base(_classIntrospector, _annotationIntrospector, _visibilityChecker, _propertyNamingStrategy, _typeFactory, |
| typer, _dateFormat, _handlerInstantiator); |
| } |
| |
| public Base withDateFormat(DateFormat df) { |
| return new Base(_classIntrospector, _annotationIntrospector, _visibilityChecker, _propertyNamingStrategy, _typeFactory, |
| _typeResolverBuilder, df, _handlerInstantiator); |
| } |
| |
| public Base withHandlerInstantiator(HandlerInstantiator hi) { |
| return new Base(_classIntrospector, _annotationIntrospector, _visibilityChecker, _propertyNamingStrategy, _typeFactory, |
| _typeResolverBuilder, _dateFormat, hi); |
| } |
| |
| /* |
| /********************************************************** |
| /* API |
| /********************************************************** |
| */ |
| |
| public ClassIntrospector<? extends BeanDescription> getClassIntrospector() { |
| return _classIntrospector; |
| } |
| |
| public AnnotationIntrospector getAnnotationIntrospector() { |
| return _annotationIntrospector; |
| } |
| |
| |
| public VisibilityChecker<?> getVisibilityChecker() { |
| return _visibilityChecker; |
| } |
| |
| public PropertyNamingStrategy getPropertyNamingStrategy() { |
| return _propertyNamingStrategy; |
| } |
| |
| public TypeFactory getTypeFactory() { |
| return _typeFactory; |
| } |
| |
| public TypeResolverBuilder<?> getTypeResolverBuilder() { |
| return _typeResolverBuilder; |
| } |
| |
| public DateFormat getDateFormat() { |
| return _dateFormat; |
| } |
| |
| public HandlerInstantiator getHandlerInstantiator() { |
| return _handlerInstantiator; |
| } |
| } |
| |
| /* |
| /********************************************************** |
| /* Basic extension; added to avoid having to change generic |
| /* signature of MapperConfig |
| /* |
| /* NOTE: May be merge in MapperConfig for 2.0, depending |
| /* on how much we value backwards compatibility |
| /********************************************************** |
| */ |
| |
| static abstract class Impl<CFG extends MapperConfig.ConfigFeature, |
| T extends Impl<CFG,T>> |
| extends MapperConfig<T> |
| { |
| /** |
| *<p> |
| * Note: moved to base class in 1.9; was stored by sub-class earlier |
| */ |
| protected int _featureFlags; |
| |
| /* |
| /********************************************************** |
| /* Construction |
| /********************************************************** |
| */ |
| |
| protected Impl(ClassIntrospector<? extends BeanDescription> ci, AnnotationIntrospector ai, |
| VisibilityChecker<?> vc, SubtypeResolver str, PropertyNamingStrategy pns, TypeFactory tf, |
| HandlerInstantiator hi, |
| int defaultFeatures) |
| { |
| super(ci, ai, vc, str, pns, tf, hi); |
| _featureFlags = defaultFeatures; |
| } |
| |
| protected Impl(Impl<CFG,T> src) { |
| super(src); |
| _featureFlags = src._featureFlags; |
| } |
| |
| protected Impl(Impl<CFG,T> src, int features) { |
| super(src); |
| _featureFlags = features; |
| } |
| |
| /** |
| * @since 1.8 |
| */ |
| protected Impl(Impl<CFG,T> src, MapperConfig.Base base, SubtypeResolver str) |
| { |
| super(src, base, str); |
| _featureFlags = src._featureFlags; |
| } |
| |
| /** |
| * Method that calculates bit set (flags) of all features that |
| * are enabled by default. |
| */ |
| static <F extends Enum<F> & MapperConfig.ConfigFeature> int collectFeatureDefaults(Class<F> enumClass) |
| { |
| int flags = 0; |
| for (F value : enumClass.getEnumConstants()) { |
| if (value.enabledByDefault()) { |
| flags |= value.getMask(); |
| } |
| } |
| return flags; |
| } |
| |
| /* |
| /********************************************************** |
| /* Additional fluent-factory methods |
| /********************************************************** |
| */ |
| |
| /** |
| * Fluent factory method that will construct and return a new configuration |
| * object instance with specified features enabled. |
| * |
| * @since 1.9 |
| */ |
| public abstract T with(CFG... features); |
| |
| /** |
| * Fluent factory method that will construct and return a new configuration |
| * object instance with specified features disabled. |
| * |
| * @since 1.9 |
| */ |
| public abstract T without(CFG... features); |
| |
| /* |
| /********************************************************** |
| /* Configuration: simple features |
| /********************************************************** |
| */ |
| |
| /* NOTE: this method was added in 1.9, but should be |
| * removed from 2.0 -- overloads do not work nicely with |
| * enums, so we better not try |
| *<p> |
| * Also note that we can NOT use type variable CFG here, because |
| * non-generic base class had to use base type. |
| * |
| * @Deprecated |
| */ |
| @Override |
| public boolean isEnabled(MapperConfig.ConfigFeature f) { |
| return (_featureFlags & f.getMask()) != 0; |
| } |
| |
| /* |
| /********************************************************** |
| /* Configuration: deprecated methods |
| /********************************************************** |
| */ |
| |
| /** |
| * Method for enabling specified feature. |
| * |
| * @deprecated Since 1.9, it is preferable to use {@link #with} instead; |
| * this method is deprecated as it modifies current instance instead of |
| * creating a new one (as the goal is to make this class immutable) |
| */ |
| @Deprecated |
| public void enable(CFG f) { |
| _featureFlags |= f.getMask(); |
| } |
| |
| /** |
| * Method for disabling specified feature. |
| * |
| * @deprecated Since 1.9, it is preferable to use {@link #without} instead; |
| * this method is deprecated as it modifies current instance instead of |
| * creating a new one (as the goal is to make this class immutable) |
| */ |
| @Deprecated |
| public void disable(CFG f) { |
| _featureFlags &= ~f.getMask(); |
| } |
| |
| /** |
| * Method for enabling or disabling specified feature. |
| * |
| * @deprecated Since 1.9, it is preferable to use {@link #with} and |
| * {@link #without} methods instead; |
| * this method is deprecated as it modifies current instance instead of |
| * creating a new one (as the goal is to make this class immutable) |
| */ |
| @SuppressWarnings("deprecation") |
| @Deprecated |
| public void set(CFG f, boolean state) |
| { |
| if (state) { |
| enable(f); |
| } else { |
| disable(f); |
| } |
| } |
| } |
| } |