1 package com.fasterxml.jackson.databind.introspect; 2 3 import java.util.HashMap; 4 import java.util.Map; 5 6 import com.fasterxml.jackson.databind.type.ClassKey; 7 8 /** 9 * Simple implementation of {@link ClassIntrospector.MixInResolver} 10 * that just uses a {@link java.util.Map} for containing mapping 11 * from target to mix-in classes. 12 *<p> 13 * Implementation is only thread-safe after initialization (that is, 14 * when underlying Map is not modified but only read). 15 * 16 * @since 2.6 17 */ 18 public class SimpleMixInResolver 19 implements ClassIntrospector.MixInResolver, 20 java.io.Serializable 21 { 22 private static final long serialVersionUID = 1L; 23 24 /** 25 * External resolver that gets called before looking at any locally defined 26 * mix-in target classes. 27 */ 28 protected final ClassIntrospector.MixInResolver _overrides; 29 30 /** 31 * Simple mix-in targets defined locally. 32 */ 33 protected Map<ClassKey,Class<?>> _localMixIns; 34 SimpleMixInResolver(ClassIntrospector.MixInResolver overrides)35 public SimpleMixInResolver(ClassIntrospector.MixInResolver overrides) { 36 _overrides = overrides; 37 } 38 SimpleMixInResolver(ClassIntrospector.MixInResolver overrides, Map<ClassKey,Class<?>> mixins)39 protected SimpleMixInResolver(ClassIntrospector.MixInResolver overrides, 40 Map<ClassKey,Class<?>> mixins) { 41 _overrides = overrides; 42 _localMixIns = mixins; 43 } 44 45 /** 46 * Mutant factory for constructor a new resolver instance with given 47 * mix-in resolver override. 48 */ withOverrides(ClassIntrospector.MixInResolver overrides)49 public SimpleMixInResolver withOverrides(ClassIntrospector.MixInResolver overrides) { 50 return new SimpleMixInResolver(overrides, _localMixIns); 51 } 52 53 /** 54 * Mutant factory method that constructs a new instance that has no locally 55 * defined mix-in/target mappings. 56 */ withoutLocalDefinitions()57 public SimpleMixInResolver withoutLocalDefinitions() { 58 return new SimpleMixInResolver(_overrides, null); 59 } 60 setLocalDefinitions(Map<Class<?>, Class<?>> sourceMixins)61 public void setLocalDefinitions(Map<Class<?>, Class<?>> sourceMixins) { 62 if (sourceMixins == null || sourceMixins.isEmpty()) { 63 _localMixIns = null; 64 } else { 65 Map<ClassKey,Class<?>> mixIns = new HashMap<ClassKey,Class<?>>(sourceMixins.size()); 66 for (Map.Entry<Class<?>,Class<?>> en : sourceMixins.entrySet()) { 67 mixIns.put(new ClassKey(en.getKey()), en.getValue()); 68 } 69 _localMixIns = mixIns; 70 } 71 } 72 addLocalDefinition(Class<?> target, Class<?> mixinSource)73 public void addLocalDefinition(Class<?> target, Class<?> mixinSource) { 74 if (_localMixIns == null) { 75 _localMixIns = new HashMap<ClassKey,Class<?>>(); 76 } 77 _localMixIns.put(new ClassKey(target), mixinSource); 78 } 79 80 @Override copy()81 public SimpleMixInResolver copy() { 82 ClassIntrospector.MixInResolver overrides = (_overrides == null) 83 ? null : _overrides.copy(); 84 Map<ClassKey,Class<?>> mixIns = (_localMixIns == null) 85 ? null : new HashMap<ClassKey,Class<?>>(_localMixIns); 86 return new SimpleMixInResolver(overrides, mixIns); 87 } 88 89 @Override findMixInClassFor(Class<?> cls)90 public Class<?> findMixInClassFor(Class<?> cls) 91 { 92 Class<?> mixin = (_overrides == null) ? null : _overrides.findMixInClassFor(cls); 93 if (mixin == null && (_localMixIns != null)) { 94 mixin = _localMixIns.get(new ClassKey(cls)); 95 } 96 return mixin; 97 } 98 localSize()99 public int localSize() { 100 return (_localMixIns == null) ? 0 : _localMixIns.size(); 101 } 102 103 /** 104 * Method that may be called for optimization purposes, to see if calls to 105 * mix-in resolver may be avoided. Return value of {@code true} means that 106 * it is possible that a mix-in class will be found; {@code false} that no 107 * mix-in will ever be found. In latter case caller can avoid calls altogether. 108 *<p> 109 * Note that the reason for "empty" resolvers is to use "null object" for simplifying 110 * code. 111 * 112 * @return True, if this resolver MAY have mix-ins to apply; false if not (it 113 * is "empty") 114 * 115 * @since 2.10.1 116 */ hasMixIns()117 public boolean hasMixIns() { 118 if (_localMixIns == null) { 119 // if neither local mix-ins nor overrides, no mix-ins 120 if (_overrides == null) { 121 return false; 122 } 123 // or, if no local mix-ins and can delegate to resolver 124 if (_overrides instanceof SimpleMixInResolver) { 125 return ((SimpleMixInResolver) _overrides).hasMixIns(); 126 } 127 } 128 // cannot rule out the possibility, so... 129 return true; 130 } 131 } 132