package com.chinamobile.scm.project.util;
import com.chinamobile.scm.project.dto.ButtonRuleDto;
import com.chinamobile.scm.project.manual.mapper.PurchaseWorkbenchQueryReturnDto;
import com.google.common.collect.Maps;
import org.springframework.cglib.beans.BeanMap;
import javax.script.Bindings;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.util.*;
/**
* 脚本规则引擎 杨航 [email protected]
*/
public class RuleUtil {
/**
* 按钮规则列表
*/
public static List buttonDisplayRules=new ArrayList<>();
public static final String argfront="var jsresult=";
private static ScriptEngine javaScriptEngine;
static {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine scriptEngine = manager.getEngineByName("js");
if (scriptEngine == null) {
throw new RuntimeException("获取脚本解析引擎失败");
}
javaScriptEngine = scriptEngine;
}
public static Object execute(String script) throws ScriptException {
return javaScriptEngine.eval(script);
}
public static Object executeForAttribute(String script, String attributeName) throws ScriptException {
javaScriptEngine.eval(script);
return javaScriptEngine.getContext().getAttribute(attributeName);
}
public static Object executeForFirstAttribute(String script) throws ScriptException {
//这里重新获取一个JavaScript解析引擎是为了避免代码中有其他调用工具类的地方的变量干扰
//重新获取后,这个JavaScript解析引擎只执行了这次传入的代码,不会保存其他地方的变量
//全局的解析器中会保存最大200个变量,JavaScript解析引擎本身最大保存100个变量
// ScriptEngineManager manager = new ScriptEngineManager();
// ScriptEngine scriptEngine = manager.getEngineByName("js");
// if (scriptEngine == null) {
// throw new RuntimeException("获取脚本解析引擎失败");
// }
javaScriptEngine.eval(script);
ScriptContext context = javaScriptEngine.getContext();
if (context == null) {
return null;
}
Bindings bindings = context.getBindings(ScriptContext.ENGINE_SCOPE);
if (bindings == null) {
return null;
}
Set> entrySet = bindings.entrySet();
if (entrySet == null || entrySet.isEmpty()) {
return null;
}
for (Map.Entry entry : entrySet) {
if (entry.getValue() != null) {
return entry.getValue();
}
}
return null;
}
public static boolean isDisplay(String rule, Object bean) throws ScriptException
{
Map args= beanToMap( bean);
if(args!=null&&args.size()>0) {
for (Map.Entry entry : args.entrySet()) {
String mapKey = entry.getKey();
Object param = entry.getValue();
String s = "";
if (param instanceof Integer) {
int value = ((Integer) param).intValue();
s = String.valueOf(value);
rule = rule.replace(mapKey, s);
} else if (param instanceof String) {
s = (String) param;
rule = rule.replace(mapKey, "'" + s + "'");
} else if (param instanceof Double) {
double d = ((Double) param).doubleValue();
s = String.valueOf(d);
rule = rule.replace(mapKey, s);
} else if (param instanceof Float) {
float f = ((Float) param).floatValue();
s = String.valueOf(f);
rule = rule.replace(mapKey, s);
} else if (param instanceof Long) {
long l = ((Long) param).longValue();
s = String.valueOf(l);
rule = rule.replace(mapKey, s);
} else if (param instanceof Boolean) {
boolean b = ((Boolean) param).booleanValue();
s = String.valueOf(b);
rule = rule.replace(mapKey, s);
} else if (param instanceof Date) {
Date d = (Date) param;
s = String.valueOf(d);
rule = rule.replace(mapKey, s);
}
// System.out.println(mapKey + ":" + rule);
}
}
boolean testExecuteForFirstAttribute = (boolean)executeForFirstAttribute(argfront+rule);
return testExecuteForFirstAttribute;
}
/**
* 将对象装换为map
*
* @param bean
* @return
*/
private static Map beanToMap(T bean) {
Map map = Maps.newHashMap();
if (bean != null) {
BeanMap beanMap = BeanMap.create(bean);
for (Object key : beanMap.keySet()) {
map.put(key + "", beanMap.get(key));
}
}
return map;
}
/**
* 示例
* @throws ScriptException
*/
public static void ruleSample1() throws ScriptException {
Integer testExecute = (Integer) execute("2*3");
Object myb=execute("var a = 6==2*3");
String testExecuteForAttribute = (String) myb;
// String testExecuteForAttribute = (String) executeForAttribute("var value = 'a'+ 'dc'", "value");
Boolean testExecuteForFirstAttribute = (Boolean)executeForFirstAttribute("var a = 6==2*3");
System.out.println(testExecute);
System.out.println(testExecuteForAttribute);
System.out.println(testExecuteForFirstAttribute);
long start = System.currentTimeMillis();
for(int i=0;i<51;i++) {
ButtonRuleDto onbu=new ButtonRuleDto();
onbu.setRuleId(i+"");
onbu.setButtonRuleScript( "nextStage=='1'&&(currentStage=='2'||nextStage=='1')" );
onbu.setButtonId(i+"");
onbu.setButtonName("测试按钮");
buttonDisplayRules.add(onbu);
// System.out.println(testExecuteForFirstAttribute2);
}
PurchaseWorkbenchQueryReturnDto purchaseWorkbenchQueryReturnDto=new PurchaseWorkbenchQueryReturnDto();
purchaseWorkbenchQueryReturnDto.setNextStage("1");
purchaseWorkbenchQueryReturnDto.setCurrentStage("2");
long useTime = System.currentTimeMillis() - start;
StringBuilder prefix = new StringBuilder();
List testlist= verfiyButtonRule(purchaseWorkbenchQueryReturnDto);
prefix.append("Used Time (ms):");
prefix.append(useTime);
System.out.println("示例结束 ...."+prefix.toString());
}
/**
* 验证可显示的按钮列表
* @param purchaseWorkbenchQueryReturnDto
* @return
* @throws ScriptException
*/
public static List verfiyButtonRule(PurchaseWorkbenchQueryReturnDto purchaseWorkbenchQueryReturnDto)throws ScriptException
{
List strings=new ArrayList<>();
for( ButtonRuleDto buttonRuleDto: buttonDisplayRules) {
Boolean verfiyflg = isDisplay(buttonRuleDto.getButtonRuleScript(), purchaseWorkbenchQueryReturnDto);
if(verfiyflg)
{
strings.add(buttonRuleDto.getButtonId());
}
}
return strings;
}
}