001package cn.sticki.validator.spel.parse;
002
003import cn.sticki.validator.spel.exception.SpelParserException;
004import lombok.extern.slf4j.Slf4j;
005import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
006import org.springframework.context.ApplicationContext;
007import org.springframework.context.expression.BeanFactoryResolver;
008import org.springframework.expression.spel.standard.SpelExpressionParser;
009import org.springframework.expression.spel.support.StandardEvaluationContext;
010
011/**
012 * Spel表达式解析工具
013 *
014 * @author 阿杆
015 * @version 1.0
016 * @since 2024/4/29
017 */
018@SuppressWarnings("AlibabaConstantFieldShouldBeUpperCase")
019@Slf4j
020public class SpelParser {
021
022        private static final SpelExpressionParser parser = new SpelExpressionParser();
023
024        private static final StandardEvaluationContext context = new StandardEvaluationContext();
025
026        static {
027                ApplicationContext applicationContext = SpelValidatorBeanRegistrar.getApplicationContext();
028                if (applicationContext != null) {
029                        AutowireCapableBeanFactory beanFactory = applicationContext.getAutowireCapableBeanFactory();
030                        context.setBeanResolver(new BeanFactoryResolver(beanFactory));
031                } else {
032                        log.warn("ApplicationContext is null, SpelParser will not support spring bean reference");
033                        log.warn("If you want to use spring bean reference in SpelParser, please use @EnableSpelValidatorBeanRegistrar to enable ApplicationContext support");
034                }
035        }
036
037        /**
038         * 解析表达式
039         *
040         * @param expression 表达式
041         * @param rootObject 用于计算表达式的根对象
042         * @return 表达式计算结果
043         */
044        public static Object parse(String expression, Object rootObject) {
045                try {
046                        Object value = parser.parseExpression(expression).getValue(context, rootObject, Object.class);
047                        log.debug("======> Parse expression: [{}], result: [{}]", expression, value);
048                        return value;
049                } catch (Exception e) {
050                        log.error("Parse expression error, expression: [{}], message: [{}]", expression, e.getMessage());
051                        throw new SpelParserException(e);
052                }
053        }
054
055        /**
056         * 解析表达式
057         *
058         * @param expression        表达式
059         * @param rootObject        用于计算表达式的根对象
060         * @param desiredResultType 指定返回值的类型
061         * @return 表达式计算结果
062         * @throws SpelParserException 当表达式计算结果为null或者不是指定类型时抛出
063         */
064        public static <T> T parse(String expression, Object rootObject, Class<T> desiredResultType) {
065                Object any = parse(expression, rootObject);
066                if (any == null) {
067                        throw new SpelParserException("Expression [" + expression + "] calculate result can not be null");
068                }
069                if (!desiredResultType.isInstance(any)) {
070                        throw new SpelParserException("Expression [" + expression + "] calculate result must be [" + desiredResultType.getName() + "]");
071                }
072                return desiredResultType.cast(any);
073        }
074
075}