|
|
@@ -1,7 +1,8 @@
|
|
|
package cn.hutool.core.convert.impl;
|
|
|
|
|
|
import cn.hutool.core.convert.AbstractConverter;
|
|
|
-import cn.hutool.core.convert.EnumItem;
|
|
|
+import cn.hutool.core.lang.EnumItem;
|
|
|
+import cn.hutool.core.lang.SimpleCache;
|
|
|
import cn.hutool.core.map.MapUtil;
|
|
|
import cn.hutool.core.util.ClassUtil;
|
|
|
import cn.hutool.core.util.EnumUtil;
|
|
|
@@ -11,7 +12,6 @@ import cn.hutool.core.util.ReflectUtil;
|
|
|
import java.lang.reflect.Method;
|
|
|
import java.util.Arrays;
|
|
|
import java.util.Map;
|
|
|
-import java.util.concurrent.ConcurrentHashMap;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
/**
|
|
|
@@ -24,7 +24,7 @@ import java.util.stream.Collectors;
|
|
|
public class EnumConverter extends AbstractConverter<Object> {
|
|
|
private static final long serialVersionUID = 1L;
|
|
|
|
|
|
- private static final Map<Class<?>, Map<Class<?>, Method>> VALUE_OF_METHOD_CACHE = new ConcurrentHashMap<>();
|
|
|
+ private static final SimpleCache<Class<?>, Map<Class<?>, Method>> VALUE_OF_METHOD_CACHE = new SimpleCache<>();
|
|
|
|
|
|
private final Class enumClass;
|
|
|
|
|
|
@@ -40,7 +40,7 @@ public class EnumConverter extends AbstractConverter<Object> {
|
|
|
@Override
|
|
|
protected Object convertInternal(Object value) {
|
|
|
Enum enumValue = tryConvertEnum(value, this.enumClass);
|
|
|
- if(null == enumValue && false == value instanceof String){
|
|
|
+ if (null == enumValue && false == value instanceof String) {
|
|
|
// 最后尝试valueOf转换
|
|
|
enumValue = Enum.valueOf(this.enumClass, convertToStr(value));
|
|
|
}
|
|
|
@@ -56,34 +56,41 @@ public class EnumConverter extends AbstractConverter<Object> {
|
|
|
* 尝试找到类似转换的静态方法调用实现转换且优先使用<br>
|
|
|
* 约定枚举类应该提供 valueOf(String) 和 valueOf(Integer)用于转换
|
|
|
* oriInt /name 转换托底
|
|
|
- *
|
|
|
+ *
|
|
|
* @param value 被转换的值
|
|
|
* @param enumClass enum类
|
|
|
* @return 对应的枚举值
|
|
|
*/
|
|
|
protected static Enum tryConvertEnum(Object value, Class enumClass) {
|
|
|
- if(value==null) {
|
|
|
+ if (value == null) {
|
|
|
return null;
|
|
|
}
|
|
|
+
|
|
|
+ // EnumItem实现转换
|
|
|
Enum enumResult = null;
|
|
|
- if(EnumItem.class.isAssignableFrom(enumClass)) {
|
|
|
- EnumItem first = (EnumItem) EnumUtil.getEnumAt(enumClass, 0);
|
|
|
- if(value instanceof Integer) {
|
|
|
- return (Enum) first.fromInt((Integer) value);
|
|
|
- }else if(value instanceof String){
|
|
|
- return (Enum) first.fromStr( value.toString());
|
|
|
+ if (EnumItem.class.isAssignableFrom(enumClass)) {
|
|
|
+ final EnumItem first = (EnumItem) EnumUtil.getEnumAt(enumClass, 0);
|
|
|
+ if(null != first){
|
|
|
+ if (value instanceof Integer) {
|
|
|
+ return (Enum) first.fromInt((Integer) value);
|
|
|
+ } else if (value instanceof String) {
|
|
|
+ return (Enum) first.fromStr(value.toString());
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
- // 用户自定义方法优先,
|
|
|
- final Map<Class<?>, Method> valueOfMethods = getValueOfMethods(enumClass);
|
|
|
- if (MapUtil.isNotEmpty(valueOfMethods)) {
|
|
|
+
|
|
|
+ // 用户自定义方法
|
|
|
+ // 查找枚举中所有返回值为目标枚举对象的方法,如果发现方法参数匹配,就执行之
|
|
|
+ final Map<Class<?>, Method> methodMap = getMethodMap(enumClass);
|
|
|
+ if (MapUtil.isNotEmpty(methodMap)) {
|
|
|
final Class<?> valueClass = value.getClass();
|
|
|
- for (Map.Entry<Class<?>, Method> entry : valueOfMethods.entrySet()) {
|
|
|
+ for (Map.Entry<Class<?>, Method> entry : methodMap.entrySet()) {
|
|
|
if (ClassUtil.isAssignable(entry.getKey(), valueClass)) {
|
|
|
enumResult = ReflectUtil.invokeStatic(entry.getValue(), value);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
//oriInt 应该滞后使用 以 GB/T 2261.1-2003 性别编码为例,对应整数并非连续数字会导致数字转枚举时失败
|
|
|
//0 - 未知的性别
|
|
|
//1 - 男性
|
|
|
@@ -91,9 +98,9 @@ public class EnumConverter extends AbstractConverter<Object> {
|
|
|
//5 - 女性改(变)为男性
|
|
|
//6 - 男性改(变)为女性
|
|
|
//9 - 未说明的性别
|
|
|
- if(null == enumResult){
|
|
|
+ if (null == enumResult) {
|
|
|
if (value instanceof Integer) {
|
|
|
- enumResult = EnumUtil.getEnumAt(enumClass, (Integer)value);
|
|
|
+ enumResult = EnumUtil.getEnumAt(enumClass, (Integer) value);
|
|
|
} else if (value instanceof String) {
|
|
|
try {
|
|
|
enumResult = Enum.valueOf(enumClass, (String) value);
|
|
|
@@ -109,19 +116,14 @@ public class EnumConverter extends AbstractConverter<Object> {
|
|
|
* 获取用于转换为enum的所有static方法
|
|
|
*
|
|
|
* @param enumClass 枚举类
|
|
|
- * @return 转换方法map
|
|
|
+ * @return 转换方法map,key为方法参数类型,value为方法
|
|
|
*/
|
|
|
- private static Map<Class<?>, Method> getValueOfMethods(Class<?> enumClass) {
|
|
|
- Map<Class<?>, Method> valueOfMethods = VALUE_OF_METHOD_CACHE.get(enumClass);
|
|
|
- if (null == valueOfMethods) {
|
|
|
- valueOfMethods = Arrays.stream(enumClass.getMethods())
|
|
|
- .filter(ModifierUtil::isStatic)
|
|
|
- .filter(m -> m.getReturnType() == enumClass)
|
|
|
- .filter(m -> m.getParameterCount() == 1)
|
|
|
- .filter(m -> false == "valueOf".equals(m.getName()))
|
|
|
- .collect(Collectors.toMap(m -> m.getParameterTypes()[0], m -> m, (existing, replacement) -> existing));
|
|
|
- VALUE_OF_METHOD_CACHE.put(enumClass, valueOfMethods);
|
|
|
- }
|
|
|
- return valueOfMethods;
|
|
|
+ private static Map<Class<?>, Method> getMethodMap(Class<?> enumClass) {
|
|
|
+ return VALUE_OF_METHOD_CACHE.get(enumClass, ()-> Arrays.stream(enumClass.getMethods())
|
|
|
+ .filter(ModifierUtil::isStatic)
|
|
|
+ .filter(m -> m.getReturnType() == enumClass)
|
|
|
+ .filter(m -> m.getParameterCount() == 1)
|
|
|
+ .filter(m -> false == "valueOf".equals(m.getName()))
|
|
|
+ .collect(Collectors.toMap(m -> m.getParameterTypes()[0], m -> m)));
|
|
|
}
|
|
|
}
|