1 package com.fasterxml.jackson.databind.introspect; 2 3 import java.lang.annotation.Annotation; 4 import java.util.*; 5 6 import com.fasterxml.jackson.databind.util.Annotations; 7 8 /** 9 * Simple helper class used to keep track of collection of 10 * Jackson Annotations associated with annotatable things 11 * (methods, constructors, classes). 12 * Note that only Jackson-owned annotations are tracked (for now?). 13 */ 14 public final class AnnotationMap implements Annotations 15 { 16 protected HashMap<Class<?>,Annotation> _annotations; 17 AnnotationMap()18 public AnnotationMap() { } 19 of(Class<?> type, Annotation value)20 public static AnnotationMap of(Class<?> type, Annotation value) { 21 HashMap<Class<?>,Annotation> ann = new HashMap<>(4); 22 ann.put(type, value); 23 return new AnnotationMap(ann); 24 } 25 AnnotationMap(HashMap<Class<?>,Annotation> a)26 AnnotationMap(HashMap<Class<?>,Annotation> a) { 27 _annotations = a; 28 } 29 30 /* 31 /********************************************************** 32 /* Annotations impl 33 /********************************************************** 34 */ 35 36 @SuppressWarnings("unchecked") 37 @Override get(Class<A> cls)38 public <A extends Annotation> A get(Class<A> cls) 39 { 40 if (_annotations == null) { 41 return null; 42 } 43 return (A) _annotations.get(cls); 44 } 45 46 @Override has(Class<?> cls)47 public boolean has(Class<?> cls) 48 { 49 if (_annotations == null) { 50 return false; 51 } 52 return _annotations.containsKey(cls); 53 } 54 55 /** 56 * Helper method that can be used for a "bulk" check to see if at least 57 * one of given annotation types is included within this map. 58 * 59 * @since 2.7 60 */ 61 @Override hasOneOf(Class<? extends Annotation>[] annoClasses)62 public boolean hasOneOf(Class<? extends Annotation>[] annoClasses) { 63 if (_annotations != null) { 64 for (int i = 0, end = annoClasses.length; i < end; ++i) { 65 if (_annotations.containsKey(annoClasses[i])) { 66 return true; 67 } 68 } 69 } 70 return false; 71 } 72 73 /* 74 /********************************************************** 75 /* Other API 76 /********************************************************** 77 */ 78 79 /** 80 * @since 2.3 81 */ annotations()82 public Iterable<Annotation> annotations() { 83 if (_annotations == null || _annotations.size() == 0) { 84 return Collections.emptyList(); 85 } 86 return _annotations.values(); 87 } 88 merge(AnnotationMap primary, AnnotationMap secondary)89 public static AnnotationMap merge(AnnotationMap primary, AnnotationMap secondary) 90 { 91 if (primary == null || primary._annotations == null || primary._annotations.isEmpty()) { 92 return secondary; 93 } 94 if (secondary == null || secondary._annotations == null || secondary._annotations.isEmpty()) { 95 return primary; 96 } 97 HashMap<Class<?>,Annotation> annotations = new HashMap<Class<?>,Annotation>(); 98 // add secondary ones first 99 for (Annotation ann : secondary._annotations.values()) { 100 annotations.put(ann.annotationType(), ann); 101 } 102 // to be overridden by primary ones 103 for (Annotation ann : primary._annotations.values()) { 104 annotations.put(ann.annotationType(), ann); 105 } 106 return new AnnotationMap(annotations); 107 } 108 109 @Override size()110 public int size() { 111 return (_annotations == null) ? 0 : _annotations.size(); 112 } 113 114 /** 115 * Method called to add specified annotation in the Map, but 116 * only if it didn't yet exist. 117 */ addIfNotPresent(Annotation ann)118 public boolean addIfNotPresent(Annotation ann) 119 { 120 if (_annotations == null || !_annotations.containsKey(ann.annotationType())) { 121 _add(ann); 122 return true; 123 } 124 return false; 125 } 126 127 /** 128 * Method called to add specified annotation in the Map. 129 * 130 * @return True if the addition changed the contents, that is, this map did not 131 * already have specified annotation 132 */ add(Annotation ann)133 public boolean add(Annotation ann) { 134 return _add(ann); 135 } 136 137 @Override toString()138 public String toString() { 139 if (_annotations == null) { 140 return "[null]"; 141 } 142 return _annotations.toString(); 143 } 144 145 /* 146 /********************************************************** 147 /* Helper methods 148 /********************************************************** 149 */ 150 _add(Annotation ann)151 protected final boolean _add(Annotation ann) { 152 if (_annotations == null) { 153 _annotations = new HashMap<Class<?>,Annotation>(); 154 } 155 Annotation previous = _annotations.put(ann.annotationType(), ann); 156 return (previous == null) || !previous.equals(ann); 157 } 158 } 159