All Downloads are FREE. Search and download functionalities are using the official Maven repository.

spring.turbo.format.StringToEnumConverterFactory Maven / Gradle / Ivy

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *    ____             _            _____           _
 *   / ___| _ __  _ __(_)_ __   __ |_   _|   _ _ __| |__   ___
 *   \___ \| '_ \| '__| | '_ \ / _` || || | | | '__| '_ \ / _ \
 *    ___) | |_) | |  | | | | | (_| || || |_| | |  | |_) | (_) |
 *   |____/| .__/|_|  |_|_| |_|\__, ||_| \__,_|_|  |_.__/ \___/
 *         |_|                 |___/   https://github.com/yingzhuo/spring-turbo
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package spring.turbo.format;

import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.ConverterFactory;
import org.springframework.lang.Nullable;
import spring.turbo.util.Asserts;
import spring.turbo.util.StringPool;
import spring.turbo.util.StringUtils;
import spring.turbo.util.reflection.MethodUtils;

import java.lang.reflect.Method;
import java.util.List;
import java.util.stream.Collectors;

import static spring.turbo.util.reflection.MethodPredicateFactories.*;

/**
 * 替代Spring原厂的 String -> Enum转换器
 *
 * @author 应卓
 * @see EnumConvertingMethod
 * @since 1.2.1
 */
@SuppressWarnings({"rawtypes", "unchecked"})
public class StringToEnumConverterFactory implements ConverterFactory {

    /**
     * 构造方法
     */
    public StringToEnumConverterFactory() {
        super();
    }

    @Override
    public  Converter getConverter(Class targetType) {
        return new StringToEnumConverter(getEnumType(targetType));
    }

    private Class getEnumType(Class targetType) {
        Class enumType = targetType;
        while (enumType != null && !enumType.isEnum()) {
            enumType = enumType.getSuperclass();
        }
        Asserts.notNull(enumType, () -> "The target type " + targetType.getName() + " does not refer to an enum");
        return enumType;
    }

    private static class StringToEnumConverter implements Converter {

        private final Class enumType;

        private StringToEnumConverter(Class enumType) {
            this.enumType = enumType;
        }

        @Nullable
        @Override
        public T convert(String source) {

            final String oriSource = source;

            if (StringUtils.isBlank(source)) {
                return null;
            }

            source = source
                    .replaceAll(StringPool.HYPHEN, StringPool.UNDERSCORE)
                    .trim();

            try {
                // 一般性尝试
                return (T) Enum.valueOf(this.enumType, source);
            } catch (Exception e) {
                // 尝试转成大写再试一次。
                source = source.toUpperCase();
                try {
                    return (T) Enum.valueOf(this.enumType, source);
                } catch (Exception ex) {
                    // 都不行的话动用反射
                    T ret = convertViaReflection(oriSource);
                    if (ret != null) {
                        return ret;
                    } else {
                        throw ex;
                    }
                }
            }
        }

        @Nullable
        private T convertViaReflection(String source) {

            final Method method = this.findConvertingMethod();
            if (method == null) {
                return null;
            }

            // 反射调用方法
            try {
                return (T) method.invoke(null, source);
            } catch (Throwable e) {
                return null;
            }
        }

        @Nullable
        private Method findConvertingMethod() {
            List ret = MethodUtils.find(enumType);
            ret = ret.stream().filter(
                    all(
                            isUserDeclaredMethod(),
                            isPublic(),
                            isStatic(),
                            withAnnotation(EnumConvertingMethod.class)
                    )
            ).collect(Collectors.toList());

            // 找到多个形同没有找到
            if (ret.size() != 1) {
                return null;
            }

            return ret.get(0);
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy