package com.elab.spring.componts;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.expression.MapAccessor;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.ParserContext;
import org.springframework.expression.PropertyAccessor;
import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.ReflectivePropertyAccessor;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import java.util.ArrayList;
import java.util.List;

/**
 * 默认的表达式环境
 *
 * @author liukaixiong
 * @Email liukx@elab-plus.com
 * @date 2021/9/27 - 14:57
 */
public class DefaultExpression implements InitializingBean {
    private Logger logger = LoggerFactory.getLogger(getClass());
    private final ExpressionParser PARSER = new SpelExpressionParser();

    private final StandardEvaluationContext standardEvaluationContext = new StandardEvaluationContext();

    private final ParserContext templateParserContext = new TemplateParserContext("${", "}");

    @Override
    public void afterPropertiesSet() throws Exception {
        List<PropertyAccessor> propertyAccessors = new ArrayList<>();
        // 目前仅支持反射的实体的对象和Map结构的对象
        propertyAccessors.add(new ReflectivePropertyAccessor());
        propertyAccessors.add(new MapAccessor());
        standardEvaluationContext.setPropertyAccessors(propertyAccessors);
    }

    /**
     * 根据表达式获取对应的值
     *
     * @param value      匹配对象
     * @param matchValue 表达式对象
     * @param clazz      转换的值
     * @param <T>
     * @return
     */
    public <T> T getValue(Object value, String matchValue, Class<T> clazz) {
        try {
            Expression expression = PARSER.parseExpression(matchValue, templateParserContext);
            return expression.getValue(standardEvaluationContext, value, clazz);
        } catch (Exception e) {
            logger.warn("表达式处理异常 : " + e.getMessage());
        }
        return null;
    }

}
