package com.fasterxml.jackson.databind.module; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.ValueInstantiator; import com.fasterxml.jackson.databind.jsontype.NamedType; /** * Simple {@link Module} implementation that allows registration * of serializers and deserializers, and bean serializer * and deserializer modifiers. */ public class SimpleModule extends Module implements java.io.Serializable { private static final long serialVersionUID = 3132264350026957446L; protected final String _name; protected final Version _version; protected SimpleSerializers _serializers = null; protected SimpleDeserializers _deserializers = null; protected SimpleSerializers _keySerializers = null; protected SimpleKeyDeserializers _keyDeserializers = null; /** * Lazily-constructed resolver used for storing mappings from * abstract classes to more specific implementing classes * (which may be abstract or concrete) */ protected SimpleAbstractTypeResolver _abstractTypes = null; /** * Lazily-constructed resolver used for storing mappings from * abstract classes to more specific implementing classes * (which may be abstract or concrete) */ protected SimpleValueInstantiators _valueInstantiators = null; /** * Lazily-constructed map that contains mix-in definitions, indexed * by target class, value being mix-in to apply. */ protected HashMap<Class<?>, Class<?>> _mixins = null; /** * Set of subtypes to register, if any. */ protected LinkedHashSet<NamedType> _subtypes = null; /* /********************************************************** /* Life-cycle: creation /********************************************************** */ /** * Constructors that should only be used for non-reusable * convenience modules used by app code: "real" modules should * use actual name and version number information. */ public SimpleModule() { // when passing 'this', can not chain constructors... _name = "SimpleModule-"+System.identityHashCode(this); _version = Version.unknownVersion(); } /** * Convenience constructor that will default version to * {@link Version#unknownVersion()}. */ public SimpleModule(String name) { this(name, Version.unknownVersion()); } /** * Convenience constructor that will use specified Version, * including name from {@link Version#getArtifactId()} */ public SimpleModule(Version version) { _name = version.getArtifactId(); _version = version; } /** * Constructor to use for actual reusable modules. * ObjectMapper may use name as identifier to notice attempts * for multiple registrations of the same module (although it * does not have to). * * @param name Unique name of the module * @param version Version of the module */ public SimpleModule(String name, Version version) { _name = name; _version = version; } /** * @since 2.1 */ public SimpleModule(String name, Version version, Map<Class<?>,JsonDeserializer<?>> deserializers) { this(name, version, deserializers, null); } /** * @since 2.1 */ public SimpleModule(String name, Version version, List<JsonSerializer<?>> serializers) { this(name, version, null, serializers); } /** * @since 2.1 */ public SimpleModule(String name, Version version, Map<Class<?>,JsonDeserializer<?>> deserializers, List<JsonSerializer<?>> serializers) { _name = name; _version = version; if (deserializers != null) { _deserializers = new SimpleDeserializers(deserializers); } if (serializers != null) { _serializers = new SimpleSerializers(serializers); } } /* /********************************************************** /* Simple setters to allow overriding /********************************************************** */ /** * Resets all currently configured serializers. */ public void setSerializers(SimpleSerializers s) { _serializers = s; } /** * Resets all currently configured deserializers. */ public void setDeserializers(SimpleDeserializers d) { _deserializers = d; } /** * Resets all currently configured key serializers. */ public void setKeySerializers(SimpleSerializers ks) { _keySerializers = ks; } /** * Resets all currently configured key deserializers. */ public void setKeyDeserializers(SimpleKeyDeserializers kd) { _keyDeserializers = kd; } /** * Resets currently configured abstract type mappings */ public void setAbstractTypes(SimpleAbstractTypeResolver atr) { _abstractTypes = atr; } /** * Resets all currently configured value instantiators */ public void setValueInstantiators(SimpleValueInstantiators svi) { _valueInstantiators = svi; } /* /********************************************************** /* Configuration methods /********************************************************** */ public SimpleModule addSerializer(JsonSerializer<?> ser) { if (_serializers == null) { _serializers = new SimpleSerializers(); } _serializers.addSerializer(ser); return this; } public <T> SimpleModule addSerializer(Class<? extends T> type, JsonSerializer<T> ser) { if (_serializers == null) { _serializers = new SimpleSerializers(); } _serializers.addSerializer(type, ser); return this; } public <T> SimpleModule addKeySerializer(Class<? extends T> type, JsonSerializer<T> ser) { if (_keySerializers == null) { _keySerializers = new SimpleSerializers(); } _keySerializers.addSerializer(type, ser); return this; } public <T> SimpleModule addDeserializer(Class<T> type, JsonDeserializer<? extends T> deser) { if (_deserializers == null) { _deserializers = new SimpleDeserializers(); } _deserializers.addDeserializer(type, deser); return this; } public SimpleModule addKeyDeserializer(Class<?> type, KeyDeserializer deser) { if (_keyDeserializers == null) { _keyDeserializers = new SimpleKeyDeserializers(); } _keyDeserializers.addDeserializer(type, deser); return this; } /** * Lazily-constructed resolver used for storing mappings from * abstract classes to more specific implementing classes * (which may be abstract or concrete) */ public <T> SimpleModule addAbstractTypeMapping(Class<T> superType, Class<? extends T> subType) { if (_abstractTypes == null) { _abstractTypes = new SimpleAbstractTypeResolver(); } // note: addMapping() will verify arguments _abstractTypes = _abstractTypes.addMapping(superType, subType); return this; } /** * Method for registering {@link ValueInstantiator} to use when deserializing * instances of type <code>beanType</code>. *<p> * Instantiator is * registered when module is registered for <code>ObjectMapper</code>. */ public SimpleModule addValueInstantiator(Class<?> beanType, ValueInstantiator inst) { if (_valueInstantiators == null) { _valueInstantiators = new SimpleValueInstantiators(); } _valueInstantiators = _valueInstantiators.addValueInstantiator(beanType, inst); return this; } /** * Method for adding set of subtypes to be registered with * {@link ObjectMapper} * this is an alternative to using annotations in super type to indicate subtypes. */ public SimpleModule registerSubtypes(Class<?> ... subtypes) { if (_subtypes == null) { _subtypes = new LinkedHashSet<NamedType>(Math.max(16, subtypes.length)); } for (Class<?> subtype : subtypes) { _subtypes.add(new NamedType(subtype)); } return this; } /** * Method for adding set of subtypes (along with type name to use) to be registered with * {@link ObjectMapper} * this is an alternative to using annotations in super type to indicate subtypes. */ public SimpleModule registerSubtypes(NamedType ... subtypes) { if (_subtypes == null) { _subtypes = new LinkedHashSet<NamedType>(Math.max(16, subtypes.length)); } for (NamedType subtype : subtypes) { _subtypes.add(subtype); } return this; } /** * Method for specifying that annotations define by <code>mixinClass</code> * should be "mixed in" with annotations that <code>targetType</code> * has (as if they were directly included on it!). *<p> * Mix-in annotations are * registered when module is registered for <code>ObjectMapper</code>. */ public SimpleModule setMixInAnnotation(Class<?> targetType, Class<?> mixinClass) { if (_mixins == null) { _mixins = new HashMap<Class<?>, Class<?>>(); } _mixins.put(targetType, mixinClass); return this; } /* /********************************************************** /* Module impl /********************************************************** */ @Override public String getModuleName() { return _name; } @Override public void setupModule(SetupContext context) { if (_serializers != null) { context.addSerializers(_serializers); } if (_deserializers != null) { context.addDeserializers(_deserializers); } if (_keySerializers != null) { context.addKeySerializers(_keySerializers); } if (_keyDeserializers != null) { context.addKeyDeserializers(_keyDeserializers); } if (_abstractTypes != null) { context.addAbstractTypeResolver(_abstractTypes); } if (_valueInstantiators != null) { context.addValueInstantiators(_valueInstantiators); } if (_subtypes != null && _subtypes.size() > 0) { context.registerSubtypes(_subtypes.toArray(new NamedType[_subtypes.size()])); } if (_mixins != null) { for (Map.Entry<Class<?>,Class<?>> entry : _mixins.entrySet()) { context.setMixInAnnotations(entry.getKey(), entry.getValue()); } } } @Override public Version version() { return _version; } }