| package com.fasterxml.jackson.databind.introspect; |
| |
| import com.fasterxml.jackson.databind.AnnotationIntrospector; |
| import com.fasterxml.jackson.databind.DeserializationConfig; |
| import com.fasterxml.jackson.databind.JavaType; |
| import com.fasterxml.jackson.databind.SerializationConfig; |
| import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; |
| import com.fasterxml.jackson.databind.cfg.MapperConfig; |
| import com.fasterxml.jackson.databind.type.SimpleType; |
| |
| public class BasicClassIntrospector |
| extends ClassIntrospector |
| implements java.io.Serializable |
| { |
| private static final long serialVersionUID = 1L; |
| |
| /* We keep a small set of pre-constructed descriptions to use for |
| * common non-structured values, such as Numbers and Strings. |
| * This is strictly performance optimization to reduce what is |
| * usually one-time cost, but seems useful for some cases considering |
| * simplicity. |
| */ |
| |
| protected final static BasicBeanDescription STRING_DESC; |
| static { |
| AnnotatedClass ac = AnnotatedClass.constructWithoutSuperTypes(String.class, null, null); |
| STRING_DESC = BasicBeanDescription.forOtherUse(null, SimpleType.constructUnsafe(String.class), ac); |
| } |
| protected final static BasicBeanDescription BOOLEAN_DESC; |
| static { |
| AnnotatedClass ac = AnnotatedClass.constructWithoutSuperTypes(Boolean.TYPE, null, null); |
| BOOLEAN_DESC = BasicBeanDescription.forOtherUse(null, SimpleType.constructUnsafe(Boolean.TYPE), ac); |
| } |
| protected final static BasicBeanDescription INT_DESC; |
| static { |
| AnnotatedClass ac = AnnotatedClass.constructWithoutSuperTypes(Integer.TYPE, null, null); |
| INT_DESC = BasicBeanDescription.forOtherUse(null, SimpleType.constructUnsafe(Integer.TYPE), ac); |
| } |
| protected final static BasicBeanDescription LONG_DESC; |
| static { |
| AnnotatedClass ac = AnnotatedClass.constructWithoutSuperTypes(Long.TYPE, null, null); |
| LONG_DESC = BasicBeanDescription.forOtherUse(null, SimpleType.constructUnsafe(Long.TYPE), ac); |
| } |
| |
| /* |
| /********************************************************** |
| /* Life cycle |
| /********************************************************** |
| */ |
| |
| public final static BasicClassIntrospector instance = new BasicClassIntrospector(); |
| |
| public BasicClassIntrospector() { } |
| |
| /* |
| /********************************************************** |
| /* Factory method impls |
| /********************************************************** |
| */ |
| |
| @Override |
| public BasicBeanDescription forSerialization(SerializationConfig cfg, |
| JavaType type, MixInResolver r) |
| { |
| // minor optimization: for JDK types do minimal introspection |
| BasicBeanDescription desc = _findCachedDesc(type); |
| if (desc == null) { |
| desc = BasicBeanDescription.forSerialization(collectProperties(cfg, |
| type, r, true, "set")); |
| } |
| return desc; |
| } |
| |
| @Override |
| public BasicBeanDescription forDeserialization(DeserializationConfig cfg, |
| JavaType type, MixInResolver r) |
| { |
| // minor optimization: for JDK types do minimal introspection |
| BasicBeanDescription desc = _findCachedDesc(type); |
| if (desc == null) { |
| desc = BasicBeanDescription.forDeserialization(collectProperties(cfg, |
| type, r, false, "set")); |
| } |
| return desc; |
| } |
| |
| @Override |
| public BasicBeanDescription forDeserializationWithBuilder(DeserializationConfig cfg, |
| JavaType type, MixInResolver r) |
| { |
| // no caching for Builders (no standard JDK builder types): |
| return BasicBeanDescription.forDeserialization(collectPropertiesWithBuilder(cfg, |
| type, r, false)); |
| } |
| |
| @Override |
| public BasicBeanDescription forCreation(DeserializationConfig cfg, |
| JavaType type, MixInResolver r) |
| { |
| BasicBeanDescription desc = _findCachedDesc(type); |
| if (desc == null) { |
| desc = BasicBeanDescription.forDeserialization( |
| collectProperties(cfg, type, r, false, "set")); |
| } |
| return desc; |
| } |
| |
| @Override |
| public BasicBeanDescription forClassAnnotations(MapperConfig<?> cfg, |
| JavaType type, MixInResolver r) |
| { |
| boolean useAnnotations = cfg.isAnnotationProcessingEnabled(); |
| AnnotatedClass ac = AnnotatedClass.construct(type.getRawClass(), |
| (useAnnotations ? cfg.getAnnotationIntrospector() : null), r); |
| return BasicBeanDescription.forOtherUse(cfg, type, ac); |
| } |
| |
| @Override |
| public BasicBeanDescription forDirectClassAnnotations(MapperConfig<?> cfg, |
| JavaType type, MixInResolver r) |
| { |
| boolean useAnnotations = cfg.isAnnotationProcessingEnabled(); |
| AnnotationIntrospector ai = cfg.getAnnotationIntrospector(); |
| AnnotatedClass ac = AnnotatedClass.constructWithoutSuperTypes(type.getRawClass(), |
| (useAnnotations ? ai : null), r); |
| return BasicBeanDescription.forOtherUse(cfg, type, ac); |
| } |
| |
| /* |
| /********************************************************** |
| /* Overridable helper methods |
| /********************************************************** |
| */ |
| |
| protected POJOPropertiesCollector collectProperties(MapperConfig<?> config, |
| JavaType type, MixInResolver r, boolean forSerialization, |
| String mutatorPrefix) |
| { |
| boolean useAnnotations = config.isAnnotationProcessingEnabled(); |
| AnnotatedClass ac = AnnotatedClass.construct(type.getRawClass(), |
| (useAnnotations ? config.getAnnotationIntrospector() : null), r); |
| return constructPropertyCollector(config, ac, type, forSerialization, mutatorPrefix).collect(); |
| } |
| |
| protected POJOPropertiesCollector collectPropertiesWithBuilder(MapperConfig<?> config, |
| JavaType type, MixInResolver r, boolean forSerialization) |
| { |
| boolean useAnnotations = config.isAnnotationProcessingEnabled(); |
| AnnotationIntrospector ai = useAnnotations ? config.getAnnotationIntrospector() : null; |
| AnnotatedClass ac = AnnotatedClass.construct(type.getRawClass(), ai, r); |
| JsonPOJOBuilder.Value builderConfig = (ai == null) ? null : ai.findPOJOBuilderConfig(ac); |
| String mutatorPrefix = (builderConfig == null) ? "with" : builderConfig.withPrefix; |
| return constructPropertyCollector(config, ac, type, forSerialization, mutatorPrefix).collect(); |
| } |
| |
| /** |
| * Overridable method called for creating {@link POJOPropertiesCollector} instance |
| * to use; override is needed if a custom sub-class is to be used. |
| */ |
| protected POJOPropertiesCollector constructPropertyCollector(MapperConfig<?> config, |
| AnnotatedClass ac, JavaType type, boolean forSerialization, String mutatorPrefix) |
| { |
| return new POJOPropertiesCollector(config, forSerialization, type, ac, mutatorPrefix); |
| } |
| |
| /** |
| * Method called to see if type is one of core JDK types |
| * that we have cached for efficiency. |
| */ |
| protected BasicBeanDescription _findCachedDesc(JavaType type) |
| { |
| Class<?> cls = type.getRawClass(); |
| if (cls == String.class) { |
| return STRING_DESC; |
| } |
| if (cls == Boolean.TYPE) { |
| return BOOLEAN_DESC; |
| } |
| if (cls == Integer.TYPE) { |
| return INT_DESC; |
| } |
| if (cls == Long.TYPE) { |
| return LONG_DESC; |
| } |
| return null; |
| } |
| } |