ExpressUtil.java 8.8 KB
package com.skua.common.util;

import io.netty.util.internal.StringUtil;

import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

/**
 * ExpressUtil(表达式判断工具类)
 */
public class ExpressUtil {

	/**
	 * 根据逻辑表达式推送结果  增加的复杂的取位运算
	 * @param express
	 * @param dataMap
	 * @return
	 * @throws ScriptException
	 */
	public static String getValueByExpress(String express, Map<String, Object> dataMap) throws ScriptException {

		if (dataMap == null)
			return "";
		if (StringUtil.isNullOrEmpty(express))
			return "";
		String result = "";
		int index = express.indexOf("=");// 表达式中有等式的
		int hideIndex = express.indexOf("@hide"); // 表达式中有@hide字符串的,表示有隐藏属性
		// 优先判断是否有隐藏属性
		if (hideIndex > 0) {
			result = "3";
			return result;
		}
		int stringIndex = express.indexOf("@word");// 表达式中有@word字符串的,表示有>=3种以上文字属性进行切换的
		ScriptEngineManager manager = new ScriptEngineManager();
		ScriptEngine engine = manager.getEngineByName("js");
		for (Map.Entry<String, Object> entry : dataMap.entrySet()) {
			engine.put(entry.getKey(), entry.getValue()); // 设置变量名称与采集数据的映射关系
		}
		/** start 增加等式逻辑判断功能,判断等式类型表达式是否成立 修改人:HQW 2016-11-10 */
		// 优先判断带文字属性的点
		if (stringIndex > 0) {
			String tempStr = express.substring(0, index);// 表达式等式中的变量名称
			result = "word" + (String) engine.eval(tempStr); // 获取表达式中的变量名称被设置的具体数值
			return result;
		}
		// 逻辑位判断处理
		int bitIndex = express.indexOf("^");// 判断表达式中是否有^符号,进行二进制转换处理
		if (bitIndex > 0) {
			String tempbit = express.substring(bitIndex + 1);
			int bitNumber = Integer.parseInt(tempbit.split("\\.")[0]) + 1;// 获取表达式中的位数,组态中从0开始为第一位
			String expStr = express.substring(0, bitIndex);
			String decimalSource = (String) engine.eval(expStr);
			result = decimalToBinary(Integer.parseInt(decimalSource.split("\\.")[0]), bitNumber);
			return result;
		}

		// 恒等式逻辑部分进行赋值
		if (index > 0) {
			String tempStr = express.substring(0, index);// 表达式等式中的变量名称
			String valueStr = express.substring(index + 1);// 表达式等式中的数值
			result = engine.eval(tempStr).toString(); // 获取表达式中的变量名称被设置的具体数值
			if (valueStr.equals(result)) {
				result = "1";
			} else {
				result = "0";
			}
		} else {
			result = engine.eval(express).toString();
		}
		// 显示隐藏逻辑部分进行赋值
		/** end */
		result = subZeroAndDot(result);
		return result;

	}

	/**
	 * 根据表达式计算结果,满足复杂逻辑表达式
	 * @Title: getValueByExpress2
	 * @Description: TODO
	 * @param express
	 * @param dataMap
	 * @return
	 * @throws ScriptException
	 * @return: String
	 */
	public static String getValueByExpress2(String express,Map<String,Object> dataMap) throws ScriptException{
		if(dataMap == null) return "";
		if(StringUtil.isNullOrEmpty(express)) return "";
		String result = "";
		//去除首尾的"#"
		if(express.startsWith("#")){
			express = express.substring(1);
		}
		if(express.endsWith("#")){
			express = express.substring(0, express.length()-1);
		}
		//优先判断是否有隐藏属性
		int hideIndex = express.indexOf("@hide"); //表达式中有@hide字符串的,表示有隐藏属性
	    if(hideIndex>0){
	    	result="3";
	    	return result;
	    }
		ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("js");
        String parameters = "";
		for (Map.Entry<String, Object> entry : dataMap.entrySet()) {
			//设置变量名称与采集数据的映射关系,value转换成double便于后续计算
			engine.put(entry.getKey(), Double.parseDouble(entry.getValue().toString()));
			//以字段为参数进行参数拼接
			parameters = parameters + "," + entry.getKey() ;
        }
		//去掉首位的","
		if(parameters.length() > 0){
			parameters = parameters.substring(1);
		}
		//定义函数并调用,将拼接好的参数带入
		String script = "function add("+parameters+"){return "+express+"} add("+parameters+")";
		Object object = engine.eval(script);
		if(object!=null){
			result = object.toString();
			//去掉模拟量中小数点后可能存在的多余0
			result = subZeroAndDot(result);
		}else{
			return "";
		}
		//判断返回是否为真假并赋予对应的值
		if("true".equals(result)){
			result = "1";
		}else if("false".equals(result)){
			result = "0";
		}
		return result;
	}

