Skip to content

Commit 84424ca

Browse files
author
Alejandro Rivera
committed
Generalized logic to find an annotated Enum value and extracted it to ClassUtil.
1 parent 1dd4bdd commit 84424ca

File tree

2 files changed

+35
-28
lines changed

2 files changed

+35
-28
lines changed

src/main/java/com/fasterxml/jackson/databind/util/ClassUtil.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -842,6 +842,34 @@ public static Class<? extends Enum<?>> findEnumType(Class<?> cls)
842842
return (Class<? extends Enum<?>>) cls;
843843
}
844844

845+
/**
846+
* A method that will look for the first Enum value annotated with the given Annotation.
847+
* <p>
848+
* If there's more than one value annotated, the first one found will be returned. Which one exactly is used is undetermined.
849+
*
850+
* @param enumClass The Enum class to scan for a value with the given annotation
851+
* @param annotationClass The annotation to look for.
852+
* @return the Enum value annotated with the given Annotation or {@code null} if none is found.
853+
* @throws IllegalArgumentException if there's a reflection issue accessing the Enum
854+
* @since 2.8
855+
*/
856+
public static <T extends Annotation> Enum<?> findFirstAnnotatedEnumValue(Class<Enum<?>> enumClass, Class<T> annotationClass) {
857+
Field[] fields = getDeclaredFields(enumClass);
858+
for (Field field : fields) {
859+
Annotation defaultValueAnnotation = field.getAnnotation(annotationClass);
860+
if (defaultValueAnnotation != null && field.isEnumConstant()) {
861+
try {
862+
Method valueOf = enumClass.getDeclaredMethod("valueOf", String.class); // using `getMethod` causes IllegalAccessException
863+
valueOf.setAccessible(true);
864+
return enumClass.cast(valueOf.invoke(null, field.getName()));
865+
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
866+
throw new IllegalArgumentException("Could not extract Enum annotated with " + annotationClass.getSimpleName(), e);
867+
}
868+
}
869+
}
870+
return null;
871+
}
872+
845873
/*
846874
/**********************************************************
847875
/* Jackson-specific stuff

src/main/java/com/fasterxml/jackson/databind/util/EnumResolver.java

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
package com.fasterxml.jackson.databind.util;
22

33
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
4-
import com.fasterxml.jackson.annotation.JsonProperty;
54
import com.fasterxml.jackson.databind.AnnotationIntrospector;
5+
import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
66

7-
import java.lang.reflect.Field;
8-
import java.lang.reflect.InvocationTargetException;
97
import java.lang.reflect.Method;
108
import java.util.*;
119

@@ -53,30 +51,11 @@ public static EnumResolver constructFor(Class<Enum<?>> enumCls, AnnotationIntros
5351
map.put(name, enumValues[i]);
5452
}
5553

56-
Enum<?> defaultEnum = determineDefaultEnumValue(enumCls);
54+
Enum<?> defaultEnum = ClassUtil.findFirstAnnotatedEnumValue(enumCls, JsonEnumDefaultValue.class);
5755

5856
return new EnumResolver(enumCls, enumValues, map, defaultEnum);
5957
}
6058

61-
private static Enum<?> determineDefaultEnumValue(Class<Enum<?>> enumCls) {
62-
Field[] fields = ClassUtil.getDeclaredFields(enumCls);
63-
for (Field field : fields) {
64-
JsonEnumDefaultValue defaultValueAnnotation = field.getAnnotation(JsonEnumDefaultValue.class);
65-
if (defaultValueAnnotation != null && field.isEnumConstant()) {
66-
try {
67-
Method valueOf = enumCls.getDeclaredMethod("valueOf", String.class); // using `getMethod` causes IllegalAccessException
68-
valueOf.setAccessible(true);
69-
return enumCls.cast(valueOf.invoke(null, field.getName()));
70-
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
71-
java.util.logging.Logger.getLogger(EnumResolver.class.getName())
72-
.warning("Could not extract Enum annotated with " + JsonEnumDefaultValue.class.getSimpleName()
73-
+ " due to: " + e.getLocalizedMessage());
74-
}
75-
}
76-
}
77-
return null;
78-
}
79-
8059
/**
8160
* Factory method for constructing resolver that maps from Enum.toString() into
8261
* Enum value
@@ -90,8 +69,9 @@ public static EnumResolver constructUsingToString(Class<Enum<?>> enumCls)
9069
Enum<?> e = enumValues[i];
9170
map.put(e.toString(), e);
9271
}
93-
Enum<?> defaultValue = determineDefaultEnumValue(enumCls);
94-
return new EnumResolver(enumCls, enumValues, map, defaultValue);
72+
73+
Enum<?> defaultEnum = ClassUtil.findFirstAnnotatedEnumValue(enumCls, JsonEnumDefaultValue.class);
74+
return new EnumResolver(enumCls, enumValues, map, defaultEnum);
9575
}
9676

9777
public static EnumResolver constructUsingMethod(Class<Enum<?>> enumCls,
@@ -112,9 +92,8 @@ public static EnumResolver constructUsingMethod(Class<Enum<?>> enumCls,
11292
}
11393
}
11494

115-
Enum<?> defaultValue = determineDefaultEnumValue(enumCls);
116-
117-
return new EnumResolver(enumCls, enumValues, map, defaultValue);
95+
Enum<?> defaultEnum = ClassUtil.findFirstAnnotatedEnumValue(enumCls, JsonEnumDefaultValue.class);
96+
return new EnumResolver(enumCls, enumValues, map, defaultEnum);
11897
}
11998

12099
/**

0 commit comments

Comments
 (0)