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

com.gitee.qdbp.staticize.utils.OgnlUtils Maven / Gradle / Ivy

There is a newer version: 3.5.18
Show newest version
package com.gitee.qdbp.staticize.utils;

import java.util.HashMap;
import java.util.Map;
import com.gitee.qdbp.able.model.reusable.ExpressionExecutor;
import com.gitee.qdbp.able.model.reusable.ExpressionMap;
import com.gitee.qdbp.staticize.exception.TagException;
import com.gitee.qdbp.tools.utils.JsonTools;
import com.gitee.qdbp.tools.utils.StringTools;
import ognl.ExpressionSyntaxException;
import ognl.InappropriateExpressionException;
import ognl.MethodFailedException;
import ognl.NoSuchPropertyException;
import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;

/**
 * OGNL工具类, copy from qdbp-tools.jar OgnlTools
 *
 * @author zhaohuihua
 * @version 20200531
 */
public class OgnlUtils {

    /** 静态工具类私有构造方法 **/
    private OgnlUtils() {
    }

    /**
     * 计算Ognl表达式的值
     *
     * @param expression 表达式
     * @return 计算结果
     * @throws TagException 表达式语法错误, 表达式取值错误
     */
    public static Object evaluate(String expression) throws TagException {
        return doEvaluate(expression, RESULT_SCALE, CALC_SCALE, null);
    }

    /**
     * 计算Ognl表达式的值
     *
     * @param expression 表达式
     * @param root 变量根容器
     * @return 计算结果
     * @throws TagException 表达式语法错误, 表达式取值错误
     */
    public static Object evaluate(String expression, Object root) throws TagException {
        return doEvaluate(expression, RESULT_SCALE, CALC_SCALE, root);
    }

    /**
     * 计算Ognl表达式的值
     *
     * @param expression 表达式
     * @param scale 结果保留几位小数 (只在结果是数字时生效)
     * @param root 变量根容器
     * @return 计算结果
     * @throws TagException 表达式语法错误, 表达式取值错误
     */
    public static Object evaluate(String expression, int scale, Object root) throws TagException {
        return doEvaluate(expression, scale, CALC_SCALE, root);
    }

    /**
     * 计算Ognl表达式的值
     *
     * @param expression 表达式
     * @param resultScale 结果保留几位小数 (只在结果是数字时生效)
     * @param calcScale 计算过程中的数字保留几位小数
     * @param root 变量根容器
     * @return 计算结果
     * @throws TagException 表达式语法错误, 表达式取值错误
     */
    public static Object evaluate(String expression, int resultScale, int calcScale, Object root)
            throws TagException {
        return doEvaluate(expression, resultScale, calcScale, root);
    }

    /**
     * 计算Ognl表达式的值
     *
     * @param expression 表达式
     * @param useBigDecimal 是否转换为BigDecimal以解决浮点数计算精度的问题
     * @param root 变量根容器
     * @return 计算结果
     * @throws TagException 表达式语法错误, 表达式取值错误
     */
    public static Object evaluate(String expression, boolean useBigDecimal, Object root) throws TagException {
        return doEvaluate(expression, null, useBigDecimal ? CALC_SCALE : null, root);
    }

    static final Integer RESULT_SCALE = null;
    static final Integer CALC_SCALE = 18;

