3
3
import java .util .*;
4
4
5
5
import com .fasterxml .jackson .databind .AnnotationIntrospector ;
6
+ import com .fasterxml .jackson .databind .DeserializationConfig ;
7
+ import com .fasterxml .jackson .databind .MapperFeature ;
6
8
import com .fasterxml .jackson .databind .introspect .AnnotatedMember ;
7
9
8
10
/**
@@ -21,31 +23,51 @@ public class EnumResolver implements java.io.Serializable
21
23
22
24
protected final Enum <?> _defaultValue ;
23
25
26
+ /**
27
+ * @since 2.12
28
+ */
29
+ protected final boolean _isIgnoreCase ;
30
+
31
+ /**
32
+ * @since 2.12
33
+ */
24
34
protected EnumResolver (Class <Enum <?>> enumClass , Enum <?>[] enums ,
25
- HashMap <String , Enum <?>> map , Enum <?> defaultValue )
35
+ HashMap <String , Enum <?>> map , Enum <?> defaultValue ,
36
+ boolean isIgnoreCase )
26
37
{
27
38
_enumClass = enumClass ;
28
39
_enums = enums ;
29
40
_enumsById = map ;
30
41
_defaultValue = defaultValue ;
42
+ _isIgnoreCase = isIgnoreCase ;
31
43
}
32
44
33
45
/**
34
46
* Factory method for constructing resolver that maps from Enum.name() into
35
- * Enum value
47
+ * Enum value.
48
+ *
49
+ * @since 2.12
50
+ */
51
+ public static EnumResolver constructFor (DeserializationConfig config ,
52
+ Class <?> enumCls ) {
53
+ return _constructFor (enumCls , config .getAnnotationIntrospector (),
54
+ config .isEnabled (MapperFeature .ACCEPT_CASE_INSENSITIVE_ENUMS ));
55
+ }
56
+
57
+ /**
58
+ * @since 2.12
36
59
*/
37
- public static EnumResolver constructFor (Class <Enum <?>> enumCls , AnnotationIntrospector ai )
60
+ protected static EnumResolver _constructFor (Class <?> enumCls0 ,
61
+ AnnotationIntrospector ai , boolean isIgnoreCase )
38
62
{
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 ]);
63
+ final Class <Enum <?>> enumCls = _enumClass (enumCls0 );
64
+ final Enum <?>[] enumConstants = _enumConstants (enumCls0 );
65
+ String [] names = ai .findEnumValues (enumCls , enumConstants , new String [enumConstants .length ]);
44
66
final String [][] allAliases = new String [names .length ][];
45
- ai .findEnumAliases (enumCls , enumValues , allAliases );
67
+ ai .findEnumAliases (enumCls , enumConstants , allAliases );
46
68
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 ];
69
+ for (int i = 0 , len = enumConstants .length ; i < len ; ++i ) {
70
+ final Enum <?> enumValue = enumConstants [i ];
49
71
String name = names [i ];
50
72
if (name == null ) {
51
73
name = enumValue .name ();
@@ -62,27 +84,30 @@ public static EnumResolver constructFor(Class<Enum<?>> enumCls, AnnotationIntros
62
84
}
63
85
}
64
86
}
65
- return new EnumResolver (enumCls , enumValues , map , ai .findDefaultEnumValue (enumCls ));
87
+ return new EnumResolver (enumCls , enumConstants , map ,
88
+ _enumDefault (ai , enumCls ), isIgnoreCase );
66
89
}
67
90
68
91
/**
69
- * @deprecated Since 2.8, use {@link #constructUsingToString(Class, AnnotationIntrospector)} instead
92
+ * Factory method for constructing resolver that maps from Enum.toString() into
93
+ * Enum value
94
+ *
95
+ * @since 2.12
70
96
*/
71
- @ Deprecated
72
- public static EnumResolver constructUsingToString (Class <Enum <?>> enumCls ) {
73
- return constructUsingToString (enumCls , null );
97
+ public static EnumResolver constructUsingToString (DeserializationConfig config ,
98
+ Class <?> enumCls ) {
99
+ return _constructUsingToString (enumCls , config .getAnnotationIntrospector (),
100
+ config .isEnabled (MapperFeature .ACCEPT_CASE_INSENSITIVE_ENUMS ));
74
101
}
75
102
76
103
/**
77
- * Factory method for constructing resolver that maps from Enum.toString() into
78
- * Enum value
79
- *
80
- * @since 2.8
104
+ * @since 2.12
81
105
*/
82
- public static EnumResolver constructUsingToString (Class <Enum <?>> enumCls ,
83
- AnnotationIntrospector ai )
106
+ protected static EnumResolver _constructUsingToString (Class <?> enumCls0 ,
107
+ AnnotationIntrospector ai , boolean isIgnoreCase )
84
108
{
85
- Enum <?>[] enumConstants = enumCls .getEnumConstants ();
109
+ final Class <Enum <?>> enumCls = _enumClass (enumCls0 );
110
+ final Enum <?>[] enumConstants = _enumConstants (enumCls0 );
86
111
HashMap <String , Enum <?>> map = new HashMap <String , Enum <?>>();
87
112
final String [][] allAliases = new String [enumConstants .length ][];
88
113
ai .findEnumAliases (enumCls , enumConstants , allAliases );
@@ -102,21 +127,34 @@ public static EnumResolver constructUsingToString(Class<Enum<?>> enumCls,
102
127
}
103
128
}
104
129
}
105
- return new EnumResolver (enumCls , enumConstants , map , ai .findDefaultEnumValue (enumCls ));
130
+ return new EnumResolver (enumCls , enumConstants , map ,
131
+ _enumDefault (ai , enumCls ), isIgnoreCase );
106
132
}
107
133
108
134
/**
109
- * @since 2.9
135
+ * Method used when actual String serialization is indicated using @JsonValue
136
+ * on a method in Enum class.
137
+ *
138
+ * @since 2.12
110
139
*/
111
- public static EnumResolver constructUsingMethod (Class <Enum <?>> enumCls ,
112
- AnnotatedMember accessor ,
113
- AnnotationIntrospector ai )
140
+ public static EnumResolver constructUsingMethod (DeserializationConfig config ,
141
+ Class <?> enumCls , AnnotatedMember accessor ) {
142
+ return _constructUsingMethod (enumCls , accessor , config .getAnnotationIntrospector (),
143
+ config .isEnabled (MapperFeature .ACCEPT_CASE_INSENSITIVE_ENUMS ));
144
+ }
145
+
146
+ /**
147
+ * @since 2.12
148
+ */
149
+ protected static EnumResolver _constructUsingMethod (Class <?> enumCls0 ,
150
+ AnnotatedMember accessor , AnnotationIntrospector ai , boolean isIgnoreCase )
114
151
{
115
- Enum <?>[] enumValues = enumCls .getEnumConstants ();
152
+ final Class <Enum <?>> enumCls = _enumClass (enumCls0 );
153
+ final Enum <?>[] enumConstants = _enumConstants (enumCls0 );
116
154
HashMap <String , Enum <?>> map = new HashMap <String , Enum <?>>();
117
155
// from last to first, so that in case of duplicate values, first wins
118
- for (int i = enumValues .length ; --i >= 0 ; ) {
119
- Enum <?> en = enumValues [i ];
156
+ for (int i = enumConstants .length ; --i >= 0 ; ) {
157
+ Enum <?> en = enumConstants [i ];
120
158
try {
121
159
Object o = accessor .getValue (en );
122
160
if (o != null ) {
@@ -126,60 +164,133 @@ public static EnumResolver constructUsingMethod(Class<Enum<?>> enumCls,
126
164
throw new IllegalArgumentException ("Failed to access @JsonValue of Enum value " +en +": " +e .getMessage ());
127
165
}
128
166
}
129
- Enum <?> defaultEnum = ( ai != null ) ? ai . findDefaultEnumValue ( enumCls ) : null ;
130
- return new EnumResolver ( enumCls , enumValues , map , defaultEnum );
167
+ return new EnumResolver ( enumCls , enumConstants , map ,
168
+ _enumDefault ( ai , enumCls ), isIgnoreCase );
131
169
}
132
170
171
+ public CompactStringObjectMap constructLookup () {
172
+ return CompactStringObjectMap .construct (_enumsById );
173
+ }
174
+
175
+ @ SuppressWarnings ("unchecked" )
176
+ protected static Class <Enum <?>> _enumClass (Class <?> enumCls0 ) {
177
+ return (Class <Enum <?>>) enumCls0 ;
178
+ }
179
+
180
+ protected static Enum <?>[] _enumConstants (Class <?> enumCls ) {
181
+ final Enum <?>[] enumValues = _enumClass (enumCls ).getEnumConstants ();
182
+ if (enumValues == null ) {
183
+ throw new IllegalArgumentException ("No enum constants for class " +enumCls .getName ());
184
+ }
185
+ return enumValues ;
186
+ }
187
+
188
+ protected static Enum <?> _enumDefault (AnnotationIntrospector intr , Class <?> enumCls ) {
189
+ return (intr != null ) ? intr .findDefaultEnumValue (_enumClass (enumCls )) : null ;
190
+ }
191
+
192
+ /*
193
+ /**********************************************************************
194
+ /* Deprecated constructors, factory methods
195
+ /**********************************************************************
196
+ */
197
+
133
198
/**
134
- * This method is needed because of the dynamic nature of constructing Enum
135
- * resolvers.
199
+ * @deprecated Since 2.12 (remove from 2.13+ not part of public API)
136
200
*/
137
- @ SuppressWarnings ({ "unchecked" })
138
- public static EnumResolver constructUnsafe (Class <?> rawEnumCls , AnnotationIntrospector ai )
139
- {
140
- /* This is oh so wrong... but at least ugliness is mostly hidden in just
141
- * this one place.
142
- */
143
- Class <Enum <?>> enumCls = (Class <Enum <?>>) rawEnumCls ;
144
- return constructFor (enumCls , ai );
201
+ @ Deprecated // since 2.12
202
+ protected EnumResolver (Class <Enum <?>> enumClass , Enum <?>[] enums ,
203
+ HashMap <String , Enum <?>> map , Enum <?> defaultValue ) {
204
+ this (enumClass , enums , map , defaultValue , false );
205
+ }
206
+
207
+ /**
208
+ * @deprecated Since 2.12
209
+ */
210
+ @ Deprecated // since 2.12
211
+ public static EnumResolver constructFor (Class <Enum <?>> enumCls , AnnotationIntrospector ai ) {
212
+ return _constructFor (enumCls , ai , false );
213
+ }
214
+
215
+ /**
216
+ * @deprecated Since 2.12
217
+ */
218
+ @ Deprecated // since 2.12
219
+ public static EnumResolver constructUnsafe (Class <?> rawEnumCls , AnnotationIntrospector ai ) {
220
+ return _constructFor (rawEnumCls , ai , false );
221
+ }
222
+
223
+ /**
224
+ * @deprecated Since 2.12
225
+ */
226
+ @ Deprecated // since 2.12
227
+ public static EnumResolver constructUsingToString (Class <Enum <?>> enumCls ,
228
+ AnnotationIntrospector ai ) {
229
+ return _constructUsingToString (enumCls , ai , false );
145
230
}
146
231
147
232
/**
148
- * Method that needs to be used instead of {@link #constructUsingToString}
149
- * if static type of enum is not known.
150
- *
151
233
* @since 2.8
234
+ * @deprecated Since 2.12
152
235
*/
153
- @ SuppressWarnings ({ "unchecked" })
236
+ @ Deprecated // since 2.12
154
237
public static EnumResolver constructUnsafeUsingToString (Class <?> rawEnumCls ,
155
- AnnotationIntrospector ai )
156
- {
157
- // oh so wrong... not much that can be done tho
158
- Class <Enum <?>> enumCls = (Class <Enum <?>>) rawEnumCls ;
159
- return constructUsingToString (enumCls , ai );
238
+ AnnotationIntrospector ai ) {
239
+ return _constructUsingToString (rawEnumCls , ai , false );
240
+ }
241
+
242
+ /**
243
+ * @deprecated Since 2.8 (remove from 2.13 or later)
244
+ */
245
+ @ Deprecated
246
+ public static EnumResolver constructUsingToString (Class <Enum <?>> enumCls ) {
247
+ return _constructUsingToString (enumCls , null , false );
248
+ }
249
+
250
+ /**
251
+ * @deprecated Since 2.12
252
+ */
253
+ @ Deprecated
254
+ public static EnumResolver constructUsingMethod (Class <Enum <?>> enumCls ,
255
+ AnnotatedMember accessor , AnnotationIntrospector ai ) {
256
+ return _constructUsingMethod (enumCls , accessor , ai , false );
160
257
}
161
258
162
259
/**
163
- * Method used when actual String serialization is indicated using @JsonValue
164
- * on a method.
165
- *
166
260
* @since 2.9
261
+ * @deprecated Since 2.12
167
262
*/
168
- @ SuppressWarnings ({ "unchecked" })
263
+ @ Deprecated
169
264
public static EnumResolver constructUnsafeUsingMethod (Class <?> rawEnumCls ,
170
- AnnotatedMember accessor ,
171
- AnnotationIntrospector ai )
172
- {
173
- // wrong as ever but:
174
- Class <Enum <?>> enumCls = (Class <Enum <?>>) rawEnumCls ;
175
- return constructUsingMethod (enumCls , accessor , ai );
265
+ AnnotatedMember accessor , AnnotationIntrospector ai ) {
266
+ return _constructUsingMethod (rawEnumCls , accessor , ai , false );
176
267
}
177
268
178
- public CompactStringObjectMap constructLookup () {
179
- return CompactStringObjectMap .construct (_enumsById );
269
+ /*
270
+ /**********************************************************************
271
+ /* Public API
272
+ /**********************************************************************
273
+ */
274
+
275
+ public Enum <?> findEnum (final String key ) {
276
+ Enum <?> en = _enumsById .get (key );
277
+ if (en == null ) {
278
+ if (_isIgnoreCase ) {
279
+ return _findEnumCaseInsensitive (key );
280
+ }
281
+ }
282
+ return en ;
180
283
}
181
284
182
- public Enum <?> findEnum (String key ) { return _enumsById .get (key ); }
285
+ // @since 2.12
286
+ protected Enum <?> _findEnumCaseInsensitive (final String key ) {
287
+ for (Map .Entry <String , Enum <?>> entry : _enumsById .entrySet ()) {
288
+ if (key .equalsIgnoreCase (entry .getKey ())) {
289
+ return entry .getValue ();
290
+ }
291
+ }
292
+ return null ;
293
+ }
183
294
184
295
public Enum <?> getEnum (int index ) {
185
296
if (index < 0 || index >= _enums .length ) {
0 commit comments