1 package com.fasterxml.jackson.databind.util;
2
3 import java.util.*;
4
5 import com.fasterxml.jackson.databind.AnnotationIntrospector;
6 import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
7
8
12 public class EnumResolver implements java.io.Serializable
13 {
14 private static final long serialVersionUID = 1L;
15
16 protected final Class<Enum<?>> _enumClass;
17
18 protected final Enum<?>[] _enums;
19
20 protected final HashMap<String, Enum<?>> _enumsById;
21
22 protected final Enum<?> _defaultValue;
23
24 protected EnumResolver(Class<Enum<?>> enumClass, Enum<?>[] enums,
25 HashMap<String, Enum<?>> map, Enum<?> defaultValue)
26 {
27 _enumClass = enumClass;
28 _enums = enums;
29 _enumsById = map;
30 _defaultValue = defaultValue;
31 }
32
33
37 public static EnumResolver constructFor(Class<Enum<?>> enumCls, AnnotationIntrospector ai)
38 {
39 Enum<?>[] enumValues = enumCls.getEnumConstants();
40 if (enumValues == null) {
41 throw new IllegalArgumentException("No enum constants for class "+enumCls.getName());
42 }
43 String[] names = ai.findEnumValues(enumCls, enumValues, new String[enumValues.length]);
44 final String[][] allAliases = new String[names.length][];
45 ai.findEnumAliases(enumCls, enumValues, allAliases);
46 HashMap<String, Enum<?>> map = new HashMap<String, Enum<?>>();
47 for (int i = 0, len = enumValues.length; i < len; ++i) {
48 final Enum<?> enumValue = enumValues[i];
49 String name = names[i];
50 if (name == null) {
51 name = enumValue.name();
52 }
53 map.put(name, enumValue);
54 String[] aliases = allAliases[i];
55 if (aliases != null) {
56 for (String alias : aliases) {
57
58
59 if (!map.containsKey(alias)) {
60 map.put(alias, enumValue);
61 }
62 }
63 }
64 }
65 return new EnumResolver(enumCls, enumValues, map, ai.findDefaultEnumValue(enumCls));
66 }
67
68
71 @Deprecated
72 public static EnumResolver constructUsingToString(Class<Enum<?>> enumCls) {
73 return constructUsingToString(enumCls, null);
74 }
75
76
82 public static EnumResolver constructUsingToString(Class<Enum<?>> enumCls,
83 AnnotationIntrospector ai)
84 {
85 Enum<?>[] enumConstants = enumCls.getEnumConstants();
86 HashMap<String, Enum<?>> map = new HashMap<String, Enum<?>>();
87 final String[][] allAliases = new String[enumConstants.length][];
88 ai.findEnumAliases(enumCls, enumConstants, allAliases);
89
90
91 for (int i = enumConstants.length; --i >= 0; ) {
92 Enum<?> enumValue = enumConstants[i];
93 map.put(enumValue.toString(), enumValue);
94 String[] aliases = allAliases[i];
95 if (aliases != null) {
96 for (String alias : aliases) {
97
98
99 if (!map.containsKey(alias)) {
100 map.put(alias, enumValue);
101 }
102 }
103 }
104 }
105 return new EnumResolver(enumCls, enumConstants, map, ai.findDefaultEnumValue(enumCls));
106 }
107
108
111 public static EnumResolver constructUsingMethod(Class<Enum<?>> enumCls,
112 AnnotatedMember accessor,
113 AnnotationIntrospector ai)
114 {
115 Enum<?>[] enumValues = enumCls.getEnumConstants();
116 HashMap<String, Enum<?>> map = new HashMap<String, Enum<?>>();
117
118 for (int i = enumValues.length; --i >= 0; ) {
119 Enum<?> en = enumValues[i];
120 try {
121 Object o = accessor.getValue(en);
122 if (o != null) {
123 map.put(o.toString(), en);
124 }
125 } catch (Exception e) {
126 throw new IllegalArgumentException("Failed to access @JsonValue of Enum value "+en+": "+e.getMessage());
127 }
128 }
129 Enum<?> defaultEnum = (ai != null) ? ai.findDefaultEnumValue(enumCls) : null;
130 return new EnumResolver(enumCls, enumValues, map, defaultEnum);
131 }
132
133
137 @SuppressWarnings({ "unchecked" })
138 public static EnumResolver constructUnsafe(Class<?> rawEnumCls, AnnotationIntrospector ai)
139 {
140
143 Class<Enum<?>> enumCls = (Class<Enum<?>>) rawEnumCls;
144 return constructFor(enumCls, ai);
145 }
146
147
153 @SuppressWarnings({ "unchecked" })
154 public static EnumResolver constructUnsafeUsingToString(Class<?> rawEnumCls,
155 AnnotationIntrospector ai)
156 {
157
158 Class<Enum<?>> enumCls = (Class<Enum<?>>) rawEnumCls;
159 return constructUsingToString(enumCls, ai);
160 }
161
162
168 @SuppressWarnings({ "unchecked" })
169 public static EnumResolver constructUnsafeUsingMethod(Class<?> rawEnumCls,
170 AnnotatedMember accessor,
171 AnnotationIntrospector ai)
172 {
173
174 Class<Enum<?>> enumCls = (Class<Enum<?>>) rawEnumCls;
175 return constructUsingMethod(enumCls, accessor, ai);
176 }
177
178 public CompactStringObjectMap constructLookup() {
179 return CompactStringObjectMap.construct(_enumsById);
180 }
181
182 public Enum<?> findEnum(String key) { return _enumsById.get(key); }
183
184 public Enum<?> getEnum(int index) {
185 if (index < 0 || index >= _enums.length) {
186 return null;
187 }
188 return _enums[index];
189 }
190
191 public Enum<?> getDefaultValue(){
192 return _defaultValue;
193 }
194
195 public Enum<?>[] getRawEnums() {
196 return _enums;
197 }
198
199 public List<Enum<?>> getEnums() {
200 ArrayList<Enum<?>> enums = new ArrayList<Enum<?>>(_enums.length);
201 for (Enum<?> e : _enums) {
202 enums.add(e);
203 }
204 return enums;
205 }
206
207
210 public Collection<String> getEnumIds() {
211 return _enumsById.keySet();
212 }
213
214 public Class<Enum<?>> getEnumClass() { return _enumClass; }
215
216 public int lastValidIndex() { return _enums.length-1; }
217 }
218
219