EnumFormatter.java
- package com.gh.mygreen.xlsmapper.textformatter;
- import java.lang.reflect.Method;
- import java.util.Collections;
- import java.util.EnumSet;
- import java.util.HashMap;
- import java.util.LinkedHashMap;
- import java.util.Map;
- import java.util.Optional;
- import com.gh.mygreen.xlsmapper.util.ArgUtils;
- /**
- * 列挙型のフォーマッタ。
- *
- * @since 2.0
- * @author T.TSUCHIE
- *
- * @param <T> 列挙型
- */
- public class EnumFormatter<T extends Enum<T>> implements TextFormatter<T> {
- private final Class<? extends Enum<?>> type;
- private final boolean ignoreCase;
- private final Optional<Method> aliasMethod;
- /**
- * キーが列挙型、値が文字列のマップ。
- */
- private final Map<Enum<?>, String> toStringMap;
- /**
- * キーが文字列、値が列挙型のマップ
- */
- private final Map<String, Enum<?>> toObjectMap;
- public EnumFormatter(final Class<T> type, final boolean ignoreCase) {
- ArgUtils.notNull(type, "type");
- this.type = type;
- this.ignoreCase = ignoreCase;
- this.aliasMethod = Optional.empty();
- this.toStringMap = createToStringMap(type);
- this.toObjectMap = createToObjectMap(type, ignoreCase);
- }
- public EnumFormatter(final Class<T> type, final boolean ignoreCase, final String alias) {
- ArgUtils.notNull(type, "type");
- ArgUtils.notEmpty(alias, "alias");
- this.type = type;
- this.ignoreCase = ignoreCase;
- this.aliasMethod = Optional.of(getEnumAliasMethod(type, alias));
- this.toStringMap = createToStringMap(type, alias);
- this.toObjectMap = createToObjectMap(type, ignoreCase, alias);
- }
- public EnumFormatter(final Class<T> type) {
- this(type, false);
- }
- public EnumFormatter(final Class<T> type, final String alias) {
- this(type, false, alias);
- }
- private static <T extends Enum<T>> Method getEnumAliasMethod(final Class<T> enumClass, final String alias) {
- try {
- final Method method = enumClass.getMethod(alias);
- method.setAccessible(true);
- return method;
- } catch (ReflectiveOperationException e) {
- throw new IllegalArgumentException(String.format("not found method '%s'", alias), e);
- }
- }
- private static <T extends Enum<T>> Map<Enum<?>, String> createToStringMap(final Class<T> enumClass) {
- final EnumSet<T> set = EnumSet.allOf(enumClass);
- final Map<Enum<?>, String> map = new LinkedHashMap<>();
- for(T e : set) {
- map.put(e, e.name());
- }
- return Collections.unmodifiableMap(map);
- }
- private static <T extends Enum<T>> Map<Enum<?>, String> createToStringMap(final Class<T> enumClass, final String alias) {
- final Method method = getEnumAliasMethod(enumClass, alias);
- final Map<Enum<?>, String> map = new LinkedHashMap<>();
- try {
- final EnumSet<T> set = EnumSet.allOf(enumClass);
- for(T e : set) {
- Object returnValue = method.invoke(e);
- map.put(e, returnValue.toString());
- }
- } catch(ReflectiveOperationException e) {
- throw new RuntimeException("fail get enum value.", e);
- }
- return Collections.unmodifiableMap(map);
- }
- private static <T extends Enum<T>> Map<String, Enum<?>> createToObjectMap(final Class<T> enumClass, final boolean ignoreCase) {
- final EnumSet<T> set = EnumSet.allOf(enumClass);
- final Map<String, Enum<?>> map = new LinkedHashMap<>();
- for(T e : set) {
- final String key = (ignoreCase ? e.name().toLowerCase() : e.name());
- map.put(key, e);
- }
- return Collections.unmodifiableMap(map);
- }
- private static <T extends Enum<T>> Map<String, Enum<?>> createToObjectMap(final Class<T> enumClass, final boolean ignoreCase,
- final String alias) {
- final Method method = getEnumAliasMethod(enumClass, alias);
- final Map<String, Enum<?>> map = new LinkedHashMap<>();
- try {
- EnumSet<T> set = EnumSet.allOf(enumClass);
- for(T e : set) {
- Object returnValue = method.invoke(e);
- final String key = (ignoreCase ? returnValue.toString().toLowerCase() : returnValue.toString());
- map.put(key, e);
- }
- } catch(ReflectiveOperationException e) {
- throw new RuntimeException(e);
- }
- return Collections.unmodifiableMap(map);
- }
- @SuppressWarnings("unchecked")
- @Override
- public T parse(final String text) throws TextParseException {
- final String keyText = ignoreCase ? text.toLowerCase() : text;
- final Optional<T> obj = Optional.ofNullable((T)toObjectMap.get(keyText));
- return obj.orElseThrow(() -> {
- final Map<String, Object> vars = new HashMap<>();
- vars.put("type", getType().getName());
- vars.put("ignoreCase", isIgnoreCase());
- getAliasMethod().ifPresent(method -> vars.put("alias", method.getName()));
- vars.put("enums", getToStringMap().values());
- return new TextParseException(text, type, vars);
- });
- }
- @Override
- public String format(final T value) {
- final Optional<String> text = Optional.ofNullable(toStringMap.get(value));
- return text.orElseGet(() -> value.toString());
- }
- public Class<? extends Enum<?>> getType() {
- return type;
- }
- public boolean isIgnoreCase() {
- return ignoreCase;
- }
- public Optional<Method> getAliasMethod() {
- return aliasMethod;
- }
- public Map<Enum<?>, String> getToStringMap() {
- return toStringMap;
- }
- public Map<String, Enum<?>> getToObjectMap() {
- return toObjectMap;
- }
- }