package com.fasterxml.jackson.databind.cfg; import java.text.DateFormat; import java.util.Locale; import java.util.TimeZone; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.Base64Variant; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.introspect.Annotated; import com.fasterxml.jackson.databind.introspect.ClassIntrospector; import com.fasterxml.jackson.databind.introspect.VisibilityChecker; import com.fasterxml.jackson.databind.jsontype.SubtypeResolver; import com.fasterxml.jackson.databind.jsontype.TypeIdResolver; import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder; import com.fasterxml.jackson.databind.type.TypeBindings; import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.databind.util.ClassUtil; /** * Interface that defines functionality accessible through both * serialization and deserialization configuration objects; * accessors to mode-independent configuration settings * and such. * In addition, shared features are defined * in {@link MapperFeature}. *<p> * Small part of implementation is included here by aggregating * {@link BaseSettings} instance that contains configuration * that is shared between different types of instances. */ public abstract class MapperConfig<T extends MapperConfig<T>> implements ClassIntrospector.MixInResolver, java.io.Serializable { private static final long serialVersionUID = 8891625428805876137L; /** * Set of shared mapper features enabled. */ protected final int _mapperFeatures; /** * Immutable container object for simple configuration settings. */ protected final BaseSettings _base; /* /********************************************************** /* Life-cycle: constructors /********************************************************** */ protected MapperConfig(BaseSettings base, int mapperFeatures) { _base = base; _mapperFeatures = mapperFeatures; } protected MapperConfig(MapperConfig<T> src) { _base = src._base; _mapperFeatures = src._mapperFeatures; } /** * Method that calculates bit set (flags) of all features that * are enabled by default. */ public static <F extends Enum<F> & ConfigFeature> int collectFeatureDefaults(Class<F> enumClass) { int flags = 0; for (F value : enumClass.getEnumConstants()) { if (value.enabledByDefault()) { flags |= value.getMask(); } } return flags; } /* /********************************************************** /* Life-cycle: factory methods /********************************************************** */ /** * Method for constructing and returning a new instance with specified * mapper features enabled. */ public abstract T with(MapperFeature... features); /** * Method for constructing and returning a new instance with specified * mapper features disabled. */ public abstract T without(MapperFeature... features); /* /********************************************************** /* Configuration: simple features /********************************************************** */ /** * Accessor for simple mapper features (which are shared for * serialization, deserialization) */ public final boolean isEnabled(MapperFeature f) { return (_mapperFeatures & f.getMask()) != 0; } /** * 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 */ public final boolean isAnnotationProcessingEnabled() { return isEnabled(MapperFeature.USE_ANNOTATIONS); } /** * 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. */ public final boolean canOverrideAccessModifiers() { return isEnabled(MapperFeature.CAN_OVERRIDE_ACCESS_MODIFIERS); } /** * Accessor for checking whether default settings for property handling * indicate that properties should be alphabetically ordered or not. */ public final boolean shouldSortPropertiesAlphabetically() { return isEnabled(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY); } /** * Accessor for checking whether configuration indicates that * "root wrapping" (use of an extra property/name pair at root level) * is expected or not. */ public abstract boolean useRootWrapping(); /* /********************************************************** /* Configuration: introspectors, mix-ins /********************************************************** */ public ClassIntrospector 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(); } /** * 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) */ public VisibilityChecker<?> getDefaultVisibilityChecker() { return _base.getVisibilityChecker(); } public final PropertyNamingStrategy getPropertyNamingStrategy() { return _base.getPropertyNamingStrategy(); } public final HandlerInstantiator getHandlerInstantiator() { return _base.getHandlerInstantiator(); } /* /********************************************************** /* 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. */ public final TypeResolverBuilder<?> getDefaultTyper(JavaType baseType) { return _base.getTypeResolverBuilder(); } public abstract SubtypeResolver getSubtypeResolver(); 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> */ 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> */ public final JavaType constructType(TypeReference<?> valueTypeRef) { return getTypeFactory().constructType(valueTypeRef.getType(), (TypeBindings) null); } public JavaType constructSpecializedType(JavaType baseType, Class<?> subclass) { return getTypeFactory().constructSpecializedType(baseType, subclass); } /* /********************************************************** /* Configuration: introspection support /********************************************************** */ /** * Accessor for getting bean description that only contains class * annotations: useful if no getter/setter/creator information is needed. */ public BeanDescription introspectClassAnnotations(Class<?> cls) { return introspectClassAnnotations(constructType(cls)); } /** * Accessor for getting bean description that only contains class * annotations: useful if no getter/setter/creator information is needed. */ public abstract BeanDescription 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. */ public BeanDescription introspectDirectClassAnnotations(Class<?> cls) { return 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 BeanDescription introspectDirectClassAnnotations(JavaType type); /* /********************************************************** /* 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(); } /** * Method for accessing the default {@link java.util.Locale} to use * for formatting, unless overridden by local annotations. * Initially set to {@link Locale#getDefault()}. */ public final Locale getLocale() { return _base.getLocale(); } /** * Method for accessing the default {@link java.util.TimeZone} to use * for formatting, unless overridden by local annotations. * Initially set to {@link TimeZone#getDefault()}. */ public final TimeZone getTimeZone() { return _base.getTimeZone(); } /** * Accessor for finding currently active view, if any (null if none) */ public abstract Class<?> getActiveView(); /** * 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); but this can * be configured on {@link ObjectWriter}. */ public Base64Variant getBase64Variant() { return _base.getBase64Variant(); } /* /********************************************************** /* Methods for instantiating handlers /********************************************************** */ /** * Method that can be called to obtain an instance of <code>TypeIdResolver</code> of * specified type. */ 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. */ 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()); } }