    /**
     * 计算Ognl表达式的值
     *
     * @param expression 表达式
     * @param resultScale 结果保留几位小数 (只在结果是数字时生效)
     * @param calcScale 计算过程中的数字保留几位小数
     * @param root 变量根容器
     * @return 计算结果
     * @throws TagException 表达式语法错误, 表达式取值错误
     */
    static Object doEvaluate(String expression, Integer resultScale, Integer calcScale, Object root)
            throws TagException {
        if (expression == null || expression.trim().length() == 0) {
            throw new TagException("ExpressionCanNotBeEmpty");
        }

        Object vars = root;
        if (root != null && calcScale != null && !(root instanceof ExpressionMap)) {
            Map json = JsonTools.beanToMap(root);
            ExpressionMap map = new ExpressionMap();
            map.setDecimalCalcScale(calcScale);
            map.putAll(json);
            vars = map;
        }

        OgnlContext context = new OgnlContext(null, null, OgnlMemberAccess.ALLOW_ALL_ACCESS);
        try {
            Object result = Ognl.getValue(expression, context, vars);
            return ExpressionExecutor.trySetDecimalScale(result, resultScale);
        } catch (ExpressionSyntaxException e) {
            throw new TagException("ExpressionSyntaxException: " + expression, e);
        } catch (MethodFailedException e) {
            throw new TagException("MethodFailedException: " + expression, e);
        } catch (InappropriateExpressionException e) {
            // 不以属性引用结尾的表达式传递给setValue时将触发该异常
            throw new TagException("InappropriateExpressionException: " + expression, e);
        } catch (NoSuchPropertyException e) {
            // 表达式指定的属性不存在, 不需要报错, 以方便页面取值, 不需要空值判断
            return null;
        } catch (OgnlException e) {
            // source is null for getProperty(null, "fieldName")
            // 取Ognl表达式出错, 不需要报错, 以方便页面取值, 不需要空值判断
            return null;
        } catch (Exception e) {
            throw new TagException("UnknownException: " + expression, e);
        }
    }

    /**
     * 从容器中获取Ognl表达式的值
     *
     * @param root 根容器
     * @param fields 字段名
     * @return 字段值
     * @throws TagException 表达式语法错误, 表达式取值错误
     */
    public static Object getValue(Object root, String fields) throws TagException {
        return evaluate(fields, false, root);
    }

    /**
     * 根据Ognl表达式向容器中设置值
     *
     * @param root 变量根容器
     * @param fields 字段名
     * @param value 字段值
     * @throws TagException 表达式语法错误, 表达式指定的属性不存在
     */
    public static void setValue(Object root, String fields, Object value) throws TagException {
        if (fields == null || fields.trim().length() == 0) {
            throw new TagException("ExpressionCanNotBeEmpty");
        }

        // 检查需要设置的key的上级是否存在, 如果不存在则设置为空map
        checkParentFieldInMap(root, fields);

        OgnlContext context = new OgnlContext(null, null, OgnlMemberAccess.ALLOW_ALL_ACCESS);
        try {
            Ognl.setValue(fields, context, root, value);
        } catch (ExpressionSyntaxException e) {
            throw new TagException("ExpressionSyntaxException: " + fields, e);
        } catch (MethodFailedException e) {
            throw new TagException("MethodFailedException: " + fields, e);
        } catch (NoSuchPropertyException e) {
            throw new TagException("NoSuchPropertyException: " + fields, e);
        } catch (InappropriateExpressionException e) {
            // 不以属性引用结尾的表达式传递给setValue时将触发该异常
            throw new TagException("InappropriateExpressionException: " + fields, e);
        } catch (OgnlException e) {
            throw new TagException("UnknownException: " + fields, e);
        } catch (Exception e) {
            throw new TagException("UnknownException: " + fields, e);
        }
    }

    // 为了能直接在map中通过多级key设置value
    // 先检查需要设置的key的上级是否存在, 如果不存在则设置为空map
    // 如setValue(map, "userBean.address.details", "Beijing China")
    // 如果userBean和address不存在就会报错
    private static void checkParentFieldInMap(Object root, String fields) {
        if (root instanceof Map && fields.indexOf('.') > 0) {
            String[] fieldNames = StringTools.split(fields, '.');
            @SuppressWarnings("unchecked")
            Map parent = (Map) root;
            for (int i = 0; i < fieldNames.length - 1; i++) {
                String fieldName = fieldNames[i];
                if (!StringTools.isWordString(fieldName)) {
                    break; // 如果不是字段名, 则退出, 如: address[0], getAddress()
                }
                Object fieldValue = parent.get(fieldName);
                if (fieldValue == null) {
                    Map map = new HashMap<>();
                    parent.put(fieldName, map);
                    parent = map;
                } else if (fieldValue instanceof Map) {
                    @SuppressWarnings("unchecked")
                    Map map = (Map) fieldValue;
                    parent = map;
                } else {
                    break;
                }
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy