1 package com.fasterxml.jackson.databind.introspect;
2 
3 import java.lang.annotation.Annotation;
4 import java.lang.reflect.Field;
5 import java.util.*;
6 
7 import com.fasterxml.jackson.annotation.*;
8 import com.fasterxml.jackson.core.Version;
9 import com.fasterxml.jackson.databind.*;
10 import com.fasterxml.jackson.databind.annotation.*;
11 import com.fasterxml.jackson.databind.cfg.HandlerInstantiator;
12 import com.fasterxml.jackson.databind.cfg.MapperConfig;
13 import com.fasterxml.jackson.databind.ext.Java7Support;
14 import com.fasterxml.jackson.databind.jsontype.NamedType;
15 import com.fasterxml.jackson.databind.jsontype.TypeIdResolver;
16 import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder;
17 import com.fasterxml.jackson.databind.jsontype.impl.StdTypeResolverBuilder;
18 import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
19 import com.fasterxml.jackson.databind.ser.VirtualBeanPropertyWriter;
20 import com.fasterxml.jackson.databind.ser.impl.AttributePropertyWriter;
21 import com.fasterxml.jackson.databind.ser.std.RawSerializer;
22 import com.fasterxml.jackson.databind.type.MapLikeType;
23 import com.fasterxml.jackson.databind.type.TypeFactory;
24 import com.fasterxml.jackson.databind.util.*;
25 
26 /**
27  * {@link AnnotationIntrospector} implementation that handles standard
28  * Jackson annotations.
29  */
30 public class JacksonAnnotationIntrospector
31     extends AnnotationIntrospector
32     implements java.io.Serializable
33 {
34     private static final long serialVersionUID = 1L;
35 
36     @SuppressWarnings("unchecked")
37     private final static Class<? extends Annotation>[] ANNOTATIONS_TO_INFER_SER = (Class<? extends Annotation>[])
38             new Class<?>[] {
39         JsonSerialize.class,
40         JsonView.class,
41         JsonFormat.class,
42         JsonTypeInfo.class,
43         JsonRawValue.class,
44         JsonUnwrapped.class,
45         JsonBackReference.class,
46         JsonManagedReference.class
47     };
48 
49     @SuppressWarnings("unchecked")
50     private final static Class<? extends Annotation>[] ANNOTATIONS_TO_INFER_DESER = (Class<? extends Annotation>[])
51             new Class<?>[] {
52         JsonDeserialize.class,
53         JsonView.class,
54         JsonFormat.class,
55         JsonTypeInfo.class,
56         JsonUnwrapped.class,
57         JsonBackReference.class,
58         JsonManagedReference.class,
59         JsonMerge.class // since 2.9
60     };
61 
62     // NOTE: loading of Java7 dependencies is encapsulated by handlers in Java7Support,
63     //  here we do not really need any handling; but for extra-safety use try-catch
64     private static final Java7Support _java7Helper;
65     static {
66         Java7Support x = null;
67         try {
68             x = Java7Support.instance();
69         } catch (Throwable t) { }
70         _java7Helper = x;
71     }
72 
73     /**
74      * Since introspection of annotation types is a performance issue in some
75      * use cases (rare, but do exist), let's try a simple cache to reduce
76      * need for actual meta-annotation introspection.
77      *<p>
78      * Non-final only because it needs to be re-created after deserialization.
79      *
80      * @since 2.7
81      */
82     protected transient LRUMap<Class<?>,Boolean> _annotationsInside = new LRUMap<Class<?>,Boolean>(48, 48);
83 
84     /*
85     /**********************************************************
86     /* Local configuration settings
87     /**********************************************************
88      */
89 
90     /**
91      * See {@link #setConstructorPropertiesImpliesCreator(boolean)} for
92      * explanation.
93      *<p>
94      * Defaults to true.
95      *
96      * @since 2.7.4
97      */
98     protected boolean _cfgConstructorPropertiesImpliesCreator = true;
99 
100     /*
101     /**********************************************************
102     /* Life-cycle
103     /**********************************************************
104      */
105 
JacksonAnnotationIntrospector()106     public JacksonAnnotationIntrospector() { }
107 
108     @Override
version()109     public Version version() {
110         return com.fasterxml.jackson.databind.cfg.PackageVersion.VERSION;
111     }
112 
readResolve()113     protected Object readResolve() {
114         if (_annotationsInside == null) {
115             _annotationsInside = new LRUMap<Class<?>,Boolean>(48, 48);
116         }
117         return this;
118     }
119 
120     /*
121     /**********************************************************
122     /* Configuration
123     /**********************************************************
124      */
125 
126     /**
127      * Method for changing behavior of {@link java.beans.ConstructorProperties}:
128      * if set to `true`, existence DOES indicate that the given constructor should
129      * be considered a creator; `false` that it should NOT be considered a creator
130      * without explicit use of <code>JsonCreator</code> annotation.
131      *<p>
132      * Default setting is `true`
133      *
134      * @since 2.7.4
135      */
setConstructorPropertiesImpliesCreator(boolean b)136     public JacksonAnnotationIntrospector setConstructorPropertiesImpliesCreator(boolean b)
137     {
138         _cfgConstructorPropertiesImpliesCreator = b;
139         return this;
140     }
141 
142     /*
143     /**********************************************************
144     /* General annotation properties
145     /**********************************************************
146      */
147 
148     /**
149      * Annotations with meta-annotation {@link JacksonAnnotationsInside}
150      * are considered bundles.
151      */
152     @Override
isAnnotationBundle(Annotation ann)153     public boolean isAnnotationBundle(Annotation ann) {
154         // 22-Sep-2015, tatu: Caching here has modest effect on JavaSE, and only
155         //   mostly in degenerate cases where introspection used more often than
156         //   it should (like recreating ObjectMapper once per read/write).
157         //   But it may be more beneficial on platforms like Android (should verify)
158         Class<?> type = ann.annotationType();
159         Boolean b = _annotationsInside.get(type);
160         if (b == null) {
161             b = type.getAnnotation(JacksonAnnotationsInside.class) != null;
162             _annotationsInside.putIfAbsent(type, b);
163         }
164         return b.booleanValue();
165     }
166 
167     /*
168     /**********************************************************
169     /* General annotations
170     /**********************************************************
171      */
172 
173     /**
174      * Since 2.6, we have supported use of {@link JsonProperty} for specifying
175      * explicit serialized name
176      */
177     @Override
178     @Deprecated // since 2.8
findEnumValue(Enum<?> value)179     public String findEnumValue(Enum<?> value)
180     {
181         // 11-Jun-2015, tatu: As per [databind#677], need to allow explicit naming.
182         //   Unfortunately cannot quite use standard AnnotatedClass here (due to various
183         //   reasons, including odd representation JVM uses); has to do for now
184         try {
185             // We know that values are actually static fields with matching name so:
186             Field f = value.getClass().getField(value.name());
187             if (f != null) {
188                 JsonProperty prop = f.getAnnotation(JsonProperty.class);
189                 if (prop != null) {
190                     String n = prop.value();
191                     if (n != null && !n.isEmpty()) {
192                         return n;
193                     }
194                 }
195             }
196         } catch (SecurityException e) {
197             // 17-Sep-2015, tatu: Anything we could/should do here?
198         } catch (NoSuchFieldException e) {
199             // 17-Sep-2015, tatu: should not really happen. But... can we do anything?
200         }
201         return value.name();
202     }
203 
204     @Override // since 2.7
findEnumValues(Class<?> enumType, Enum<?>[] enumValues, String[] names)205     public String[] findEnumValues(Class<?> enumType, Enum<?>[] enumValues, String[] names) {
206         HashMap<String,String> expl = null;
207         for (Field f : enumType.getDeclaredFields()) {
208             if (!f.isEnumConstant()) {
209                 continue;
210             }
211             JsonProperty prop = f.getAnnotation(JsonProperty.class);
212             if (prop == null) {
213                 continue;
214             }
215             String n = prop.value();
216             if (n.isEmpty()) {
217                 continue;
218             }
219             if (expl == null) {
220                 expl = new HashMap<String,String>();
221             }
222             expl.put(f.getName(), n);
223         }
224         // and then stitch them together if and as necessary
225         if (expl != null) {
226             for (int i = 0, end = enumValues.length; i < end; ++i) {
227                 String defName = enumValues[i].name();
228                 String explValue = expl.get(defName);
229                 if (explValue != null) {
230                     names[i] = explValue;
231                 }
232             }
233         }
234         return names;
235     }
236 
237     @Override // since 2.11
findEnumAliases(Class<?> enumType, Enum<?>[] enumValues, String[][] aliasList)238     public void findEnumAliases(Class<?> enumType, Enum<?>[] enumValues, String[][] aliasList)
239     {
240         // Main complication: discrepancy between Field that represent enum value,
241         // Enum abstraction; joint by name but not reference
242         for (Field f : enumType.getDeclaredFields()) {
243             if (f.isEnumConstant()) {
244                 JsonAlias aliasAnnotation = f.getAnnotation(JsonAlias.class);
245                 if (aliasAnnotation != null) {
246                     String[] aliases = aliasAnnotation.value();
247                     if (aliases.length != 0) {
248                         final String name = f.getName();
249                         // Find matching enum (could create Ma
250                         for (int i = 0, end = enumValues.length; i < end; ++i) {
251                             if (name.equals(enumValues[i].name())) {
252                                 aliasList[i] = aliases;
253                             }
254                         }
255                     }
256                 }
257             }
258         }
259     }
260 
261     /**
262      * Finds the Enum value that should be considered the default value, if possible.
263      * <p>
264      * This implementation relies on {@link JsonEnumDefaultValue} annotation to determine the default value if present.
265      *
266      * @param enumCls The Enum class to scan for the default value.
267      * @return null if none found or it's not possible to determine one.
268      * @since 2.8
269      */
270     @Override
findDefaultEnumValue(Class<Enum<?>> enumCls)271     public Enum<?> findDefaultEnumValue(Class<Enum<?>> enumCls) {
272         return ClassUtil.findFirstAnnotatedEnumValue(enumCls, JsonEnumDefaultValue.class);
273     }
274 
275     /*
276     /**********************************************************
277     /* General class annotations
278     /**********************************************************
279      */
280 
281     @Override
findRootName(AnnotatedClass ac)282     public PropertyName findRootName(AnnotatedClass ac)
283     {
284         JsonRootName ann = _findAnnotation(ac, JsonRootName.class);
285         if (ann == null) {
286             return null;
287         }
288         String ns = ann.namespace();
289         if (ns != null && ns.length() == 0) {
290             ns = null;
291         }
292         return PropertyName.construct(ann.value(), ns);
293     }
294 
295     @Override
isIgnorableType(AnnotatedClass ac)296     public Boolean isIgnorableType(AnnotatedClass ac) {
297         JsonIgnoreType ignore = _findAnnotation(ac, JsonIgnoreType.class);
298         return (ignore == null) ? null : ignore.value();
299     }
300 
301     @Override // since 2.12
findPropertyIgnoralByName(MapperConfig<?> config, Annotated a)302     public JsonIgnoreProperties.Value findPropertyIgnoralByName(MapperConfig<?> config, Annotated a)
303     {
304         JsonIgnoreProperties v = _findAnnotation(a, JsonIgnoreProperties.class);
305         if (v == null) {
306             return JsonIgnoreProperties.Value.empty();
307         }
308         return JsonIgnoreProperties.Value.from(v);
309     }
310 
311     // Keep around until 3.x
312     @Deprecated // since 2.12
313     @Override
findPropertyIgnorals(Annotated ac)314     public JsonIgnoreProperties.Value findPropertyIgnorals(Annotated ac) {
315         return findPropertyIgnoralByName(null, ac);
316     }
317 
318     @Override
findPropertyInclusionByName(MapperConfig<?> config, Annotated a)319     public JsonIncludeProperties.Value findPropertyInclusionByName(MapperConfig<?> config, Annotated a)
320     {
321         JsonIncludeProperties v = _findAnnotation(a, JsonIncludeProperties.class);
322         if (v == null) {
323             return JsonIncludeProperties.Value.all();
324         }
325         return JsonIncludeProperties.Value.from(v);
326     }
327 
328     @Override
findFilterId(Annotated a)329     public Object findFilterId(Annotated a) {
330         JsonFilter ann = _findAnnotation(a, JsonFilter.class);
331         if (ann != null) {
332             String id = ann.value();
333             // Empty String is same as not having annotation, to allow overrides
334             if (id.length() > 0) {
335                 return id;
336             }
337         }
338         return null;
339     }
340 
341     @Override
findNamingStrategy(AnnotatedClass ac)342     public Object findNamingStrategy(AnnotatedClass ac)
343     {
344         JsonNaming ann = _findAnnotation(ac, JsonNaming.class);
345         return (ann == null) ? null : ann.value();
346     }
347 
348     @Override
findClassDescription(AnnotatedClass ac)349     public String findClassDescription(AnnotatedClass ac) {
350         JsonClassDescription ann = _findAnnotation(ac, JsonClassDescription.class);
351         return (ann == null) ? null : ann.value();
352     }
353 
354     /*
355     /**********************************************************
356     /* Property auto-detection
357     /**********************************************************
358      */
359 
360     @Override
findAutoDetectVisibility(AnnotatedClass ac, VisibilityChecker<?> checker)361     public VisibilityChecker<?> findAutoDetectVisibility(AnnotatedClass ac,
362         VisibilityChecker<?> checker)
363     {
364         JsonAutoDetect ann = _findAnnotation(ac, JsonAutoDetect.class);
365         return (ann == null) ? checker : checker.with(ann);
366     }
367 
368     /*
369     /**********************************************************
370     /* General member (field, method/constructor) annotations
371     /**********************************************************
372      */
373 
374     @Override
findImplicitPropertyName(AnnotatedMember m)375     public String findImplicitPropertyName(AnnotatedMember m) {
376         PropertyName n = _findConstructorName(m);
377         return (n == null) ? null : n.getSimpleName();
378     }
379 
380     @Override
findPropertyAliases(Annotated m)381     public List<PropertyName> findPropertyAliases(Annotated m) {
382         JsonAlias ann = _findAnnotation(m, JsonAlias.class);
383         if (ann == null) {
384             return null;
385         }
386         String[] strs = ann.value();
387         final int len = strs.length;
388         if (len == 0) {
389             return Collections.emptyList();
390         }
391         List<PropertyName> result = new ArrayList<>(len);
392         for (int i = 0; i < len; ++i) {
393             result.add(PropertyName.construct(strs[i]));
394         }
395         return result;
396     }
397 
398     @Override
hasIgnoreMarker(AnnotatedMember m)399     public boolean hasIgnoreMarker(AnnotatedMember m) {
400         return _isIgnorable(m);
401     }
402 
403     @Override
hasRequiredMarker(AnnotatedMember m)404     public Boolean hasRequiredMarker(AnnotatedMember m)
405     {
406         JsonProperty ann = _findAnnotation(m, JsonProperty.class);
407         if (ann != null) {
408             return ann.required();
409         }
410         return null;
411     }
412 
413     @Override
findPropertyAccess(Annotated m)414     public JsonProperty.Access findPropertyAccess(Annotated m) {
415         JsonProperty ann = _findAnnotation(m, JsonProperty.class);
416         if (ann != null) {
417             return ann.access();
418         }
419         return null;
420     }
421 
422     @Override
findPropertyDescription(Annotated ann)423     public String findPropertyDescription(Annotated ann) {
424         JsonPropertyDescription desc = _findAnnotation(ann, JsonPropertyDescription.class);
425         return (desc == null) ? null : desc.value();
426     }
427 
428     @Override
findPropertyIndex(Annotated ann)429     public Integer findPropertyIndex(Annotated ann) {
430         JsonProperty prop = _findAnnotation(ann, JsonProperty.class);
431         if (prop != null) {
432           int ix = prop.index();
433           if (ix != JsonProperty.INDEX_UNKNOWN) {
434                return Integer.valueOf(ix);
435           }
436         }
437         return null;
438     }
439 
440     @Override
findPropertyDefaultValue(Annotated ann)441     public String findPropertyDefaultValue(Annotated ann) {
442         JsonProperty prop = _findAnnotation(ann, JsonProperty.class);
443         if (prop == null) {
444             return null;
445         }
446         String str = prop.defaultValue();
447         // Since annotations do not allow nulls, need to assume empty means "none"
448         return str.isEmpty() ? null : str;
449     }
450 
451     @Override
findFormat(Annotated ann)452     public JsonFormat.Value findFormat(Annotated ann) {
453         JsonFormat f = _findAnnotation(ann, JsonFormat.class);
454         // NOTE: could also just call `JsonFormat.Value.from()` with `null`
455         // too, but that returns "empty" instance
456         return (f == null)  ? null : JsonFormat.Value.from(f);
457     }
458 
459     @Override
findReferenceType(AnnotatedMember member)460     public ReferenceProperty findReferenceType(AnnotatedMember member)
461     {
462         JsonManagedReference ref1 = _findAnnotation(member, JsonManagedReference.class);
463         if (ref1 != null) {
464             return AnnotationIntrospector.ReferenceProperty.managed(ref1.value());
465         }
466         JsonBackReference ref2 = _findAnnotation(member, JsonBackReference.class);
467         if (ref2 != null) {
468             return AnnotationIntrospector.ReferenceProperty.back(ref2.value());
469         }
470         return null;
471     }
472 
473     @Override
findUnwrappingNameTransformer(AnnotatedMember member)474     public NameTransformer findUnwrappingNameTransformer(AnnotatedMember member)
475     {
476         JsonUnwrapped ann = _findAnnotation(member, JsonUnwrapped.class);
477         // if not enabled, just means annotation is not enabled; not necessarily
478         // that unwrapping should not be done (relevant when using chained introspectors)
479         if (ann == null || !ann.enabled()) {
480             return null;
481         }
482         String prefix = ann.prefix();
483         String suffix = ann.suffix();
484         return NameTransformer.simpleTransformer(prefix, suffix);
485     }
486 
487     @Override // since 2.9
findInjectableValue(AnnotatedMember m)488     public JacksonInject.Value findInjectableValue(AnnotatedMember m) {
489         JacksonInject ann = _findAnnotation(m, JacksonInject.class);
490         if (ann == null) {
491             return null;
492         }
493         // Empty String means that we should use name of declared value class.
494         JacksonInject.Value v = JacksonInject.Value.from(ann);
495         if (!v.hasId()) {
496             Object id;
497             // slight complication; for setters, type
498             if (!(m instanceof AnnotatedMethod)) {
499                 id = m.getRawType().getName();
500             } else {
501                 AnnotatedMethod am = (AnnotatedMethod) m;
502                 if (am.getParameterCount() == 0) { // getter
503                     id = m.getRawType().getName();
504                 } else { // setter
505                     id = am.getRawParameterType(0).getName();
506                 }
507             }
508             v = v.withId(id);
509         }
510         return v;
511     }
512 
513     @Override
514     @Deprecated // since 2.9
findInjectableValueId(AnnotatedMember m)515     public Object findInjectableValueId(AnnotatedMember m) {
516         JacksonInject.Value v = findInjectableValue(m);
517         return (v == null) ? null : v.getId();
518     }
519 
520     @Override
findViews(Annotated a)521     public Class<?>[] findViews(Annotated a)
522     {
523         JsonView ann = _findAnnotation(a, JsonView.class);
524         return (ann == null) ? null : ann.value();
525     }
526 
527     @Override // since 2.7
resolveSetterConflict(MapperConfig<?> config, AnnotatedMethod setter1, AnnotatedMethod setter2)528     public AnnotatedMethod resolveSetterConflict(MapperConfig<?> config,
529             AnnotatedMethod setter1, AnnotatedMethod setter2)
530     {
531         Class<?> cls1 = setter1.getRawParameterType(0);
532         Class<?> cls2 = setter2.getRawParameterType(0);
533 
534         // First: prefer primitives over non-primitives
535         // 11-Dec-2015, tatu: TODO, perhaps consider wrappers for primitives too?
536         if (cls1.isPrimitive()) {
537             if (!cls2.isPrimitive()) {
538                 return setter1;
539             }
540         } else if (cls2.isPrimitive()) {
541             return setter2;
542         }
543 
544         if (cls1 == String.class) {
545             if (cls2 != String.class) {
546                 return setter1;
547             }
548         } else if (cls2 == String.class) {
549             return setter2;
550         }
551 
552         return null;
553     }
554 
555     @Override // since 2.11
findRenameByField(MapperConfig<?> config, AnnotatedField f, PropertyName implName)556     public PropertyName findRenameByField(MapperConfig<?> config,
557             AnnotatedField f, PropertyName implName) {
558         // Nothing to report, only used by modules. But define just as documentation
559         return null;
560     }
561 
562     /*
563     /**********************************************************
564     /* Annotations for Polymorphic Type handling
565     /**********************************************************
566      */
567 
568     @Override
findTypeResolver(MapperConfig<?> config, AnnotatedClass ac, JavaType baseType)569     public TypeResolverBuilder<?> findTypeResolver(MapperConfig<?> config,
570             AnnotatedClass ac, JavaType baseType)
571     {
572         return _findTypeResolver(config, ac, baseType);
573     }
574 
575     @Override
findPropertyTypeResolver(MapperConfig<?> config, AnnotatedMember am, JavaType baseType)576     public TypeResolverBuilder<?> findPropertyTypeResolver(MapperConfig<?> config,
577             AnnotatedMember am, JavaType baseType)
578     {
579         /* As per definition of @JsonTypeInfo, should only apply to contents of container
580          * (collection, map) types, not container types themselves:
581          */
582         // 17-Apr-2016, tatu: For 2.7.4 make sure ReferenceType also included
583         if (baseType.isContainerType() || baseType.isReferenceType()) {
584             return null;
585         }
586         // No per-member type overrides (yet)
587         return _findTypeResolver(config, am, baseType);
588     }
589 
590     @Override
findPropertyContentTypeResolver(MapperConfig<?> config, AnnotatedMember am, JavaType containerType)591     public TypeResolverBuilder<?> findPropertyContentTypeResolver(MapperConfig<?> config,
592             AnnotatedMember am, JavaType containerType)
593     {
594         /* First: let's ensure property is a container type: caller should have
595          * verified but just to be sure
596          */
597         if (containerType.getContentType() == null) {
598             throw new IllegalArgumentException("Must call method with a container or reference type (got "+containerType+")");
599         }
600         return _findTypeResolver(config, am, containerType);
601     }
602 
603     @Override
findSubtypes(Annotated a)604     public List<NamedType> findSubtypes(Annotated a)
605     {
606         JsonSubTypes t = _findAnnotation(a, JsonSubTypes.class);
607         if (t == null) return null;
608         JsonSubTypes.Type[] types = t.value();
609         ArrayList<NamedType> result = new ArrayList<NamedType>(types.length);
610         for (JsonSubTypes.Type type : types) {
611             result.add(new NamedType(type.value(), type.name()));
612             // [databind#2761]: alternative set of names to use
613             for (String name : type.names()) {
614                 result.add(new NamedType(type.value(), name));
615             }
616         }
617         return result;
618     }
619 
620     @Override
findTypeName(AnnotatedClass ac)621     public String findTypeName(AnnotatedClass ac)
622     {
623         JsonTypeName tn = _findAnnotation(ac, JsonTypeName.class);
624         return (tn == null) ? null : tn.value();
625     }
626 
627     @Override
isTypeId(AnnotatedMember member)628     public Boolean isTypeId(AnnotatedMember member) {
629         return _hasAnnotation(member, JsonTypeId.class);
630     }
631 
632     /*
633     /**********************************************************
634     /* Annotations for Object Id handling
635     /**********************************************************
636      */
637 
638     @Override
findObjectIdInfo(Annotated ann)639     public ObjectIdInfo findObjectIdInfo(Annotated ann) {
640         JsonIdentityInfo info = _findAnnotation(ann, JsonIdentityInfo.class);
641         if (info == null || info.generator() == ObjectIdGenerators.None.class) {
642             return null;
643         }
644         // In future may need to allow passing namespace?
645         PropertyName name = PropertyName.construct(info.property());
646         return new ObjectIdInfo(name, info.scope(), info.generator(), info.resolver());
647     }
648 
649     @Override
findObjectReferenceInfo(Annotated ann, ObjectIdInfo objectIdInfo)650     public ObjectIdInfo findObjectReferenceInfo(Annotated ann, ObjectIdInfo objectIdInfo) {
651         JsonIdentityReference ref = _findAnnotation(ann, JsonIdentityReference.class);
652         if (ref == null) {
653             return objectIdInfo;
654         }
655         if (objectIdInfo == null) {
656             objectIdInfo = ObjectIdInfo.empty();
657         }
658         return objectIdInfo.withAlwaysAsId(ref.alwaysAsId());
659     }
660 
661     /*
662     /**********************************************************
663     /* Serialization: general annotations
664     /**********************************************************
665     */
666 
667     @Override
findSerializer(Annotated a)668     public Object findSerializer(Annotated a)
669     {
670         JsonSerialize ann = _findAnnotation(a, JsonSerialize.class);
671         if (ann != null) {
672             @SuppressWarnings("rawtypes")
673             Class<? extends JsonSerializer> serClass = ann.using();
674             if (serClass != JsonSerializer.None.class) {
675                 return serClass;
676             }
677         }
678 
679         /* 18-Oct-2010, tatu: [JACKSON-351] @JsonRawValue handled just here, for now;
680          *  if we need to get raw indicator from other sources need to add
681          *  separate accessor within {@link AnnotationIntrospector} interface.
682          */
683         JsonRawValue annRaw =  _findAnnotation(a, JsonRawValue.class);
684         if ((annRaw != null) && annRaw.value()) {
685             // let's construct instance with nominal type:
686             Class<?> cls = a.getRawType();
687             return new RawSerializer<Object>(cls);
688         }
689         return null;
690     }
691 
692     @Override
findKeySerializer(Annotated a)693     public Object findKeySerializer(Annotated a)
694     {
695         JsonSerialize ann = _findAnnotation(a, JsonSerialize.class);
696         if (ann != null) {
697             @SuppressWarnings("rawtypes")
698             Class<? extends JsonSerializer> serClass = ann.keyUsing();
699             if (serClass != JsonSerializer.None.class) {
700                 return serClass;
701             }
702         }
703         return null;
704     }
705 
706     @Override
findContentSerializer(Annotated a)707     public Object findContentSerializer(Annotated a)
708     {
709         JsonSerialize ann = _findAnnotation(a, JsonSerialize.class);
710         if (ann != null) {
711             @SuppressWarnings("rawtypes")
712             Class<? extends JsonSerializer> serClass = ann.contentUsing();
713             if (serClass != JsonSerializer.None.class) {
714                 return serClass;
715             }
716         }
717         return null;
718     }
719 
720     @Override
findNullSerializer(Annotated a)721     public Object findNullSerializer(Annotated a)
722     {
723         JsonSerialize ann = _findAnnotation(a, JsonSerialize.class);
724         if (ann != null) {
725             @SuppressWarnings("rawtypes")
726             Class<? extends JsonSerializer> serClass = ann.nullsUsing();
727             if (serClass != JsonSerializer.None.class) {
728                 return serClass;
729             }
730         }
731         return null;
732     }
733 
734     @Override
findPropertyInclusion(Annotated a)735     public JsonInclude.Value findPropertyInclusion(Annotated a)
736     {
737         JsonInclude inc = _findAnnotation(a, JsonInclude.class);
738         JsonInclude.Value value = (inc == null) ? JsonInclude.Value.empty() : JsonInclude.Value.from(inc);
739 
740         // only consider deprecated variant if we didn't have non-deprecated one:
741         if (value.getValueInclusion() == JsonInclude.Include.USE_DEFAULTS) {
742             value = _refinePropertyInclusion(a, value);
743         }
744         return value;
745     }
746 
747     @SuppressWarnings("deprecation")
_refinePropertyInclusion(Annotated a, JsonInclude.Value value)748     private JsonInclude.Value _refinePropertyInclusion(Annotated a, JsonInclude.Value value) {
749         JsonSerialize ann = _findAnnotation(a, JsonSerialize.class);
750         if (ann != null) {
751             switch (ann.include()) {
752             case ALWAYS:
753                 return value.withValueInclusion(JsonInclude.Include.ALWAYS);
754             case NON_NULL:
755                 return value.withValueInclusion(JsonInclude.Include.NON_NULL);
756             case NON_DEFAULT:
757                 return value.withValueInclusion(JsonInclude.Include.NON_DEFAULT);
758             case NON_EMPTY:
759                 return value.withValueInclusion(JsonInclude.Include.NON_EMPTY);
760             case DEFAULT_INCLUSION:
761             default:
762             }
763         }
764         return value;
765     }
766 
767     @Override
findSerializationTyping(Annotated a)768     public JsonSerialize.Typing findSerializationTyping(Annotated a)
769     {
770         JsonSerialize ann = _findAnnotation(a, JsonSerialize.class);
771         return (ann == null) ? null : ann.typing();
772     }
773 
774     @Override
findSerializationConverter(Annotated a)775     public Object findSerializationConverter(Annotated a) {
776         JsonSerialize ann = _findAnnotation(a, JsonSerialize.class);
777         return (ann == null) ? null : _classIfExplicit(ann.converter(), Converter.None.class);
778     }
779 
780     @Override
findSerializationContentConverter(AnnotatedMember a)781     public Object findSerializationContentConverter(AnnotatedMember a) {
782         JsonSerialize ann = _findAnnotation(a, JsonSerialize.class);
783         return (ann == null) ? null : _classIfExplicit(ann.contentConverter(), Converter.None.class);
784     }
785 
786     /*
787     /**********************************************************
788     /* Serialization: type refinements
789     /**********************************************************
790      */
791 
792     @Override
refineSerializationType(final MapperConfig<?> config, final Annotated a, final JavaType baseType)793     public JavaType refineSerializationType(final MapperConfig<?> config,
794             final Annotated a, final JavaType baseType) throws JsonMappingException
795     {
796         JavaType type = baseType;
797         final TypeFactory tf = config.getTypeFactory();
798 
799         final JsonSerialize jsonSer = _findAnnotation(a, JsonSerialize.class);
800 
801         // Ok: start by refining the main type itself; common to all types
802 
803         final Class<?> serClass = (jsonSer == null) ? null : _classIfExplicit(jsonSer.as());
804         if (serClass != null) {
805             if (type.hasRawClass(serClass)) {
806                 // 30-Nov-2015, tatu: As per [databind#1023], need to allow forcing of
807                 //    static typing this way
808                 type = type.withStaticTyping();
809             } else {
810                 Class<?> currRaw = type.getRawClass();
811                 try {
812                     // 11-Oct-2015, tatu: For deser, we call `TypeFactory.constructSpecializedType()`,
813                     //   may be needed here too in future?
814                     if (serClass.isAssignableFrom(currRaw)) { // common case
815                         type = tf.constructGeneralizedType(type, serClass);
816                     } else if (currRaw.isAssignableFrom(serClass)) { // specialization, ok as well
817                         type = tf.constructSpecializedType(type, serClass);
818                     } else if (_primitiveAndWrapper(currRaw, serClass)) {
819                         // 27-Apr-2017, tatu: [databind#1592] ignore primitive<->wrapper refinements
820                         type = type.withStaticTyping();
821                     } else {
822                         throw new JsonMappingException(null,
823                                 String.format("Cannot refine serialization type %s into %s; types not related",
824                                         type, serClass.getName()));
825                     }
826                 } catch (IllegalArgumentException iae) {
827                     throw new JsonMappingException(null,
828                             String.format("Failed to widen type %s with annotation (value %s), from '%s': %s",
829                                     type, serClass.getName(), a.getName(), iae.getMessage()),
830                                     iae);
831                 }
832             }
833         }
834         // Then further processing for container types
835 
836         // First, key type (for Maps, Map-like types):
837         if (type.isMapLikeType()) {
838             JavaType keyType = type.getKeyType();
839             final Class<?> keyClass = (jsonSer == null) ? null : _classIfExplicit(jsonSer.keyAs());
840             if (keyClass != null) {
841                 if (keyType.hasRawClass(keyClass)) {
842                     keyType = keyType.withStaticTyping();
843                 } else {
844                     Class<?> currRaw = keyType.getRawClass();
845                     try {
846                         // 19-May-2016, tatu: As per [databind#1231], [databind#1178] may need to actually
847                         //   specialize (narrow) type sometimes, even if more commonly opposite
848                         //   is needed.
849                         if (keyClass.isAssignableFrom(currRaw)) { // common case
850                             keyType = tf.constructGeneralizedType(keyType, keyClass);
851                         } else if (currRaw.isAssignableFrom(keyClass)) { // specialization, ok as well
852                             keyType = tf.constructSpecializedType(keyType, keyClass);
853                         } else if (_primitiveAndWrapper(currRaw, keyClass)) {
854                             // 27-Apr-2017, tatu: [databind#1592] ignore primitive<->wrapper refinements
855                             keyType = keyType.withStaticTyping();
856                         } else {
857                             throw new JsonMappingException(null,
858                                     String.format("Cannot refine serialization key type %s into %s; types not related",
859                                             keyType, keyClass.getName()));
860                         }
861                     } catch (IllegalArgumentException iae) {
862                         throw new JsonMappingException(null,
863                                 String.format("Failed to widen key type of %s with concrete-type annotation (value %s), from '%s': %s",
864                                         type, keyClass.getName(), a.getName(), iae.getMessage()),
865                                         iae);
866                     }
867                 }
868                 type = ((MapLikeType) type).withKeyType(keyType);
869             }
870         }
871 
872         JavaType contentType = type.getContentType();
873         if (contentType != null) { // collection[like], map[like], array, reference
874             // And then value types for all containers:
875            final Class<?> contentClass = (jsonSer == null) ? null : _classIfExplicit(jsonSer.contentAs());
876            if (contentClass != null) {
877                if (contentType.hasRawClass(contentClass)) {
878                    contentType = contentType.withStaticTyping();
879                } else {
880                    // 03-Apr-2016, tatu: As per [databind#1178], may need to actually
881                    //   specialize (narrow) type sometimes, even if more commonly opposite
882                    //   is needed.
883                    Class<?> currRaw = contentType.getRawClass();
884                    try {
885                        if (contentClass.isAssignableFrom(currRaw)) { // common case
886                            contentType = tf.constructGeneralizedType(contentType, contentClass);
887                        } else if (currRaw.isAssignableFrom(contentClass)) { // specialization, ok as well
888                            contentType = tf.constructSpecializedType(contentType, contentClass);
889                        } else if (_primitiveAndWrapper(currRaw, contentClass)) {
890                            // 27-Apr-2017, tatu: [databind#1592] ignore primitive<->wrapper refinements
891                            contentType = contentType.withStaticTyping();
892                        } else {
893                            throw new JsonMappingException(null,
894                                    String.format("Cannot refine serialization content type %s into %s; types not related",
895                                            contentType, contentClass.getName()));
896                        }
897                    } catch (IllegalArgumentException iae) { // shouldn't really happen
898                        throw new JsonMappingException(null,
899                                String.format("Internal error: failed to refine value type of %s with concrete-type annotation (value %s), from '%s': %s",
900                                        type, contentClass.getName(), a.getName(), iae.getMessage()),
901                                        iae);
902                    }
903                }
904                type = type.withContentType(contentType);
905            }
906         }
907         return type;
908     }
909 
910     @Override
911     @Deprecated // since 2.7
findSerializationType(Annotated am)912     public Class<?> findSerializationType(Annotated am) {
913         return null;
914     }
915 
916     @Override
917     @Deprecated // since 2.7
findSerializationKeyType(Annotated am, JavaType baseType)918     public Class<?> findSerializationKeyType(Annotated am, JavaType baseType) {
919         return null;
920     }
921 
922     @Override
923     @Deprecated // since 2.7
findSerializationContentType(Annotated am, JavaType baseType)924     public Class<?> findSerializationContentType(Annotated am, JavaType baseType) {
925         return null;
926     }
927 
928     /*
929     /**********************************************************
930     /* Serialization: class annotations
931     /**********************************************************
932      */
933 
934     @Override
findSerializationPropertyOrder(AnnotatedClass ac)935     public String[] findSerializationPropertyOrder(AnnotatedClass ac) {
936         JsonPropertyOrder order = _findAnnotation(ac, JsonPropertyOrder.class);
937         return (order == null) ? null : order.value();
938     }
939 
940     @Override
findSerializationSortAlphabetically(Annotated ann)941     public Boolean findSerializationSortAlphabetically(Annotated ann) {
942         return _findSortAlpha(ann);
943     }
944 
_findSortAlpha(Annotated ann)945     private final Boolean _findSortAlpha(Annotated ann) {
946         JsonPropertyOrder order = _findAnnotation(ann, JsonPropertyOrder.class);
947         // 23-Jun-2015, tatu: as per [databind#840], let's only consider
948         //  `true` to have any significance.
949         if ((order != null) && order.alphabetic()) {
950             return Boolean.TRUE;
951         }
952         return null;
953     }
954 
955     @Override
findAndAddVirtualProperties(MapperConfig<?> config, AnnotatedClass ac, List<BeanPropertyWriter> properties)956     public void findAndAddVirtualProperties(MapperConfig<?> config, AnnotatedClass ac,
957             List<BeanPropertyWriter> properties) {
958         JsonAppend ann = _findAnnotation(ac, JsonAppend.class);
959         if (ann == null) {
960             return;
961         }
962         final boolean prepend = ann.prepend();
963         JavaType propType = null;
964 
965         // First: any attribute-backed properties?
966         JsonAppend.Attr[] attrs = ann.attrs();
967         for (int i = 0, len = attrs.length; i < len; ++i) {
968             if (propType == null) {
969                 propType = config.constructType(Object.class);
970             }
971             BeanPropertyWriter bpw = _constructVirtualProperty(attrs[i],
972                     config, ac, propType);
973             if (prepend) {
974                 properties.add(i, bpw);
975             } else {
976                 properties.add(bpw);
977             }
978         }
979 
980         // Then: general-purpose virtual properties?
981         JsonAppend.Prop[] props = ann.props();
982         for (int i = 0, len = props.length; i < len; ++i) {
983             BeanPropertyWriter bpw = _constructVirtualProperty(props[i],
984                     config, ac);
985             if (prepend) {
986                 properties.add(i, bpw);
987             } else {
988                 properties.add(bpw);
989             }
990         }
991     }
992 
_constructVirtualProperty(JsonAppend.Attr attr, MapperConfig<?> config, AnnotatedClass ac, JavaType type)993     protected BeanPropertyWriter _constructVirtualProperty(JsonAppend.Attr attr,
994             MapperConfig<?> config, AnnotatedClass ac, JavaType type)
995     {
996         PropertyMetadata metadata = attr.required() ?
997                     PropertyMetadata.STD_REQUIRED : PropertyMetadata.STD_OPTIONAL;
998         // could add Index, Description in future, if those matter
999         String attrName = attr.value();
1000 
1001         // allow explicit renaming; if none, default to attribute name
1002         PropertyName propName = _propertyName(attr.propName(), attr.propNamespace());
1003         if (!propName.hasSimpleName()) {
1004             propName = PropertyName.construct(attrName);
1005         }
1006         // now, then, we need a placeholder for member (no real Field/Method):
1007         AnnotatedMember member = new VirtualAnnotatedMember(ac, ac.getRawType(),
1008                 attrName, type);
1009         // and with that and property definition
1010         SimpleBeanPropertyDefinition propDef = SimpleBeanPropertyDefinition.construct(config,
1011                 member, propName, metadata, attr.include());
1012         // can construct the property writer
1013         return AttributePropertyWriter.construct(attrName, propDef,
1014                 ac.getAnnotations(), type);
1015     }
1016 
_constructVirtualProperty(JsonAppend.Prop prop, MapperConfig<?> config, AnnotatedClass ac)1017     protected BeanPropertyWriter _constructVirtualProperty(JsonAppend.Prop prop,
1018             MapperConfig<?> config, AnnotatedClass ac)
1019     {
1020         PropertyMetadata metadata = prop.required() ?
1021                     PropertyMetadata.STD_REQUIRED : PropertyMetadata.STD_OPTIONAL;
1022         PropertyName propName = _propertyName(prop.name(), prop.namespace());
1023         JavaType type = config.constructType(prop.type());
1024         // now, then, we need a placeholder for member (no real Field/Method):
1025         AnnotatedMember member = new VirtualAnnotatedMember(ac, ac.getRawType(),
1026                 propName.getSimpleName(), type);
1027         // and with that and property definition
1028         SimpleBeanPropertyDefinition propDef = SimpleBeanPropertyDefinition.construct(config,
1029                 member, propName, metadata, prop.include());
1030 
1031         Class<?> implClass = prop.value();
1032 
1033         HandlerInstantiator hi = config.getHandlerInstantiator();
1034         VirtualBeanPropertyWriter bpw = (hi == null) ? null
1035                 : hi.virtualPropertyWriterInstance(config, implClass);
1036         if (bpw == null) {
1037             bpw = (VirtualBeanPropertyWriter) ClassUtil.createInstance(implClass,
1038                     config.canOverrideAccessModifiers());
1039         }
1040 
1041         // one more thing: give it necessary contextual information
1042         return bpw.withConfig(config, ac, propDef, type);
1043     }
1044 
1045     /*
1046     /**********************************************************
1047     /* Serialization: property annotations
1048     /**********************************************************
1049      */
1050 
1051     @Override
findNameForSerialization(Annotated a)1052     public PropertyName findNameForSerialization(Annotated a)
1053     {
1054         boolean useDefault = false;
1055         JsonGetter jg = _findAnnotation(a, JsonGetter.class);
1056         if (jg != null) {
1057             String s = jg.value();
1058             // 04-May-2018, tatu: Should allow for "nameless" `@JsonGetter` too
1059             if (!s.isEmpty()) {
1060                 return PropertyName.construct(s);
1061             }
1062             useDefault = true;
1063         }
1064         JsonProperty pann = _findAnnotation(a, JsonProperty.class);
1065         if (pann != null) {
1066             return PropertyName.construct(pann.value());
1067         }
1068         if (useDefault || _hasOneOf(a, ANNOTATIONS_TO_INFER_SER)) {
1069             return PropertyName.USE_DEFAULT;
1070         }
1071         return null;
1072     }
1073 
1074     @Override // since 2.9
hasAsValue(Annotated a)1075     public Boolean hasAsValue(Annotated a) {
1076         JsonValue ann = _findAnnotation(a, JsonValue.class);
1077         if (ann == null) {
1078             return null;
1079         }
1080         return ann.value();
1081     }
1082 
1083     @Override // since 2.9
hasAnyGetter(Annotated a)1084     public Boolean hasAnyGetter(Annotated a) {
1085         JsonAnyGetter ann = _findAnnotation(a, JsonAnyGetter.class);
1086         if (ann == null) {
1087             return null;
1088         }
1089         return ann.enabled();
1090     }
1091 
1092     @Override
1093     @Deprecated // since 2.9
hasAnyGetterAnnotation(AnnotatedMethod am)1094     public boolean hasAnyGetterAnnotation(AnnotatedMethod am) {
1095         // No dedicated disabling; regular @JsonIgnore used if needs to be ignored (handled separately)
1096         return _hasAnnotation(am, JsonAnyGetter.class);
1097     }
1098 
1099     @Override
1100     @Deprecated // since 2.9
hasAsValueAnnotation(AnnotatedMethod am)1101     public boolean hasAsValueAnnotation(AnnotatedMethod am) {
1102         JsonValue ann = _findAnnotation(am, JsonValue.class);
1103         // value of 'false' means disabled...
1104         return (ann != null) && ann.value();
1105     }
1106 
1107     /*
1108     /**********************************************************
1109     /* Deserialization: general annotations
1110     /**********************************************************
1111      */
1112 
1113     @Override
findDeserializer(Annotated a)1114     public Object findDeserializer(Annotated a)
1115     {
1116         JsonDeserialize ann = _findAnnotation(a, JsonDeserialize.class);
1117         if (ann != null) {
1118             @SuppressWarnings("rawtypes")
1119             Class<? extends JsonDeserializer> deserClass = ann.using();
1120             if (deserClass != JsonDeserializer.None.class) {
1121                 return deserClass;
1122             }
1123         }
1124         return null;
1125     }
1126 
1127     @Override
findKeyDeserializer(Annotated a)1128     public Object findKeyDeserializer(Annotated a)
1129     {
1130         JsonDeserialize ann = _findAnnotation(a, JsonDeserialize.class);
1131         if (ann != null) {
1132             Class<? extends KeyDeserializer> deserClass = ann.keyUsing();
1133             if (deserClass != KeyDeserializer.None.class) {
1134                 return deserClass;
1135             }
1136         }
1137         return null;
1138     }
1139 
1140     @Override
findContentDeserializer(Annotated a)1141     public Object findContentDeserializer(Annotated a)
1142     {
1143         JsonDeserialize ann = _findAnnotation(a, JsonDeserialize.class);
1144         if (ann != null) {
1145             @SuppressWarnings("rawtypes")
1146             Class<? extends JsonDeserializer> deserClass = ann.contentUsing();
1147             if (deserClass != JsonDeserializer.None.class) {
1148                 return deserClass;
1149             }
1150         }
1151         return null;
1152     }
1153 
1154     @Override
findDeserializationConverter(Annotated a)1155     public Object findDeserializationConverter(Annotated a)
1156     {
1157         JsonDeserialize ann = _findAnnotation(a, JsonDeserialize.class);
1158         return (ann == null) ? null : _classIfExplicit(ann.converter(), Converter.None.class);
1159     }
1160 
1161     @Override
findDeserializationContentConverter(AnnotatedMember a)1162     public Object findDeserializationContentConverter(AnnotatedMember a)
1163     {
1164         JsonDeserialize ann = _findAnnotation(a, JsonDeserialize.class);
1165         return (ann == null) ? null : _classIfExplicit(ann.contentConverter(), Converter.None.class);
1166     }
1167 
1168     /*
1169     /**********************************************************
1170     /* Deserialization: type modifications
1171     /**********************************************************
1172      */
1173 
1174     @Override
refineDeserializationType(final MapperConfig<?> config, final Annotated a, final JavaType baseType)1175     public JavaType refineDeserializationType(final MapperConfig<?> config,
1176             final Annotated a, final JavaType baseType) throws JsonMappingException
1177     {
1178         JavaType type = baseType;
1179         final TypeFactory tf = config.getTypeFactory();
1180 
1181         final JsonDeserialize jsonDeser = _findAnnotation(a, JsonDeserialize.class);
1182 
1183         // Ok: start by refining the main type itself; common to all types
1184         final Class<?> valueClass = (jsonDeser == null) ? null : _classIfExplicit(jsonDeser.as());
1185         if ((valueClass != null) && !type.hasRawClass(valueClass)
1186                 && !_primitiveAndWrapper(type, valueClass)) {
1187             try {
1188                 type = tf.constructSpecializedType(type, valueClass);
1189             } catch (IllegalArgumentException iae) {
1190                 throw new JsonMappingException(null,
1191                         String.format("Failed to narrow type %s with annotation (value %s), from '%s': %s",
1192                                 type, valueClass.getName(), a.getName(), iae.getMessage()),
1193                                 iae);
1194             }
1195         }
1196         // Then further processing for container types
1197 
1198         // First, key type (for Maps, Map-like types):
1199         if (type.isMapLikeType()) {
1200             JavaType keyType = type.getKeyType();
1201             final Class<?> keyClass = (jsonDeser == null) ? null : _classIfExplicit(jsonDeser.keyAs());
1202             if ((keyClass != null)
1203                     && !_primitiveAndWrapper(keyType, keyClass)) {
1204                 try {
1205                     keyType = tf.constructSpecializedType(keyType, keyClass);
1206                     type = ((MapLikeType) type).withKeyType(keyType);
1207                 } catch (IllegalArgumentException iae) {
1208                     throw new JsonMappingException(null,
1209                             String.format("Failed to narrow key type of %s with concrete-type annotation (value %s), from '%s': %s",
1210                                     type, keyClass.getName(), a.getName(), iae.getMessage()),
1211                                     iae);
1212                 }
1213             }
1214         }
1215         JavaType contentType = type.getContentType();
1216         if (contentType != null) { // collection[like], map[like], array, reference
1217             // And then value types for all containers:
1218             final Class<?> contentClass = (jsonDeser == null) ? null : _classIfExplicit(jsonDeser.contentAs());
1219             if ((contentClass != null)
1220                     && !_primitiveAndWrapper(contentType, contentClass)) {
1221                 try {
1222                     contentType = tf.constructSpecializedType(contentType, contentClass);
1223                     type = type.withContentType(contentType);
1224                 } catch (IllegalArgumentException iae) {
1225                     throw new JsonMappingException(null,
1226                             String.format("Failed to narrow value type of %s with concrete-type annotation (value %s), from '%s': %s",
1227                                     type, contentClass.getName(), a.getName(), iae.getMessage()),
1228                             iae);
1229                 }
1230             }
1231         }
1232         return type;
1233     }
1234 
1235     @Override
1236     @Deprecated // since 2.7
findDeserializationContentType(Annotated am, JavaType baseContentType)1237     public Class<?> findDeserializationContentType(Annotated am, JavaType baseContentType) {
1238         return null;
1239     }
1240 
1241     @Override
1242     @Deprecated // since 2.7
findDeserializationType(Annotated am, JavaType baseType)1243     public Class<?> findDeserializationType(Annotated am, JavaType baseType) {
1244         return null;
1245     }
1246 
1247     @Override
1248     @Deprecated // since 2.7
findDeserializationKeyType(Annotated am, JavaType baseKeyType)1249     public Class<?> findDeserializationKeyType(Annotated am, JavaType baseKeyType) {
1250         return null;
1251     }
1252 
1253     /*
1254     /**********************************************************
1255     /* Deserialization: Class annotations
1256     /**********************************************************
1257      */
1258 
1259     @Override
findValueInstantiator(AnnotatedClass ac)1260     public Object findValueInstantiator(AnnotatedClass ac)
1261     {
1262         JsonValueInstantiator ann = _findAnnotation(ac, JsonValueInstantiator.class);
1263         // no 'null' marker yet, so:
1264         return (ann == null) ? null : ann.value();
1265     }
1266 
1267     @Override
findPOJOBuilder(AnnotatedClass ac)1268     public Class<?> findPOJOBuilder(AnnotatedClass ac)
1269     {
1270         JsonDeserialize ann = _findAnnotation(ac, JsonDeserialize.class);
1271         return (ann == null) ? null : _classIfExplicit(ann.builder());
1272     }
1273 
1274     @Override
findPOJOBuilderConfig(AnnotatedClass ac)1275     public JsonPOJOBuilder.Value findPOJOBuilderConfig(AnnotatedClass ac)
1276     {
1277         JsonPOJOBuilder ann = _findAnnotation(ac, JsonPOJOBuilder.class);
1278         return (ann == null) ? null : new JsonPOJOBuilder.Value(ann);
1279     }
1280 
1281     /*
1282     /**********************************************************
1283     /* Deserialization: property annotations
1284     /**********************************************************
1285      */
1286 
1287     @Override
findNameForDeserialization(Annotated a)1288     public PropertyName findNameForDeserialization(Annotated a)
1289     {
1290         // @JsonSetter has precedence over @JsonProperty, being more specific
1291 
1292         boolean useDefault = false;
1293         JsonSetter js = _findAnnotation(a, JsonSetter.class);
1294         if (js != null) {
1295             String s = js.value();
1296             // 04-May-2018, tatu: Need to allow for "nameless" `@JsonSetter` too
1297             if (s.isEmpty()) {
1298                 useDefault = true;
1299             } else {
1300                 return PropertyName.construct(s);
1301             }
1302         }
1303         JsonProperty pann = _findAnnotation(a, JsonProperty.class);
1304         if (pann != null) {
1305             return PropertyName.construct(pann.value());
1306         }
1307         if (useDefault || _hasOneOf(a, ANNOTATIONS_TO_INFER_DESER)) {
1308             return PropertyName.USE_DEFAULT;
1309         }
1310         return null;
1311     }
1312 
1313     @Override
hasAnySetter(Annotated a)1314     public Boolean hasAnySetter(Annotated a) {
1315         JsonAnySetter ann = _findAnnotation(a, JsonAnySetter.class);
1316         return (ann == null) ? null : ann.enabled();
1317     }
1318 
1319     @Override
findSetterInfo(Annotated a)1320     public JsonSetter.Value findSetterInfo(Annotated a) {
1321         return JsonSetter.Value.from(_findAnnotation(a, JsonSetter.class));
1322     }
1323 
1324     @Override // since 2.9
findMergeInfo(Annotated a)1325     public Boolean findMergeInfo(Annotated a) {
1326         JsonMerge ann = _findAnnotation(a, JsonMerge.class);
1327         return (ann == null) ? null : ann.value().asBoolean();
1328     }
1329 
1330     @Override
1331     @Deprecated // since 2.9
hasAnySetterAnnotation(AnnotatedMethod am)1332     public boolean hasAnySetterAnnotation(AnnotatedMethod am) {
1333         return _hasAnnotation(am, JsonAnySetter.class);
1334     }
1335 
1336     @Override
1337     @Deprecated // since 2.9
hasCreatorAnnotation(Annotated a)1338     public boolean hasCreatorAnnotation(Annotated a)
1339     {
1340         /* No dedicated disabling; regular @JsonIgnore used if needs to be
1341          * ignored (and if so, is handled prior to this method getting called)
1342          */
1343          JsonCreator ann = _findAnnotation(a, JsonCreator.class);
1344          if (ann != null) {
1345              return (ann.mode() != JsonCreator.Mode.DISABLED);
1346          }
1347          // 19-Apr-2016, tatu: As per [databind#1197], [databind#1122] (and some related),
1348          //    may or may not consider it a creator
1349          if (_cfgConstructorPropertiesImpliesCreator ) {
1350              if (a instanceof AnnotatedConstructor) {
1351                  if (_java7Helper != null) {
1352                      Boolean b = _java7Helper.hasCreatorAnnotation(a);
1353                      if (b != null) {
1354                          return b.booleanValue();
1355                      }
1356                  }
1357              }
1358          }
1359          return false;
1360     }
1361 
1362     @Override
1363     @Deprecated // since 2.9
findCreatorBinding(Annotated a)1364     public JsonCreator.Mode findCreatorBinding(Annotated a) {
1365         JsonCreator ann = _findAnnotation(a, JsonCreator.class);
1366         return (ann == null) ? null : ann.mode();
1367     }
1368 
1369     @Override
findCreatorAnnotation(MapperConfig<?> config, Annotated a)1370     public JsonCreator.Mode findCreatorAnnotation(MapperConfig<?> config, Annotated a) {
1371         JsonCreator ann = _findAnnotation(a, JsonCreator.class);
1372         if (ann != null) {
1373             return ann.mode();
1374         }
1375         if (_cfgConstructorPropertiesImpliesCreator
1376                 && config.isEnabled(MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES)
1377             ) {
1378             if (a instanceof AnnotatedConstructor) {
1379                 if (_java7Helper != null) {
1380                     Boolean b = _java7Helper.hasCreatorAnnotation(a);
1381                     if ((b != null) && b.booleanValue()) {
1382                         // 13-Sep-2016, tatu: Judgment call, but I don't think JDK ever implies
1383                         //    use of delegate; assumes as-properties implicitly
1384                         return JsonCreator.Mode.PROPERTIES;
1385                     }
1386                 }
1387             }
1388         }
1389         return null;
1390     }
1391 
1392     /*
1393     /**********************************************************
1394     /* Helper methods
1395     /**********************************************************
1396      */
1397 
_isIgnorable(Annotated a)1398     protected boolean _isIgnorable(Annotated a)
1399     {
1400         JsonIgnore ann = _findAnnotation(a, JsonIgnore.class);
1401         if (ann != null) {
1402             return ann.value();
1403         }
1404         if (_java7Helper != null) {
1405             Boolean b = _java7Helper.findTransient(a);
1406             if (b != null) {
1407                 return b.booleanValue();
1408             }
1409         }
1410         return false;
1411     }
1412 
_classIfExplicit(Class<?> cls)1413     protected Class<?> _classIfExplicit(Class<?> cls) {
1414         if (cls == null || ClassUtil.isBogusClass(cls)) {
1415             return null;
1416         }
1417         return cls;
1418     }
1419 
_classIfExplicit(Class<?> cls, Class<?> implicit)1420     protected Class<?> _classIfExplicit(Class<?> cls, Class<?> implicit) {
1421         cls = _classIfExplicit(cls);
1422         return (cls == null || cls == implicit) ? null : cls;
1423     }
1424 
_propertyName(String localName, String namespace)1425     protected PropertyName _propertyName(String localName, String namespace) {
1426         if (localName.isEmpty()) {
1427             return PropertyName.USE_DEFAULT;
1428         }
1429         if (namespace == null || namespace.isEmpty()) {
1430             return PropertyName.construct(localName);
1431         }
1432         return PropertyName.construct(localName, namespace);
1433     }
1434 
_findConstructorName(Annotated a)1435     protected PropertyName _findConstructorName(Annotated a)
1436     {
1437         if (a instanceof AnnotatedParameter) {
1438             AnnotatedParameter p = (AnnotatedParameter) a;
1439             AnnotatedWithParams ctor = p.getOwner();
1440 
1441             if (ctor != null) {
1442                 if (_java7Helper != null) {
1443                     PropertyName name = _java7Helper.findConstructorName(p);
1444                     if (name != null) {
1445                         return name;
1446                     }
1447                 }
1448             }
1449         }
1450         return null;
1451     }
1452 
1453     /**
1454      * Helper method called to construct and initialize instance of {@link TypeResolverBuilder}
1455      * if given annotated element indicates one is needed.
1456      */
1457     @SuppressWarnings("deprecation")
_findTypeResolver(MapperConfig<?> config, Annotated ann, JavaType baseType)1458     protected TypeResolverBuilder<?> _findTypeResolver(MapperConfig<?> config,
1459             Annotated ann, JavaType baseType)
1460     {
1461         // First: maybe we have explicit type resolver?
1462         TypeResolverBuilder<?> b;
1463         JsonTypeInfo info = _findAnnotation(ann, JsonTypeInfo.class);
1464         JsonTypeResolver resAnn = _findAnnotation(ann, JsonTypeResolver.class);
1465 
1466         if (resAnn != null) {
1467             if (info == null) {
1468                 return null;
1469             }
1470             // let's not try to force access override (would need to pass
1471             // settings through if we did, since that's not doable on some platforms)
1472             b = config.typeResolverBuilderInstance(ann, resAnn.value());
1473         } else { // if not, use standard one, if indicated by annotations
1474             if (info == null) {
1475                 return null;
1476             }
1477             // bit special; must return 'marker' to block use of default typing:
1478             if (info.use() == JsonTypeInfo.Id.NONE) {
1479                 return _constructNoTypeResolverBuilder();
1480             }
1481             b = _constructStdTypeResolverBuilder();
1482         }
1483         // Does it define a custom type id resolver?
1484         JsonTypeIdResolver idResInfo = _findAnnotation(ann, JsonTypeIdResolver.class);
1485         TypeIdResolver idRes = (idResInfo == null) ? null
1486                 : config.typeIdResolverInstance(ann, idResInfo.value());
1487         if (idRes != null) {
1488             idRes.init(baseType);
1489         }
1490         b = b.init(info.use(), idRes);
1491         // 13-Aug-2011, tatu: One complication; external id only works for properties;
1492         //    so if declared for a Class, we will need to map it to "PROPERTY"
1493         //    instead of "EXTERNAL_PROPERTY"
1494         JsonTypeInfo.As inclusion = info.include();
1495         if (inclusion == JsonTypeInfo.As.EXTERNAL_PROPERTY && (ann instanceof AnnotatedClass)) {
1496             inclusion = JsonTypeInfo.As.PROPERTY;
1497         }
1498         b = b.inclusion(inclusion);
1499         b = b.typeProperty(info.property());
1500         Class<?> defaultImpl = info.defaultImpl();
1501 
1502         // 08-Dec-2014, tatu: To deprecate `JsonTypeInfo.None` we need to use other placeholder(s);
1503         //   and since `java.util.Void` has other purpose (to indicate "deser as null"), we'll instead
1504         //   use `JsonTypeInfo.class` itself. But any annotation type will actually do, as they have no
1505         //   valid use (cannot instantiate as default)
1506         if (defaultImpl != JsonTypeInfo.None.class && !defaultImpl.isAnnotation()) {
1507             b = b.defaultImpl(defaultImpl);
1508         }
1509         b = b.typeIdVisibility(info.visible());
1510         return b;
1511     }
1512 
1513     /**
1514      * Helper method for constructing standard {@link TypeResolverBuilder}
1515      * implementation.
1516      */
_constructStdTypeResolverBuilder()1517     protected StdTypeResolverBuilder _constructStdTypeResolverBuilder() {
1518         return new StdTypeResolverBuilder();
1519     }
1520 
1521     /**
1522      * Helper method for dealing with "no type info" marker; can't be null
1523      * (as it'd be replaced by default typing)
1524      */
_constructNoTypeResolverBuilder()1525     protected StdTypeResolverBuilder _constructNoTypeResolverBuilder() {
1526         return StdTypeResolverBuilder.noTypeInfoBuilder();
1527     }
1528 
_primitiveAndWrapper(Class<?> baseType, Class<?> refinement)1529     private boolean _primitiveAndWrapper(Class<?> baseType, Class<?> refinement)
1530     {
1531         if (baseType.isPrimitive()) {
1532             return baseType == ClassUtil.primitiveType(refinement);
1533         }
1534         if (refinement.isPrimitive()) {
1535             return refinement == ClassUtil.primitiveType(baseType);
1536         }
1537         return false;
1538     }
1539 
_primitiveAndWrapper(JavaType baseType, Class<?> refinement)1540     private boolean _primitiveAndWrapper(JavaType baseType, Class<?> refinement)
1541     {
1542         if (baseType.isPrimitive()) {
1543             return baseType.hasRawClass(ClassUtil.primitiveType(refinement));
1544         }
1545         if (refinement.isPrimitive()) {
1546             return refinement == ClassUtil.primitiveType(baseType.getRawClass());
1547         }
1548         return false;
1549     }
1550 }
1551