	/**
	 * 去掉数字字符串中小数点后多余的0
	 * @param s
	 * @return
	 */
	public static String subZeroAndDot(String s){
        if(s.indexOf(".") > 0){
        	//去掉多余的0
            s = s.replaceAll("0+?$", "");
          //如最后一位是.则去掉
            s = s.replaceAll("[.]$", "");
        }
        return s;
    }

	/**
	 * @Title: decimalToBinary
	 * @Description: 进行十进制和2进行数据转换,并获取指定位数数据    获取2进制的位运算方法
	 * @param decimalSource
	 *            待转换10进制数据
	 * @param bitNumber
	 *            需要获取第几位数据
	 * @return
	 * @return: String 返回值非0即1,只有两种状态
	 */
	public static String decimalToBinary(int decimalSource, int bitNumber) {
		BigInteger bi = new BigInteger(String.valueOf(decimalSource)); // 转换成BigInteger类型
		String bitValueS = bi.toString(2);// 参数2指定的是转化成X进制,默认10进制
		int bitLength = bitValueS.length(); // 转换后二进制数据长度
		String bitValue = "0"; // 默认值
		/* 逻辑处理 */
		if (bitLength < bitNumber) {
			bitValue = "0";
		} else {
			int leftIndex = bitLength - bitNumber;
			bitValue = bitValueS.substring(leftIndex, leftIndex + 1);// 获取指定位数,取其中一位
		}
		return bitValue;
	}

	private Map<String,String> getExpressMapByExpressStr2(Map<String, String> mapResult, String express, Map<String, String> dataResult){
		if(dataResult == null){
			dataResult = new HashMap<String,String>();
		}
		if(StringUtil.isNullOrEmpty(express)){
			return null;
		}
		for (Map.Entry<String, String> entry : mapResult.entrySet()) {
			String field = entry.getKey();
			if(express.contains(field)){
				dataResult.put(field, mapResult.get(field));
			}
		}
		return dataResult;
	}

	/**
	 * 通过计算表达式得到数据
	 * @param mapResult 已知的结果集
	 * @param express 表达式
	 * @return 转换后的结果
	 */
	private Map<String,String> getExpressMapByExpressStr(Map<String,String> mapResult , String express,Map<String,String> dataResult){
		if(dataResult == null){
			dataResult = new HashMap<String,String>();
		}
		if(StringUtil.isNullOrEmpty(express)){
			return null;
		}
		Pattern p = Pattern.compile("^*\\|\\||\\||&|&&*$");
		Matcher m = p.matcher(express);
		if (m.find()) {
			//按照特殊字符进行切割
			int index = getIndexBySymbol(express);
			if(index < 1){
				//针对特殊字符重复的时候,需要优先进行2次处理
				return getExpressMapByExpressStr(mapResult , express.substring(1) , dataResult);
			}
			String fieldName = express.substring(0,index);
			fieldName = cleanFieldName(fieldName , "()()");
			dataResult.put(fieldName , mapResult.get(fieldName));
			return getExpressMapByExpressStr(mapResult , express.substring(index) , dataResult);
		}else{
			//清洗字符串中不含有括号时
			String fieldName = cleanFieldName(express , "()()");
			dataResult.put(fieldName , mapResult.get(fieldName));
			return dataResult;
		}
	}

	/**
	 * 根据&或者|进行
	 * @param express
	 * @return
	 */
	private int getIndexBySymbol(String express){
		int index = express.indexOf("&");
		int otherIndex = express.indexOf("|");
		if(index > otherIndex){
			return otherIndex;
		}
		return index;

	}

	/**
	 * 清洗字段名称-将左右括号进行清洗掉
	 * @param fieldName 字段名称
	 * @return 已清洗后的字段名称
	 */
	private String cleanFieldName(String fieldName , String replaceStr){
		if(StringUtil.isNullOrEmpty(fieldName)){
			return "";
		}else{
			fieldName = fieldName.replaceAll("["+replaceStr+"]", "");
			/**satar 增加等式类型表达式处理逻辑,取出等式中的字段名称 修改人:HQW 2016-11-10*/
			int index = fieldName.indexOf("=");
			if(index>0){
				fieldName = fieldName.substring(0, index);
			}
			if(fieldName.contains("^")) {
				fieldName=fieldName.substring(0, fieldName.indexOf("^"));
			}
			/**end */
			return fieldName;
		}
	}

}