|
@@ -5,6 +5,7 @@ import java.io.Serializable;
|
|
|
import java.lang.reflect.Constructor;
|
|
|
import java.lang.reflect.Field;
|
|
|
import java.lang.reflect.Modifier;
|
|
|
+import java.util.Collections;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
import java.util.Objects;
|
|
@@ -74,12 +75,12 @@ public abstract class Enumeration implements Serializable {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 枚举对象/值列表映射表
|
|
|
+ * 枚举对象/编码/排序/是否动态映射表
|
|
|
*/
|
|
|
- private static final Map<Class<?>, List<Pair<String, Boolean>>> VALUES = Maps.newConcurrentMap();
|
|
|
+ private static final Map<Class<?>, List<BiPair<String, Integer, Boolean>>> VALUES = Maps.newConcurrentMap();
|
|
|
|
|
|
/**
|
|
|
- * 枚举对象/值/实例映射表
|
|
|
+ * 枚举对象/编码/实例映射表
|
|
|
*/
|
|
|
private static final Map<Class<?>, Map<String, Enumeration>> INSTANCES = Maps.newConcurrentMap();
|
|
|
|
|
@@ -88,6 +89,11 @@ public abstract class Enumeration implements Serializable {
|
|
|
*/
|
|
|
private final String code;
|
|
|
|
|
|
+ /**
|
|
|
+ * 排序数字
|
|
|
+ */
|
|
|
+ private final int ordinal;
|
|
|
+
|
|
|
/**
|
|
|
* 是否动态
|
|
|
*/
|
|
@@ -99,52 +105,55 @@ public abstract class Enumeration implements Serializable {
|
|
|
private final String description;
|
|
|
|
|
|
protected Enumeration() {
|
|
|
- this(null);
|
|
|
+ this(null, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ protected Enumeration(Integer ordinal) {
|
|
|
+ this(ordinal, null);
|
|
|
}
|
|
|
|
|
|
protected Enumeration(String description) {
|
|
|
+ this(null, description);
|
|
|
+ }
|
|
|
+
|
|
|
+ protected Enumeration(Integer ordinal, String description) {
|
|
|
Class<?> clazz = this.getClass();
|
|
|
synchronized (clazz.getName().intern()) {
|
|
|
- List<Pair<String, Boolean>> values = VALUES.get(clazz);
|
|
|
+ List<BiPair<String, Integer, Boolean>> values = VALUES.get(clazz);
|
|
|
if (ObjectUtils.isEmpty(values) && INSTANCES.containsKey(clazz)) {
|
|
|
throw new IllegalStateException("Invalid enumeration instance");
|
|
|
} else if (ObjectUtils.isEmpty(values)) {
|
|
|
values = VALUES.computeIfAbsent(clazz, Enumeration::getValues);
|
|
|
}
|
|
|
- Pair<String, Boolean> pair = values.remove(0);
|
|
|
- this.code = Objects.requireNonNull(pair.getKey());
|
|
|
- this.dynamic = Boolean.TRUE.equals(pair.getValue());
|
|
|
+ BiPair<String, Integer, Boolean> pair = values.remove(0);
|
|
|
+ this.code = Objects.requireNonNull(pair.getLeft());
|
|
|
+ this.ordinal = ObjectUtils.ifNull(ordinal, pair::getMiddle);
|
|
|
+ this.dynamic = Boolean.TRUE.equals(pair.getRight());
|
|
|
if (ObjectUtils.isEmpty(values)) {
|
|
|
VALUES.remove(clazz);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 设置枚举描述信息
|
|
|
this.description = ObjectUtils.ifNull(description, this.code);
|
|
|
-
|
|
|
- // 保存枚举值/实例映射
|
|
|
INSTANCES.computeIfAbsent(clazz, k -> Maps.newConcurrentMap()).putIfAbsent(this.code, this);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 获取枚举值
|
|
|
+ * 获取枚举值,需要返回一个可更新列表
|
|
|
*
|
|
|
* @param clazz 枚举对象
|
|
|
- * @return 枚举值/是否动态信息列表
|
|
|
+ * @return 枚举编码/排序/是否动态信息列表
|
|
|
*/
|
|
|
- private static List<Pair<String, Boolean>> getValues(Class<?> clazz) {
|
|
|
- Field[] fields = clazz.getDeclaredFields();
|
|
|
- List<Pair<String, Boolean>> values = Lists.newLinkedList();
|
|
|
+ private static List<BiPair<String, Integer, Boolean>> getValues(Class<?> clazz) {
|
|
|
+ Field[] fields = clazz.getFields();
|
|
|
+ List<BiPair<String, Integer, Boolean>> values = Lists.newLinkedList();
|
|
|
if (ObjectUtils.notEmpty(fields)) {
|
|
|
for (Field field : fields) {
|
|
|
Class<?> type = field.getType();
|
|
|
- if (type.isAssignableFrom(clazz) || clazz.isAssignableFrom(type)) {
|
|
|
- int modifiers = field.getModifiers();
|
|
|
- if (!(type == clazz && Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers)
|
|
|
- && Modifier.isFinal(modifiers))) {
|
|
|
- throw new IllegalStateException("Invalid enumeration field: " + field);
|
|
|
- }
|
|
|
- values.add(Pair.of(field.getName(), false));
|
|
|
+ int modifiers = field.getModifiers();
|
|
|
+ if (type == clazz && Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers)
|
|
|
+ && Modifier.isFinal(modifiers)) {
|
|
|
+ values.add(BiPair.of(field.getName(), values.size(), false));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -172,36 +181,26 @@ public abstract class Enumeration implements Serializable {
|
|
|
synchronized (type.getName().intern()) {
|
|
|
if ((instances = INSTANCES.get(type)) == null) {
|
|
|
// 枚举字段尚未初始化
|
|
|
- List<Pair<String, Boolean>> values = VALUES.computeIfAbsent(type, Enumeration::getValues);
|
|
|
- dynamic = values.stream().noneMatch(pair -> Objects.equals(pair.getKey(), value));
|
|
|
- values.add(Pair.of(value, dynamic));
|
|
|
+ List<BiPair<String, Integer, Boolean>> values =
|
|
|
+ VALUES.computeIfAbsent(type, Enumeration::getValues);
|
|
|
+ BiPair<String, Integer, Boolean> found =
|
|
|
+ values.stream().filter(p -> Objects.equals(p.getLeft(), value)).findAny().orElse(null);
|
|
|
+ int ordinal = (dynamic = Objects.isNull(found)) ? 0 : found.getMiddle();
|
|
|
+ values.add(BiPair.of(value, ordinal, dynamic));
|
|
|
} else if ((instance = instances.get(value)) == null) {
|
|
|
// 枚举字段已经初始化
|
|
|
- VALUES.put(type, Lists.newArrayList(Pair.of(value, dynamic = true)));
|
|
|
+ VALUES.put(type, Lists.newArrayList(BiPair.of(value, 0, dynamic = true)));
|
|
|
} else {
|
|
|
return (T) instance;
|
|
|
}
|
|
|
|
|
|
- // 优先使用无参构造函数初始化枚举实例,如果函数不存在则使用枚举描述构造函数
|
|
|
- Constructor<T> constructor;
|
|
|
+ // 使用无参构造方法初始化枚举实例
|
|
|
try {
|
|
|
- constructor = type.getDeclaredConstructor();
|
|
|
- } catch (NoSuchMethodException e) {
|
|
|
- try {
|
|
|
- constructor = type.getDeclaredConstructor(String.class);
|
|
|
- } catch (NoSuchMethodException ignore) {
|
|
|
- throw new RuntimeException(e);
|
|
|
- }
|
|
|
- }
|
|
|
- if (!constructor.isAccessible()) {
|
|
|
- constructor.setAccessible(true);
|
|
|
- }
|
|
|
- try {
|
|
|
- if (constructor.getParameterCount() > 0) {
|
|
|
- instance = constructor.newInstance(value);
|
|
|
- } else {
|
|
|
- instance = constructor.newInstance();
|
|
|
+ Constructor<T> constructor = type.getDeclaredConstructor();
|
|
|
+ if (!constructor.isAccessible()) {
|
|
|
+ constructor.setAccessible(true);
|
|
|
}
|
|
|
+ instance = constructor.newInstance();
|
|
|
} catch (ReflectiveOperationException e) {
|
|
|
throw new RuntimeException(e);
|
|
|
}
|
|
@@ -215,6 +214,29 @@ public abstract class Enumeration implements Serializable {
|
|
|
return (T) instance;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 获取枚举实例
|
|
|
+ *
|
|
|
+ * @param type 枚举类型
|
|
|
+ * @param <T> 对象类型
|
|
|
+ * @return 枚举编码/实例映射表
|
|
|
+ */
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ public static <T extends Enumeration> Map<String, T> getInstances(@NonNull Class<T> type) {
|
|
|
+ Map<String, T> instances = (Map<String, T>) INSTANCES.get(type);
|
|
|
+ if (instances == null) {
|
|
|
+ synchronized (type.getName().intern()) {
|
|
|
+ if ((instances = (Map<String, T>) INSTANCES.get(type)) == null) {
|
|
|
+ // 临时设置一个无效枚举实例,待枚举对象实例初始化完成后移除
|
|
|
+ parse(type, StringUtils.SPACE);
|
|
|
+ instances = (Map<String, T>) INSTANCES.get(type);
|
|
|
+ instances.remove(StringUtils.SPACE);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return Collections.unmodifiableMap(instances);
|
|
|
+ }
|
|
|
+
|
|
|
@Override
|
|
|
public int hashCode() {
|
|
|
return this.code.hashCode();
|