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

com.github.outerman.be.util.JexlUtil Maven / Gradle / Ivy

There is a newer version: 1.1.22
Show newest version
package com.github.outerman.be.util;

import java.io.StringReader;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.beanutils.BeanMap;
import org.apache.commons.jexl3.JexlBuilder;
import org.apache.commons.jexl3.JexlContext;
import org.apache.commons.jexl3.JexlEngine;
import org.apache.commons.jexl3.JexlException;
import org.apache.commons.jexl3.JexlExpression;
import org.apache.commons.jexl3.MapContext;
import org.apache.commons.jexl3.internal.Debugger;
import org.apache.commons.jexl3.parser.ASTIdentifier;
import org.apache.commons.jexl3.parser.ASTJexlScript;
import org.apache.commons.jexl3.parser.JexlNode;
import org.apache.commons.jexl3.parser.Parser;

import com.github.outerman.be.contant.BusinessEngineException;

/**
 * Java Expression Language Util
 * @author gaoxue
 */
public final class JexlUtil {

    private static JexlEngine jexl = new JexlBuilder().create();

    private static JexlExpression createExpression(String expression) throws BusinessEngineException {
        try {
            JexlExpression jexlExpression = jexl.createExpression(expression);
            return jexlExpression;
        } catch (JexlException ex) {
            throw new BusinessEngineException("", ex.getMessage(), null, ex);
        }
    }

    private static  JexlContext getContext(T data) {
        JexlContext context = new MapContext();
        BeanMap map = new org.apache.commons.beanutils.BeanMap(data);
        for (Entry entry : map.entrySet()) {
            context.set(entry.getKey().toString(), entry.getValue());
        }
        return context;
    }

    /**
     * Return true if the expression is valid
     * @param expression
     * @return true if the expression is valid
     */
    public static boolean isExprValid(String expression) {
        boolean result = true;
        try {
            createExpression(expression);
        } catch (Exception ex) {
            result = false;
        }
        return result;
    }

    /**
     * Evaluate the expression with data
     * @param expression
     * @param data
     * @return
     * @throws BusinessEngineException
     */
    public static  Object evaluate(String expression, T data) throws BusinessEngineException {
        return evaluate(expression, data, null);
    }

    /**
     * Evaluate the expression with data, variables in params
     * @param expression
     * @param data
     * @param params
     * @return
     * @throws BusinessEngineException
     */
    public static  Object evaluate(String expression, T data, Map params) throws BusinessEngineException {
        JexlExpression jexlExpression = createExpression(expression);
        JexlContext context = getContext(data);
        if (params != null) {
            for (Entry param : params.entrySet()) {
                context.set(param.getKey(), param.getValue());
            }
        }
        try {
            Object result = jexlExpression.evaluate(context);
            return result;
        } catch (JexlException ex) {
            throw new BusinessEngineException("", ex.getMessage(), null, ex);
        }
    }

    /**
     * Parse the expression with JEXL, get {@code ASTIdentifier} node name list
     * @param expression
     * @return
     */
    public static List getIdentifierName(String expression) {
        Parser lparser = new Parser(new StringReader(";"));
        ASTJexlScript script = lparser.parse(null, expression, null, false, true);
        List identifierList = getIdentifier(script);
        Set nameSet = new HashSet<>();
        for (ASTIdentifier identifier : identifierList) {
            nameSet.add(identifier.getName());
        }
        return new ArrayList<>(nameSet);
    }

    /**
     * Replace the expression with parsedMap
     * @param expression
     * @param parsedMap
     * @return
     */
    public static String getParsedText(String expression, Map parsedMap) {
        Parser lparser = new Parser(new StringReader(";"));
        ASTJexlScript script = lparser.parse(null, expression, null, false, true);
        List identifierList = JexlUtil.getIdentifier(script);
        for (ASTIdentifier identifier : identifierList) {
            String name = identifier.getName();
            if (!parsedMap.containsKey(name)) {
                continue;
            }
            try {
                Field nameField = identifier.getClass().getDeclaredField("name");
                nameField.setAccessible(true);
                nameField.set(identifier, parsedMap.get(name));
            } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex) {
                // do nothing
            }
        }
        Debugger debug = new Debugger();
        debug.setIndentation(2);
        debug.debug(script);
        String parsedText = debug.toString();
        return parsedText;
    }

    /**
     * Get {@code ASTIdentifier} node list with root {@code node}
     * @param node
     * @return
     */
    private static List getIdentifier(JexlNode node) {
        List result = new ArrayList<>();
        int num = node.jjtGetNumChildren();
        if (num == 0) {
            if (node instanceof ASTIdentifier) {
                result.add((ASTIdentifier) node);
            }
            return result;
        }
        for (int index = 0; index < num; index++) {
            JexlNode child = node.jjtGetChild(index);
            result.addAll(getIdentifier(child));
        }
        return result;
    }

    private JexlUtil() {
        // final util class, avoid instantiate
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy