提交 acd841e9 编写于 作者: T tianqiao

sync the alibaba inner version

1 add rule execute method to runner
2 fix some bugs
3 enhance some basic operator:instanceof ,bit operator
上级 2336835d
......@@ -6,7 +6,7 @@
<groupId>com.taobao.util</groupId>
<artifactId>taobao-express</artifactId>
<packaging>jar</packaging>
<version>3.0.18</version>
<version>3.1.4</version>
<name>taobao-express</name>
<dependencies>
......
......@@ -4,8 +4,15 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.ql.util.express.instruction.op.*;
import com.ql.util.express.parse.*;
import com.ql.util.express.rule.Condition;
import com.ql.util.express.rule.Rule;
import com.ql.util.express.rule.RuleManager;
import com.ql.util.express.rule.RuleResult;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
......@@ -13,14 +20,6 @@ import com.ql.util.express.instruction.ForRelBreakContinue;
import com.ql.util.express.instruction.IOperateDataCache;
import com.ql.util.express.instruction.InstructionFactory;
import com.ql.util.express.instruction.OperateDataCacheImpl;
import com.ql.util.express.instruction.op.OperatorBase;
import com.ql.util.express.instruction.op.OperatorFactory;
import com.ql.util.express.instruction.op.OperatorMinMax;
import com.ql.util.express.instruction.op.OperatorPrint;
import com.ql.util.express.instruction.op.OperatorPrintln;
import com.ql.util.express.instruction.op.OperatorRound;
import com.ql.util.express.instruction.op.OperatorSelfDefineClassFunction;
import com.ql.util.express.instruction.op.OperatorSelfDefineServiceFunction;
/**
* 语法分析和计算的入口类
......@@ -35,22 +34,27 @@ public class ExpressRunner {
* 是否输出所有的跟踪信息,同时还需要log级别是DEBUG级别
*/
private boolean isTrace = false;
/**
* 是否使用逻辑短路特性增强质量的效率
*/
private boolean isShortCircuit = true;
/**
* 是否需要高精度计算
*/
private boolean isPrecise = false;
/**
* 一段文本对应的指令集的缓存
*/
private Map<String,InstructionSet> expressInstructionSetCache = new HashMap<String, InstructionSet>();
/**
* 一段文本对应的规则的缓存
*/
private Map<String,Rule> ruleCache = new HashMap<String, Rule>();
private ExpressLoader loader;
private IExpressResourceLoader expressResourceLoader;
/**
......@@ -64,8 +68,8 @@ public class ExpressRunner {
/**
* 语法分析器
*/
private ExpressParse parse ;
private ExpressParse parse ;
/**
* 缺省的Class查找的包管理器
*/
......@@ -82,7 +86,7 @@ public class ExpressRunner {
}
private AppendingClassFieldManager appendingClassFieldManager;
private ThreadLocal<IOperateDataCache> m_OperateDataObjectCache = new ThreadLocal<IOperateDataCache>(){
protected IOperateDataCache initialValue() {
return new OperateDataCacheImpl(30);
......@@ -91,12 +95,12 @@ public class ExpressRunner {
public IOperateDataCache getOperateDataCache(){
return this.m_OperateDataObjectCache.get();
}
public ExpressRunner(){
this(false,false);
}
/**
*
*
* @param aIsPrecise 是否需要高精度计算支持
* @param aIstrace 是否跟踪执行指令的过程
*/
......@@ -107,7 +111,7 @@ public class ExpressRunner {
this(aIsPrecise,aIstrace,new DefaultExpressResourceLoader(),aManager);
}
/**
*
*
* @param aIsPrecise 是否需要高精度计算支持
* @param aIstrace 是否跟踪执行指令的过程
* @param aExpressResourceLoader 表达式的资源装载器
......@@ -127,10 +131,20 @@ public class ExpressRunner {
rootExpressPackage.addPackage("java.lang");
rootExpressPackage.addPackage("java.util");
this.addSystemFunctions();
}
public void addSystemFunctions(){
this.addFunction("max", new OperatorMinMax("max"));
this.addFunction("min", new OperatorMinMax("min"));
this.addSystemOperators();
}
private void addSystemOperators() {
try {
this.addOperator("instanceof", new OperatorInstanceOf("instanceof"));
}catch (Exception e){
throw new RuntimeException(e);
}
}
public void addSystemFunctions(){
this.addFunction("max", new OperatorMinMax("max"));
this.addFunction("min", new OperatorMinMax("min"));
this.addFunction("round", new OperatorRound("round"));
this.addFunction("print", new OperatorPrint("print"));
this.addFunction("println", new OperatorPrintln("println"));
......@@ -157,23 +171,23 @@ public class ExpressRunner {
* 添加宏定义 例如: macro 玄难 { abc(userinfo.userId);}
* @param macroName:玄难
* @param express :abc(userinfo.userId);
* @throws Exception
* @throws Exception
*/
public void addMacro(String macroName,String express) throws Exception{
public void addMacro(String macroName,String express) throws Exception{
String macroExpress = "macro " + macroName +" {" + express + "}";
this.loader.parseInstructionSet(GLOBAL_DEFINE_NAME,macroExpress);
}
/**
* 装载表达式,但不执行,例如一些宏定义,或者自定义函数
* @param groupName
* @param express
* @throws Exception
*/
public void loadMutilExpress(String groupName,String express) throws Exception{
public void loadMutilExpress(String groupName,String express) throws Exception{
if(groupName == null || groupName.trim().length() ==0){
groupName = GLOBAL_DEFINE_NAME;
}
}
this.loader.parseInstructionSet(groupName,express);
}
/**
......@@ -267,7 +281,7 @@ public class ExpressRunner {
String errorInfo) throws Exception {
this.addFunction(name, new OperatorSelfDefineClassFunction(name,
aClassName, aFunctionName, aParameterClassTypes,null,null, errorInfo));
}
/**
* 添加一个类的函数定义,例如:Math.abs(double) 映射为表达式中的 "取绝对值(-5.0)"
......@@ -275,7 +289,7 @@ public class ExpressRunner {
* @param aClassName 类名称
* @param aFunctionName 类中的方法名称
* @param aParameterClassTypes 方法的参数类型名称
* @param aParameterDesc 方法的参数说明
* @param aParameterDesc 方法的参数说明
* @param aParameterAnnotation 方法的参数注解
* @param errorInfo 如果函数执行的结果是false,需要输出的错误信息
* @throws Exception
......@@ -301,7 +315,7 @@ public class ExpressRunner {
String aFunctionName, String[] aParameterTypes, String errorInfo)
throws Exception {
this.addFunction(name, new OperatorSelfDefineClassFunction(name,
aClassName, aFunctionName, aParameterTypes, null,null,errorInfo));
aClassName, aFunctionName, aParameterTypes, null,null,errorInfo));
}
/**
* 添加一个类的函数定义,例如:Math.abs(double) 映射为表达式中的 "取绝对值(-5.0)"
......@@ -309,7 +323,7 @@ public class ExpressRunner {
* @param aClassName 类名称
* @param aFunctionName 类中的方法名称
* @param aParameterTypes 方法的参数类型名称
* @param aParameterDesc 方法的参数说明
* @param aParameterDesc 方法的参数说明
* @param aParameterAnnotation 方法的参数注解
* @param errorInfo 如果函数执行的结果是false,需要输出的错误信息
* @throws Exception
......@@ -320,8 +334,8 @@ public class ExpressRunner {
String errorInfo)
throws Exception {
this.addFunction(name, new OperatorSelfDefineClassFunction(name,
aClassName, aFunctionName, aParameterTypes, aParameterDesc,aParameterAnnotation,errorInfo));
aClassName, aFunctionName, aParameterTypes, aParameterDesc,aParameterAnnotation,errorInfo));
}
/**
* 用于将一个用户自己定义的对象(例如Spring对象)方法转换为一个表达式计算的函数
......@@ -337,7 +351,7 @@ public class ExpressRunner {
String errorInfo) throws Exception {
this.addFunction(name, new OperatorSelfDefineServiceFunction(name,
aServiceObject, aFunctionName, aParameterClassTypes,null,null, errorInfo));
}
/**
* 用于将一个用户自己定义的对象(例如Spring对象)方法转换为一个表达式计算的函数
......@@ -345,11 +359,11 @@ public class ExpressRunner {
* @param aServiceObject
* @param aFunctionName
* @param aParameterClassTypes
* @param aParameterDesc 方法的参数说明
* @param aParameterDesc 方法的参数说明
* @param aParameterAnnotation 方法的参数注解
* @param errorInfo
* @throws Exception
*/
*/
public void addFunctionOfServiceMethod(String name, Object aServiceObject,
String aFunctionName, Class<?>[] aParameterClassTypes,
String[] aParameterDesc,String[] aParameterAnnotation,
......@@ -369,7 +383,7 @@ public class ExpressRunner {
*/
public void addFunctionOfServiceMethod(String name, Object aServiceObject,
String aFunctionName, String[] aParameterTypes, String errorInfo)
throws Exception {
throws Exception {
this.addFunction(name, new OperatorSelfDefineServiceFunction(name,
aServiceObject, aFunctionName, aParameterTypes,null,null, errorInfo));
......@@ -387,7 +401,7 @@ public class ExpressRunner {
* 添加操作符号,此操作符号的优先级与 "*"相同,语法形式也是 data name data
* @param name
* @param op
* @throws Exception
* @throws Exception
*/
public void addOperator(String name,Operator op) throws Exception {
this.addOperator(name, "*", op);
......@@ -397,7 +411,7 @@ public class ExpressRunner {
* @param name 操作符号名称
* @param aRefOpername 参照的操作符号,例如 "+","--"等
* @param op
* @throws Exception
* @throws Exception
*/
public void addOperator(String name,String aRefOpername,Operator op) throws Exception {
this.manager.addOperatorWithLevelOfReference(name, aRefOpername);
......@@ -425,7 +439,7 @@ public class ExpressRunner {
}
NodeType realNodeType = this.manager.findNodeType(realKeyWordName);
if(realNodeType == null){
throw new Exception("关键字:" + realKeyWordName +"不存在");
throw new Exception("关键字:" + realKeyWordName +"不存在");
}
boolean isExist = this.operatorManager.isExistOperator(realNodeType.getName());
if(isExist == false && errorInfo != null){
......@@ -435,7 +449,7 @@ public class ExpressRunner {
//不需要新增操作符号,只需要建立一个关键子即可
this.manager.addOperatorWithRealNodeType(keyWordName, realNodeType.getName());
}else{
this.manager.addOperatorWithLevelOfReference(keyWordName, realNodeType.getName());
this.manager.addOperatorWithLevelOfReference(keyWordName, realNodeType.getName());
this.operatorManager.addOperatorWithAlias(keyWordName, realNodeType.getName(), errorInfo);
}
}
......@@ -446,7 +460,7 @@ public class ExpressRunner {
public OperatorBase replaceOperator(String name,OperatorBase op){
return this.operatorManager.replaceOperator(name, op);
}
public ExpressPackage getRootExpressPackage(){
return this.rootExpressPackage;
}
......@@ -492,7 +506,7 @@ public class ExpressRunner {
return InstructionSetRunner.executeOuter(this,instructionSets[0],this.loader,context, errorList,
isTrace,isCatchException,aLog,false);
}
/**
* 执行指令集
* @param instructionSets
......@@ -557,6 +571,73 @@ public class ExpressRunner {
isTrace,false,aLog,false);
}
public RuleResult executeRule(String expressString, IExpressContext<String,Object> context, boolean isCache, boolean isTrace)
throws Exception {
Rule rule = null;
if (isCache == true) {
rule = ruleCache.get(expressString);
if (rule == null) {
synchronized (ruleCache) {
rule = ruleCache.get(expressString);
if (rule == null) {
rule = this.parseRule(expressString);
ruleCache.put(expressString,
rule);
}
}
}
} else {
rule = this.parseRule(expressString);
}
return RuleManager.executeRule(this,rule,context,isCache,isTrace);
}
static Pattern patternRule = Pattern.compile("rule[\\s]+'([^']+)'[\\s]+name[\\s]+'([^']+)'[\\s]+");
public Rule parseRule(String text)
throws Exception {
String ruleName = null;
String ruleCode = null;
Matcher matcher = patternRule.matcher(text);
if(matcher.find()) {
ruleCode = matcher.group(1);
ruleName = matcher.group(2);
text = text.substring(matcher.end());
}
Map<String,String> selfDefineClass = new HashMap<String,String> ();
for(ExportItem item : this.loader.getExportInfo()){
if(item.getType().equals(InstructionSet.TYPE_CLASS)){
selfDefineClass.put(item.getName(), item.getName());
}
}
// 分成两句话执行,用来保存中间的words结果
// ExpressNode root = this.parse.parse(this.rootExpressPackage,text, isTrace,selfDefineClass);
Word[] words = this.parse.splitWords(rootExpressPackage,text,isTrace,selfDefineClass);
ExpressNode root = this.parse.parse(rootExpressPackage,words,text,isTrace,selfDefineClass);
Rule rule = RuleManager.createRule(root,words);
rule.setCode(ruleCode);
rule.setName(ruleName);
return rule;
}
public Condition parseContition(String text)
throws Exception {
Map<String,String> selfDefineClass = new HashMap<String,String> ();
for(ExportItem item : this.loader.getExportInfo()){
if(item.getType().equals(InstructionSet.TYPE_CLASS)){
selfDefineClass.put(item.getName(), item.getName());
}
}
Word[] words = this.parse.splitWords(rootExpressPackage,text,isTrace,selfDefineClass);
ExpressNode root = this.parse.parse(rootExpressPackage,words,text,isTrace,selfDefineClass);
return RuleManager.createCondition(root,words);
}
/**
* 解析一段文本,生成指令集合
* @param text
......@@ -571,7 +652,7 @@ public class ExpressRunner {
selfDefineClass.put(item.getName(), item.getName());
}
}
ExpressNode root = this.parse.parse(this.rootExpressPackage,text, isTrace,selfDefineClass);
InstructionSet result = createInstructionSet(root, "main");
if (this.isTrace && log.isDebugEnabled()) {
......@@ -586,7 +667,7 @@ public class ExpressRunner {
public ExportItem[] getExportInfo(){
return this.loader.getExportInfo();
}
/**
* 优先从本地指令集缓存获取指令集,没有的话生成并且缓存在本地
* @param expressString
......@@ -637,7 +718,7 @@ public class ExpressRunner {
* 获取一个表达式需要的外部变量名称列表
* @param express
* @return
* @throws Exception
* @throws Exception
*/
public String[] getOutVarNames(String express) throws Exception{
return this.parseInstructionSet(express).getOutAttrNames();
......
......@@ -3,6 +3,8 @@ package com.ql.util.express;
import com.ql.util.express.instruction.OperateDataCacheManager;
import com.ql.util.express.instruction.op.OperatorBase;
import java.util.Date;
/**
* 操作符的基类
* @author xuannan
......@@ -12,7 +14,7 @@ public abstract class Operator extends OperatorBase{
public OperateData executeInner(InstructionSetContext context, ArraySwap list) throws Exception{
Object[] parameters = new Object[list.length];
for(int i = 0;i <list.length;i++){
for(int i = 0;i <list.length;i++){
parameters[i] = list.get(i).getObject(context);
}
Object result = this.executeInner(parameters);
......@@ -53,7 +55,10 @@ public abstract class Operator extends OperatorBase{
compareResult =0;
else
compareResult =-1;
}
}else if ((op1 instanceof Date) && (op2 instanceof Date))
{
compareResult = ((Date) op1).compareTo((Date) op2);
}
else
throw new Exception(op1 + "和" + op2 +"不能执行compare 操作");
return compareResult;
......
......@@ -15,7 +15,7 @@ public class BlockInstructionFactory extends InstructionFactory {
throws Exception {
if (node.isTypeEqualsOrChild("STAT_SEMICOLON")
&&result.getCurrentPoint() >=0 && result.getInstruction(result.getCurrentPoint()) instanceof InstructionClearDataStack == false) {
result.addInstruction(new InstructionClearDataStack());
result.addInstruction(new InstructionClearDataStack().setLine(node.getLine()));
}
int tmpPoint = result.getCurrentPoint()+1;
......@@ -27,8 +27,8 @@ public class BlockInstructionFactory extends InstructionFactory {
}
if (hasDef == true&& isRoot == false
&& node.getTreeType().isEqualsOrChild("STAT_BLOCK")){
result.insertInstruction(tmpPoint,new InstructionOpenNewArea());
result.insertInstruction(result.getCurrentPoint() + 1,new InstructionCloseNewArea());
result.insertInstruction(tmpPoint,new InstructionOpenNewArea().setLine(node.getLine()));
result.insertInstruction(result.getCurrentPoint() + 1,new InstructionCloseNewArea().setLine(node.getLine()));
returnVal = false;
}else{
returnVal = hasDef;
......
......@@ -14,7 +14,7 @@ public class BreakInstructionFactory extends InstructionFactory {
InstructionGoTo breakInstruction = new InstructionGoTo(result.getCurrentPoint()+1);
breakInstruction.name = "break";
forStack.peek().breakList.add(breakInstruction);
result.addInstruction(breakInstruction);
result.addInstruction(breakInstruction.setLine(node.getLine()));
return false;
}
}
......@@ -28,10 +28,10 @@ public class CallFunctionInstructionFactory extends InstructionFactory{
functionName);
int opNum = children.length -1;
if (op != null) {
result.addInstruction(new InstructionOperator(op,opNum ));
result.addInstruction(new InstructionOperator(op,opNum ).setLine(node.getLine()));
} else {
result.addInstruction(new InstructionCallSelfDefineFunction(
functionName,opNum));
functionName,opNum).setLine(children[0].getLine()));
}
return returnVal;
}
......
......@@ -27,7 +27,7 @@ public class CastInstructionFactory extends InstructionFactory{
boolean tmpHas = aCompile.createInstructionSetPrivate(result,forStack,children[i],false);
returnVal = returnVal || tmpHas;
}
result.addInstruction(new InstructionOperator(op,children.length));
result.addInstruction(new InstructionOperator(op,children.length).setLine(node.getLine()));
return returnVal;
}
}
......@@ -21,7 +21,7 @@ public class ConstDataInstructionFactory extends InstructionFactory {
public boolean createInstruction(ExpressRunner aCompile,
InstructionSet result, Stack<ForRelBreakContinue> forStack,
ExpressNode node, boolean isRoot) throws Exception {
result.addInstruction(new InstructionConstData(genOperateData(node)));
result.addInstruction(new InstructionConstData(genOperateData(node)).setLine(node.getLine()));
return false;
}
}
......@@ -14,7 +14,7 @@ public class ContinueInstructionFactory extends InstructionFactory {
InstructionGoTo continueInstruction = new InstructionGoTo(result.getCurrentPoint()+1);
continueInstruction.name = "continue";
forStack.peek().continueList.add(continueInstruction);
result.addInstruction(continueInstruction);
result.addInstruction(continueInstruction.setLine(node.getLine()));
return false;
}
}
......@@ -48,7 +48,7 @@ class DefineInstructionFactory extends InstructionFactory{
finishPoint[i] = result.getCurrentPoint();
}
OperatorBase op = aCompile.getOperatorFactory().newInstance(node);
result.addInstruction(new InstructionOperator(op, children.length));
result.addInstruction(new InstructionOperator(op, children.length).setLine(node.getLine()));
returnVal = true;
return returnVal;
}
......
......@@ -29,7 +29,7 @@ public class FieldCallInstructionFactory extends InstructionFactory {
OperatorBase op = new OperatorField(fieldName);
result.addInstruction(new InstructionOperator(op,1));
result.addInstruction(new InstructionOperator(op,1).setLine(node.getLine()));
return returnVal;
}
......
......@@ -23,7 +23,7 @@ public class ForInstructionFactory extends InstructionFactory {
throw new Exception("循环语句的设置不合适:" + node.getChildren()[0]);
}
//生成作用域开始指令
result.addInstruction(new InstructionOpenNewArea());
result.addInstruction(new InstructionOpenNewArea().setLine(node.getLine()));
forStack.push(new ForRelBreakContinue());
//生成条件语句部分指令
......@@ -49,7 +49,7 @@ public class ForInstructionFactory extends InstructionFactory {
aCompile.createInstructionSetPrivate(result,forStack,conditionNode.getChildren()[nodePoint],false);
//跳转的位置需要根据后续的指令情况决定
conditionInstruction = new InstructionGoToWithCondition(false,-1,true);
result.insertInstruction(result.getCurrentPoint()+1,conditionInstruction);
result.insertInstruction(result.getCurrentPoint()+1,conditionInstruction.setLine(node.getLine()));
nodePoint = nodePoint+ 1;
}
int conditionPoint = result.getCurrentPoint();
......@@ -65,7 +65,7 @@ public class ForInstructionFactory extends InstructionFactory {
}
//增加一个无条件跳转
InstructionGoTo reStartGoto = new InstructionGoTo(loopStartPoint - (result.getCurrentPoint() + 1));
result.addInstruction(reStartGoto);
result.addInstruction(reStartGoto.setLine(node.getLine()));
//修改条件判断的跳转位置
if(conditionInstruction != null){
......@@ -82,7 +82,7 @@ public class ForInstructionFactory extends InstructionFactory {
}
//生成作用域结束指令
result.addInstruction(new InstructionCloseNewArea());
result.addInstruction(new InstructionCloseNewArea().setLine(node.getLine()));
return false;
}
......
......@@ -37,10 +37,10 @@ public class IfInstructionFactory extends InstructionFactory {
boolean r1 = aCompile.createInstructionSetPrivate(result,forStack,children[0],false);//condition
finishPoint[0] = result.getCurrentPoint();
boolean r2 = aCompile.createInstructionSetPrivate(result,forStack,children[1],false);//true
result.insertInstruction(finishPoint[0]+1,new InstructionGoToWithCondition(false,result.getCurrentPoint() - finishPoint[0] + 2,true));
result.insertInstruction(finishPoint[0]+1,new InstructionGoToWithCondition(false,result.getCurrentPoint() - finishPoint[0] + 2,true).setLine(node.getLine()));
finishPoint[1] = result.getCurrentPoint();
boolean r3 = aCompile.createInstructionSetPrivate(result,forStack,children[2],false);//false
result.insertInstruction(finishPoint[1]+1,new InstructionGoTo(result.getCurrentPoint() - finishPoint[1] + 1));
result.insertInstruction(finishPoint[1]+1,new InstructionGoTo(result.getCurrentPoint() - finishPoint[1] + 1).setLine(node.getLine()));
return r1 || r2 || r3;
}
}
......@@ -29,7 +29,7 @@ public class InInstructionFactory extends InstructionFactory{
returnVal = returnVal || tmpHas;
}
OperatorBase op = aCompile.getOperatorFactory().newInstance(node);
result.addInstruction(new InstructionOperator(op, children.length));
result.addInstruction(new InstructionOperator(op, children.length).setLine(node.getLine()));
return returnVal;
}
}
......@@ -28,7 +28,7 @@ class KeyValueInstructionFactory extends InstructionFactory{
returnVal = returnVal || tmpHas;
}
OperatorBase op = aCompile.getOperatorFactory().newInstance("alias");
result.addInstruction(new InstructionOperator(op, children.length));
result.addInstruction(new InstructionOperator(op, children.length).setLine(node.getLine()));
returnVal = true;
}else{
for(int i =0;i < children.length;i++){
......@@ -38,7 +38,7 @@ class KeyValueInstructionFactory extends InstructionFactory{
}
OperatorBase op = aCompile.getOperatorFactory().newInstance(node);
result.addInstruction(new InstructionOperator(op,children.length));
result.addInstruction(new InstructionOperator(op,children.length).setLine(node.getLine()));
}
return returnVal;
}
......
......@@ -15,9 +15,9 @@ public class LoadAttrInstructionFactory extends InstructionFactory {
throws Exception{
FunctionInstructionSet functionSet = result.getMacroDefine(node.getValue());
if(functionSet != null){//是宏定义
result.insertInstruction(result.getCurrentPoint()+1, new InstructionCallMacro(node.getValue()));
result.insertInstruction(result.getCurrentPoint()+1, new InstructionCallMacro(node.getValue()).setLine(node.getLine()).setLine(node.getLine()));
}else{
result.addInstruction(new InstructionLoadAttr(node.getValue()));
result.addInstruction(new InstructionLoadAttr(node.getValue()).setLine(node.getLine()));
if(node.getChildren().length >0){
throw new Exception("表达式设置错误");
}
......
......@@ -30,7 +30,7 @@ public class MethodCallInstructionFactory extends InstructionFactory {
returnVal = returnVal || tmpHas;
}
OperatorBase op = new OperatorMethod(methodName);
result.addInstruction(new InstructionOperator(op, children.length - 1));
result.addInstruction(new InstructionOperator(op, children.length - 1).setLine(node.getLine()));
return returnVal;
}
......
......@@ -34,7 +34,7 @@ public class NewInstructionFactory extends InstructionFactory{
boolean tmpHas = aCompile.createInstructionSetPrivate(result,forStack, children[i], false);
returnVal = returnVal || tmpHas;
}
result.addInstruction(new InstructionOperator(op, children.length));
result.addInstruction(new InstructionOperator(op, children.length).setLine(node.getLine()));
return returnVal;
}
}
......@@ -19,7 +19,7 @@ public class NewVClassInstructionFactory extends InstructionFactory{
boolean tmpHas = aCompile.createInstructionSetPrivate(result,forStack, children[i], false);
returnVal = returnVal || tmpHas;
}
result.addInstruction(new InstructionNewVirClass(virClassName, children.length -1));
result.addInstruction(new InstructionNewVirClass(virClassName, children.length -1).setLine(node.getLine()));
return returnVal;
}
}
......@@ -27,16 +27,16 @@ class OperatorInstructionFactory extends InstructionFactory{
}
if(node.isTypeEqualsOrChild("return")){
result.addInstruction(new InstructionReturn(children.length > 0));
result.addInstruction(new InstructionReturn(children.length > 0).setLine(node.getLine()));
}else{
OperatorBase op = aCompile.getOperatorFactory().newInstance(node);
result.addInstruction(new InstructionOperator(op,children.length));
result.addInstruction(new InstructionOperator(op,children.length).setLine(node.getLine()).setLine(node.getLine()));
if(node.isTypeEqualsOrChild("&&") && aCompile.isShortCircuit()){
result.insertInstruction(finishPoint[0]+1,new InstructionGoToWithCondition(false,result.getCurrentPoint() - finishPoint[0] + 1,false));
result.insertInstruction(finishPoint[0]+1,new InstructionGoToWithCondition(false,result.getCurrentPoint() - finishPoint[0] + 1,false).setLine(node.getLine()));
}else if(node.isTypeEqualsOrChild("||") && aCompile.isShortCircuit()){
result.insertInstruction(finishPoint[0]+1,new InstructionGoToWithCondition(true,result.getCurrentPoint() - finishPoint[0] + 1,false));
result.insertInstruction(finishPoint[0]+1,new InstructionGoToWithCondition(true,result.getCurrentPoint() - finishPoint[0] + 1,false).setLine(node.getLine()));
}else if(node.isTypeEqualsOrChild("nor") ){
result.insertInstruction(finishPoint[0]+1,new InstructionGoToWithNotNull(result.getCurrentPoint() - finishPoint[0] + 1,false));
result.insertInstruction(finishPoint[0]+1,new InstructionGoToWithNotNull(result.getCurrentPoint() - finishPoint[0] + 1,false).setLine(node.getLine()));
}else if(node.isTypeEqualsOrChild("def") || node.isTypeEqualsOrChild("alias")){
returnVal = true;
}else if(node.isTypeEqualsOrChild("exportDef")){
......
......@@ -13,11 +13,26 @@ public abstract class Instruction implements java.io.Serializable {
private static final long serialVersionUID = 1361458333068300443L;
protected static transient Log staticLog = LogFactory.getLog(Instruction.class);
protected static transient Log log = staticLog;
public void setLog(Log aLog) {
private Integer line = 0;
public Instruction setLine(Integer line)
{
this.line = line;
return this;
}
public Integer getLine() {
return line;
}
public void setLog(Log aLog) {
if (aLog != null) {
this.log = aLog;
}
}
public String getExceptionPrefix()
{
return "run QlExpress Exception at line "+line+" :";
}
public abstract void execute(RunEnvironment environment, List<String> errorList)
throws Exception;
}
......@@ -59,7 +59,7 @@ public class InstructionCallSelfDefineFunction extends Instruction{
Object function = environment.getContext().getSymbol(functionName);
if (function == null || function instanceof InstructionSet == false) {
throw new Exception("在Runner的操作符定义和自定义函数中都没有找到\""
throw new Exception(getExceptionPrefix()+"在Runner的操作符定义和自定义函数中都没有找到\""
+ this.functionName + "\"的定义");
}
InstructionSet functionSet = (InstructionSet)function;
......
......@@ -37,7 +37,7 @@ public class InstructionGoToWithCondition extends Instruction{
}else if(o instanceof Boolean){
r = ((Boolean)o).booleanValue();
}else{
throw new Exception("指令错误:" + o + " 不是Boolean");
throw new Exception(getExceptionPrefix()+"指令错误:" + o + " 不是Boolean");
}
if (r == this.condition) {
if (environment.isTrace() && log.isDebugEnabled()) {
......
......@@ -22,7 +22,7 @@ public class InstructionOperator extends Instruction{
return this.operator;
}
public void execute(RunEnvironment environment,List<String> errorList) throws Exception{
ArraySwap parameters = environment.popArray(environment.getContext(),this.opDataNumber);
ArraySwap parameters = environment.popArray(environment.getContext(),this.opDataNumber);
if(environment.isTrace() && this.log.isDebugEnabled()){
String str = this.operator.toString() + "(";
OperateData p = null;
......@@ -40,13 +40,16 @@ public class InstructionOperator extends Instruction{
str = str + ")";
this.log.debug(str);
}
OperateData result = this.operator.execute(environment.getContext(),parameters, errorList);
environment.push(result);
environment.programPointAddOne();
try {
OperateData result = this.operator.execute(environment.getContext(), parameters, errorList);
environment.push(result);
environment.programPointAddOne();
}catch (Exception e){
throw new Exception(getExceptionPrefix(),e);
}
}
public String toString(){
String result = "OP : " + this.operator.toString() + " OPNUMBER[" + this.opDataNumber +"]";
return result;
}
}
}
package com.ql.util.express.instruction.op;
import com.ql.util.express.Operator;
import java.util.Arrays;
/**
* Created by tianqiao on 16/12/15.
*/
public class OperatorBit extends Operator {
public OperatorBit(String name)
{
this.name = name;
}
@Override
public Object executeInner(Object[] list) throws Exception {
if( this.name.equals("~")){
if (list.length == 1 && list[0] instanceof Number) {
if(list[0]instanceof Integer) {
return ~(((Number) list[0]).intValue());
}else{
return ~(((Number) list[0]).longValue());
}
}else{
throw new Exception("取反操作符 ~ 参数不合法:"+ Arrays.toString(list));
}
}
if( this.name.equals("&")){
if (list.length == 2 && list[0] instanceof Number && list[1] instanceof Number) {
if(list[0]instanceof Integer && list[1] instanceof Integer){
return (Integer)list[0]&(Integer)list[1];
}
return (((Number)list[0]).longValue())&(((Number)list[1]).longValue());
}else{
throw new Exception("按位与操作符 & 两边的参数不合法:"+ Arrays.toString(list));
}
}
if( this.name.equals("|")){
if (list.length == 2 && list[0] instanceof Number && list[1] instanceof Number) {
if(list[0]instanceof Integer && list[1] instanceof Integer){
return (Integer)list[0]|(Integer)list[1];
}
return (((Number)list[0]).longValue())|(((Number)list[1]).longValue());
}else{
throw new Exception("按位或操作符 | 两边的参数不合法:"+ Arrays.toString(list));
}
}
if( this.name.equals("^")){
if (list.length == 2 && list[0] instanceof Number && list[1] instanceof Number) {
if(list[0]instanceof Integer && list[1] instanceof Integer){
return (Integer)list[0]^(Integer)list[1];
}
return (((Number)list[0]).longValue())^(((Number)list[1]).longValue());
}else{
throw new Exception("按位异或操作符 ^ 两边的参数不合法:"+ Arrays.toString(list));
}
}
if( this.name.equals("<<")){
if (list.length == 2 && list[0] instanceof Number && list[1] instanceof Number) {
if(list[0]instanceof Integer && list[1] instanceof Integer){
return (Integer)list[0]<<(Integer)list[1];
}
return (((Number)list[0]).longValue())<<(((Number)list[1]).longValue());
}else{
throw new Exception("左移操作符 << 两边的参数不合法:"+ Arrays.toString(list));
}
}
if( this.name.equals(">>")){
if (list.length == 2 && list[0] instanceof Number && list[1] instanceof Number) {
if(list[0]instanceof Integer && list[1] instanceof Integer){
return (Integer)list[0]>>(Integer)list[1];
}
return (((Number)list[0]).longValue())>>(((Number)list[1]).longValue());
}else{
throw new Exception("右移操作符 >> 两边的参数不合法:"+ Arrays.toString(list));
}
}
throw new Exception("不支持的位运算操作符:"+ Arrays.toString(list));
}
}
......@@ -54,6 +54,13 @@ public class OperatorFactory {
addOperator("function",new OperatorFunction("function"));
addOperator("in", new OperatorIn("in"));
addOperator("like", new OperatorLike("like"));
//bit operator
addOperator("&",new OperatorBit("&"));
addOperator("|",new OperatorBit("|"));
addOperator("^",new OperatorBit("^"));
addOperator("~",new OperatorBit("~"));
addOperator("<<",new OperatorBit("<<"));
addOperator(">>",new OperatorBit(">>"));
}
public void addOperator(String name, OperatorBase op) {
OperatorBase oldOp = this.operator.get(name);
......
package com.ql.util.express.instruction.op;
import com.ql.util.express.Operator;
/**
* Created by tianqiao on 17/9/19.
*/
public class OperatorInstanceOf extends Operator {
public OperatorInstanceOf(String anInstanceof) {
this.name = anInstanceof;
}
@Override
public Object executeInner(Object[] list) throws Exception {
Object obj = list[0];
Object cls = list[1];
if(obj!=null && cls!=null && cls instanceof Class){
Class targetClass = (Class) cls;
Class fromClass = obj.getClass();
return targetClass.isAssignableFrom(fromClass);
}
return false;
}
}
......@@ -17,7 +17,7 @@ public class OperatorSelfDefineClassFunction extends OperatorBase implements Can
Class<?>[] parameterClasses ;
Class<?> operClass;
Object operInstance;
transient Method method;
Method method;
boolean isReturnVoid;
boolean maybeDynamicParams;
......@@ -25,7 +25,7 @@ public class OperatorSelfDefineClassFunction extends OperatorBase implements Can
Class<?>[] aParameterClassTypes,String[] aParameterDesc,String[] aParameterAnnotation,String aErrorInfo) throws Exception {
if (errorInfo != null && errorInfo.trim().length() == 0) {
errorInfo = null;
}
}
this.name = aOperName;
this.errorInfo = aErrorInfo;
this.functionName = aFunctionName;
......@@ -46,7 +46,7 @@ public class OperatorSelfDefineClassFunction extends OperatorBase implements Can
String[] aParameterTypes,String[] aParameterDesc,String[] aParameterAnnotation,String aErrorInfo) throws Exception {
if (errorInfo != null && errorInfo.trim().length() == 0) {
errorInfo = null;
}
}
this.name = aOperName;
this.errorInfo = aErrorInfo;
this.functionName = aFunctionName;
......@@ -73,13 +73,13 @@ public class OperatorSelfDefineClassFunction extends OperatorBase implements Can
public OperateData executeInner(InstructionSetContext context, ArraySwap list) throws Exception {
Object[] parameres = DynamicParamsUtil.transferDynamicParams(context, list, parameterClasses,this.maybeDynamicParams);
Object obj = null;
if( Modifier.isStatic(this.getMethod().getModifiers())){
obj = this.getMethod().invoke(null,ExpressUtil.transferArray(parameres,parameterClasses));
if( Modifier.isStatic(this.method.getModifiers())){
obj = this.method.invoke(null,ExpressUtil.transferArray(parameres,parameterClasses));
}else{
if(operInstance==null){
operInstance = operClass.newInstance();
}
obj = this.getMethod().invoke(operInstance,ExpressUtil.transferArray(parameres,parameterClasses));
obj = this.method.invoke(operInstance,ExpressUtil.transferArray(parameres,parameterClasses));
}
if(obj != null){
......@@ -88,17 +88,8 @@ public class OperatorSelfDefineClassFunction extends OperatorBase implements Can
if(this.isReturnVoid == true){
return OperateDataCacheManager.fetchOperateDataAttr("null", void.class);
}else{
return OperateDataCacheManager.fetchOperateDataAttr("null", null);
}
}
private Method getMethod() throws NoSuchMethodException {
if(this.method!=null){
return this.method;
return OperateDataCacheManager.fetchOperateDataAttr("null", null);
}
this.method = operClass.getMethod(functionName,parameterClasses);
return this.method;
}
......
......@@ -15,7 +15,7 @@ public class OperatorSelfDefineServiceFunction extends OperatorBase implements C
String functionName;
String[] parameterTypes;
Class<?>[] parameterClasses ;
transient Method method;
Method method;
boolean isReturnVoid;
boolean maybeDynamicParams;
......@@ -24,7 +24,7 @@ public class OperatorSelfDefineServiceFunction extends OperatorBase implements C
Class<?>[] aParameterClassTypes,String[] aParameterDesc,String[] aParameterAnnotation, String aErrorInfo) throws Exception {
if (errorInfo != null && errorInfo.trim().length() == 0) {
errorInfo = null;
}
}
this.name = aOperName;
this.errorInfo = aErrorInfo;
this.serviceObject = aServiceObject;
......@@ -47,7 +47,7 @@ public class OperatorSelfDefineServiceFunction extends OperatorBase implements C
if (errorInfo != null && errorInfo.trim().length() == 0) {
errorInfo = null;
}
}
this.name = aOperName;
this.errorInfo = aErrorInfo;
this.serviceObject = aServiceObject;
......@@ -73,24 +73,14 @@ public class OperatorSelfDefineServiceFunction extends OperatorBase implements C
}
public OperateData executeInner(InstructionSetContext context, ArraySwap list) throws Exception {
Object[] parameres = DynamicParamsUtil.transferDynamicParams(context, list, parameterClasses,this.maybeDynamicParams);
Object obj = this.getMethod().invoke(this.serviceObject,ExpressUtil.transferArray(parameres,parameterClasses));
Object obj = this.method.invoke(this.serviceObject,ExpressUtil.transferArray(parameres,parameterClasses));
if(obj != null){
return OperateDataCacheManager.fetchOperateData(obj,obj.getClass());
}
if(this.isReturnVoid == true){
return OperateDataCacheManager.fetchOperateDataAttr("null", void.class);
}else{
return OperateDataCacheManager.fetchOperateDataAttr("null", null);
return OperateDataCacheManager.fetchOperateDataAttr("null", null);
}
}
private Method getMethod() throws NoSuchMethodException {
if(this.method!=null){
return this.method;
}
Class<?> operClass = serviceObject.getClass();
this.method = operClass.getMethod(functionName, parameterClasses);
return this.method;
}
}
......@@ -41,11 +41,19 @@ public class ExpressNode implements IDataNode{
* 列号
*/
private int col;
public ExpressNode(NodeType aType,String aValue) throws Exception{
this(aType, aValue, null,null,null,-1,-1);
/**
* word的序号
*/
private int wordIndex = -1;
public int getWordIndex() {
return wordIndex;
}
public ExpressNode(NodeType aType, String aValue) throws Exception{
this(aType, aValue, null,null,null,-1,-1,-1);
}
public ExpressNode(NodeType aType,String aValue,String aOrgiValue,Object aObjectValue,NodeType aTreeType,int aLine,int aCol) throws Exception{
public ExpressNode(NodeType aType,String aValue,String aOrgiValue,Object aObjectValue,NodeType aTreeType,int aLine,int aCol,int wordIndex) throws Exception{
if(aType == null){
throw new Exception(aValue + " 没有找到对应的节点类型");
}
......@@ -62,6 +70,7 @@ public class ExpressNode implements IDataNode{
}
this.line = aLine;
this.col =aCol;
this.wordIndex = wordIndex;
}
public boolean isTypeEqualsOrChild(String parent){
......
......@@ -234,7 +234,7 @@ public class ExpressParse {
point = point + 1;
}
}
result.add(new ExpressNode(tempType,tempWord,orgiValue,objectValue,treeNodeType,tmpWordObject.line,tmpWordObject.col));
result.add(new ExpressNode(tempType,tempWord,orgiValue,objectValue,treeNodeType,tmpWordObject.line,tmpWordObject.col,tmpWordObject.index));
treeNodeType = null;
objectValue = null;
orgiValue = null;
......@@ -303,6 +303,11 @@ public class ExpressParse {
}
}
public ExpressNode parse(ExpressPackage rootExpressPackage,String express,boolean isTrace,Map<String,String> selfDefineClass) throws Exception{
Word[] words = splitWords(rootExpressPackage,express,isTrace,selfDefineClass);
return parse(rootExpressPackage,words,express,isTrace,selfDefineClass);
}
public Word[] splitWords(ExpressPackage rootExpressPackage,String express,boolean isTrace,Map<String,String> selfDefineClass) throws Exception{
Word[] words = WordSplit.parse(this.nodeTypeManager.splitWord,express);
if(isTrace == true && log.isDebugEnabled()){
log.debug("执行的表达式:" + express);
......@@ -318,6 +323,13 @@ public class ExpressParse {
selfDefineClass = new HashMap<String,String>();
}
fetchSelfDefineClass(words,selfDefineClass);
for(int i=0;i<words.length;i++){
words[i].index=i;
}
return words;
}
public ExpressNode parse(ExpressPackage rootExpressPackage,Word[] words ,String express,boolean isTrace,Map<String,String> selfDefineClass) throws Exception{
List<ExpressNode> tempList = this.transferWord2ExpressNode(rootExpressPackage,words,selfDefineClass,true);
if(isTrace == true && log.isDebugEnabled()){
......
......@@ -3,7 +3,7 @@ package com.ql.util.express.parse;
public class KeyWordDefine4Java {
public String[] splitWord={
"~","&","|","<<", ">>",//位操作
"^","~","&","|","<<", ">>",// 位操作
"+", "-","*", "/", "%","++", "--",//四则运算:
".",",",":",";","(", ")", "{", "}", "[", "]","?",//分隔符号
"!","<", ">", "<=", ">=", "==","!=","&&","||",//Boolean运算符号
......@@ -20,11 +20,12 @@ public class KeyWordDefine4Java {
public String[] nodeTypeDefines = new String[] {
"ID:TYPE=WORDDEF",
"EOF:TYPE=WORDDEF",
"FUNCTION_NAME:TYPE=WORDDEF",
"FUNCTION_NAME:TYPE=WORDDEF",
"FUNCTION_DEFINE:TYPE=WORDDEF",
"LEFT_BRACKET:TYPE=WORDDEF,DEFINE=(",
"RIGHT_BRACKET:TYPE=WORDDEF,DEFINE=)",
"XOR:TYPE=WORDDEF,DEFINE=^",
"MAYBE:TYPE=WORDDEF,DEFINE=|",
"OR:TYPE=WORDDEF,DEFINE=||",
"LEFT_COMMENT:TYPE=WORDDEF,DEFINE=/**",
......@@ -48,15 +49,15 @@ public class KeyWordDefine4Java {
"CHILD_EXPRESS:TYPE=EXPRESS,DEFINE=LEFT_BRACKET->CHILD_EXPRESS^$(RIGHT_BRACKET~|(EXPRESS$(,~$EXPRESS)*$RIGHT_BRACKET~))",
"[]:TYPE=EXPRESS,DEFINE=[~$EXPRESS*$]~#[]",
"OP_LEVEL1:TYPE=OPERATOR,DEFINE=~|!",
"OP_LEVEL2:TYPE=OPERATOR,DEFINE=++|--",
"OP_LEVEL3:TYPE=OPERATOR,DEFINE=&|MAYBE|<<|>>",
"OP_LEVEL4:TYPE=OPERATOR,DEFINE=*|/|mod|%",
"OP_LEVEL5:TYPE=OPERATOR,DEFINE=+|-",
"OP_LEVEL6:TYPE=OPERATOR,DEFINE=in|like",
"OP_LEVEL1:TYPE=OPERATOR,DEFINE=~|!",
"OP_LEVEL2:TYPE=OPERATOR,DEFINE=++|--",
"OP_LEVEL3:TYPE=OPERATOR,DEFINE=&|MAYBE|XOR|<<|>>",
"OP_LEVEL4:TYPE=OPERATOR,DEFINE=*|/|mod|%",
"OP_LEVEL5:TYPE=OPERATOR,DEFINE=+|-",
"OP_LEVEL6:TYPE=OPERATOR,DEFINE=in|like",
"OP_LEVEL7:TYPE=OPERATOR,DEFINE=>|>=|<|<=|==|!=",
"OP_LEVEL8:TYPE=OPERATOR,DEFINE=&&",
"OP_LEVEL9:TYPE=OPERATOR,DEFINE=OR|nor",
"OP_LEVEL9:TYPE=OPERATOR,DEFINE=OR|nor",
"OP_LIST:TYPE=GROUP,DEFINE=OP_LEVEL1|OP_LEVEL2|OP_LEVEL3|OP_LEVEL4|OP_LEVEL5|OP_LEVEL6|OP_LEVEL7|OP_LEVEL8|OP_LEVEL9|=|LEFT_BRACKET|RIGHT_BRACKET|[|]|{|}",
......@@ -127,14 +128,14 @@ public class KeyWordDefine4Java {
"STATEMENT:TYPE=STATEMENT,DEFINE=COMMENT|STAT_IFELSE|STAT_IF|STAT_IFELSE_JAVA|STAT_IF_JAVA|STAT_FOR|STAT_MACRO|STAT_FUNCTION|STAT_CLASS|STAT_SEMICOLON",
"STAT_BLOCK:TYPE=BLOCK,DEFINE={->STAT_BLOCK^$STAT_LIST$}~",
"STAT_LIST:TYPE=BLOCK,DEFINE=(STAT_BLOCK|STATEMENT)*",
"STAT_LIST:TYPE=BLOCK,DEFINE=(STAT_BLOCK|STATEMENT)*",
"PROGRAM:TYPE=BLOCK,DEFINE=STAT_LIST#STAT_BLOCK",
};
public String[][] instructionFacotryMapping = {
{"~,!,++,--,&,|,<<,>>,*,/,mod,%,+,-,like,>,>=,<,<=,==,!=,&&,||,nor,=,return,alias,exportAlias,ARRAY_CALL","com.ql.util.express.instruction.OperatorInstructionFactory"},
{"^,~,!,++,--,&,|,<<,>>,*,/,mod,%,+,-,like,>,>=,<,<=,==,!=,&&,||,nor,=,return,alias,exportAlias,ARRAY_CALL","com.ql.util.express.instruction.OperatorInstructionFactory"},
{"in","com.ql.util.express.instruction.InInstructionFactory"},
{"exportDef","com.ql.util.express.instruction.OperatorInstructionFactory"},
{"ID","com.ql.util.express.instruction.LoadAttrInstructionFactory"},
{"ID","com.ql.util.express.instruction.LoadAttrInstructionFactory"},
{"CONST,CONST_CLASS","com.ql.util.express.instruction.ConstDataInstructionFactory"},
{"[],STAT_SEMICOLON,STAT_BLOCK,FUNCTION_DEFINE,CHILD_EXPRESS","com.ql.util.express.instruction.BlockInstructionFactory"},
{"def","com.ql.util.express.instruction.DefineInstructionFactory"},
......
......@@ -5,6 +5,7 @@ public class Word {
public String word;
public int line;
public int col;
public int index;
public Word(String aWord,int aLine,int aCol){
this.word = aWord;
this.line = aLine;
......
package com.ql.util.express.rule;
/**
* Created by tianqiao on 16/12/12.
*/
public class Action extends Node{
public Action(String text) {
this.setText(text);
}
}
package com.ql.util.express.rule;
import org.apache.commons.lang.StringUtils;
import java.util.ArrayList;
import java.util.List;
/**
* Created by tianqiao on 16/12/6.
*/
public class Condition extends Node{
private boolean prior = false;
private ConditionType type;
private List<Condition> children;
public Condition(ConditionType type) {
this.type = type;
}
public Condition() {
}
public boolean isPrior() {
return prior;
}
public void setPrior(boolean prior) {
this.prior = prior;
}
public ConditionType getType() {
return type;
}
public void setType(ConditionType type) {
this.type = type;
}
public List<Condition> getChildren() {
return children;
}
public void setChildren(List<Condition> children) {
this.children = children;
}
public void addChild(Condition child) {
if(this.children==null){
this.children = new ArrayList<Condition>();
}
this.children.add(child);
}
public String toString()
{
if(this.type == ConditionType.Leaf){
return priorString(this.getText());
} else if(this.type == ConditionType.And){
return priorString(StringUtils.join(this.getChildren()," and "));
} else if(this.type == ConditionType.Or){
return priorString(StringUtils.join(this.getChildren()," or "));
}
return null;
}
private String priorString(String orig)
{
if(this.isPrior()){
return new StringBuilder("(").append(orig).append(")").toString();
}
return orig;
}
}
package com.ql.util.express.rule;
/**
* Created by tianqiao on 16/12/6.
*/
public enum ConditionType {
And,
Or,
Leaf
}
package com.ql.util.express.rule;
/**
* Created by tianqiao on 16/12/12.
*/
public class Node {
private Integer nodeId;
private Integer level;
private String text;
public Integer getNodeId() {
return nodeId;
}
public void setNodeId(Integer nodeId) {
this.nodeId = nodeId;
}
public Integer getLevel() {
return level;
}
public void setLevel(Integer level) {
this.level = level;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
package com.ql.util.express.rule;
import java.util.ArrayList;
import java.util.List;
/**
* Created by tianqiao on 16/12/8.
*/
public class Rule extends Node{
private String code;
private String name;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private List<RuleCase> ruleCases = new ArrayList<RuleCase>();
public List<RuleCase> getRuleCases() {
return ruleCases;
}
public void addRuleCases(RuleCase ruleCase) {
this.ruleCases.add(ruleCase);
}
public String toQl()
{
StringBuilder sb = new StringBuilder();
boolean first = true;
for(RuleCase oneCase : ruleCases){
if(first){
sb.append(this.ruleCaseToScript("ql",oneCase));
first = false;
}else{
sb.append("else ").append(this.ruleCaseToScript("ql",oneCase));
}
}
return sb.toString();
}
public String toSkylight()
{
StringBuilder sb = new StringBuilder();
if(code!=null && name!=null){
sb.append(String.format("rule '%s'\nname '%s'\n",code,name));
}
boolean first = true;
for(RuleCase oneCase : ruleCases){
if(first){
sb.append(this.ruleCaseToScript("skylight",oneCase));
first = false;
}else{
sb.append(this.ruleCaseToScript("skylight",oneCase));
}
}
return sb.toString();
}
public String toTree()
{
StringBuilder sb = new StringBuilder();
sb.append(String.format("Rule:%s(%s),%d\n",code,name,getNodeId()));
for(RuleCase ruleCase : ruleCases){
printLevel(ruleCase.getLevel(),sb);
sb.append(String.format("Case:%s,%d\n","case",ruleCase.getNodeId()));
printConitionTree(ruleCase.getCondition(),sb);
for(Action action:ruleCase.getActions()){
printLevel(action.getLevel(),sb);
sb.append(String.format("Action:%s,%d\n",action.getText(),action.getNodeId()));
}
}
return sb.toString();
}
public void printLevel(int level,StringBuilder sb)
{
for(int i=0;i<level;i++){
sb.append("======");
}
}
private void printConitionTree(Condition root,StringBuilder sb)
{
printLevel(root.getLevel(),sb);
sb.append(String.format("Condition:%s,%d\n",root.getText(),root.getNodeId()));
if(root.getChildren()!=null) {
for (Condition sub : root.getChildren()) {
printConitionTree(sub,sb);
}
}
}
private String ruleCaseToScript(String scriptType, RuleCase ruleCase)
{
StringBuilder sb = new StringBuilder();
if(scriptType.equals("ql")) {
for(Action action : ruleCase.getActions()){
sb.append(action.getText()).append(";\n");
}
return String.format("if(%s)\n{\n%s}", ruleCase.getCondition().toString(), sb);
}else if(scriptType.equals("skylight")){
for(Action action : ruleCase.getActions()){
sb.append(action.getText()).append("\n");
}
return String.format("when %s\nthen %s", ruleCase.getCondition().toString(), sb);
}
return null;
}
}
package com.ql.util.express.rule;
import java.util.List;
/**
* Created by tianqiao on 16/12/6.
*/
public class RuleCase extends Node{
private List<Action> actions;
private Condition condition;
public RuleCase(Condition condition,List<Action> actions) {
this.actions = actions;
this.condition = condition;
}
public List<Action> getActions() {
return actions;
}
public void setActions(List<Action> actions) {
this.actions = actions;
}
public Condition getCondition() {
return condition;
}
public void setCondition(Condition condition) {
this.condition = condition;
}
}
package com.ql.util.express.rule;
import com.ql.util.express.ExpressRunner;
import com.ql.util.express.IExpressContext;
import com.ql.util.express.parse.ExpressNode;
import com.ql.util.express.parse.Word;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* Created by tianqiao on 16/12/8.
*/
public class RuleManager {
private static final Log log = LogFactory.getLog(RuleManager.class);
public static RuleResult executeRule(ExpressRunner runner,Rule rule, IExpressContext<String,Object> context, boolean isCache, boolean isTrace)
{
RuleResult result = new RuleResult();
result.setRule(rule);
Map<String, Boolean> traceMap = new LinkedHashMap<String, Boolean>();
result.setTraceMap(traceMap);
Object actionResult = null;
for(RuleCase ruleCase : rule.getRuleCases())
{
Condition root = ruleCase.getCondition();
Boolean conditionResult = calculateCondition(runner,context,root,traceMap,isCache,isTrace,result);
if(conditionResult==true){
for(Action action :ruleCase.getActions()){
try {
traceMap.put(action.getNodeId()+"",true);
actionResult = runner.execute(action.getText(),context,null,isCache,isTrace);
} catch (Exception e) {
result.setHasException(true);
log.error("执行action出错:action=\n"+action.getText(),e);
actionResult = null;
}
}
break;
}
}
result.setResult(actionResult);
return result;
}
private static Boolean calculateCondition(ExpressRunner runner, IExpressContext<String, Object> context, Condition root, Map<String, Boolean> traceMap, boolean isCache, boolean isTrace, RuleResult result)
{
boolean isShortCircuit = runner.isShortCircuit();
String key = root.getNodeId()+"";
if(root.getType()==ConditionType.Leaf){
String text = root.getText();
try {
Boolean r = (Boolean) runner.execute(text,context,null,isCache,isTrace);
traceMap.put(key,r);
return r;
} catch (Exception e) {
result.setHasException(true);
log.error("计算condition出错:condition=\n"+text,e);
traceMap.put(key,false);
return false;
}
}
Boolean unionLogicResult = null;
ConditionType rootType = root.getType();
if(root.getChildren()!=null) {
for (Condition sub : root.getChildren()) {
Boolean subResult = calculateCondition(runner,context,sub,traceMap,isCache,isTrace, result);
if(unionLogicResult==null){
unionLogicResult = subResult;
}else{
if (rootType == ConditionType.And) {
unionLogicResult = unionLogicResult && subResult;
}else if (rootType == ConditionType.Or) {
unionLogicResult = unionLogicResult || subResult;
}
}
if(isShortCircuit) {
if (rootType == ConditionType.And) {
if(unionLogicResult==false){
break;
}
}
if (rootType == ConditionType.Or) {
if(unionLogicResult==true){
break;
}
}
}
}
}
traceMap.put(key,unionLogicResult);
return unionLogicResult;
}
public static Rule createRule(ExpressNode root, Word[] words) {
ExpressNode ifNode = getIfRootNode(root);
if (ifNode != null) {
Rule rule = new Rule();
addRuleCaseByExpress(ifNode, rule, words);
tagRuleConitionId(rule);
return rule;
}
return null;
}
private static Integer tagRuleConitionId(Rule rule) {
Integer nodeId = 0;
Integer level = 0;
rule.setNodeId(nodeId++);
rule.setLevel(level++);
for(RuleCase ruleCase: rule.getRuleCases()){
ruleCase.setNodeId(nodeId++);
ruleCase.setLevel(level);
Condition root = ruleCase.getCondition();
nodeId = tagConditionNode(root,nodeId,level+1);
List<Action>actions = ruleCase.getActions();
for(Action action:actions){
action.setLevel(level+1);
action.setNodeId(nodeId++);
}
}
return nodeId;
}
private static Integer tagConditionNode(Condition root,Integer nodeId,Integer level) {
root.setLevel(level);
root.setNodeId(nodeId++);
if(root.getChildren()!=null) {
for (Condition sub : root.getChildren()) {
nodeId = tagConditionNode(sub, nodeId,level+1);
}
}
return nodeId;
}
private static void addRuleCaseByExpress(ExpressNode ifNode, Rule rule, Word[] words) {
ExpressNode[] children = ifNode.getChildren();
ExpressNode condtion = null;
ExpressNode action = null;
ExpressNode nextCase = null;
//[0]ConditionNode
int point = 0;
ExpressNode first = children[point];
if (isNodeType(first, "CHILD_EXPRESS")) {
condtion = first.getChildren()[0];
} else {
condtion = first;
}
point++;
//[1]"then"
if (isNodeType(children[point], "then")) {
point++;
}
//[2]ActionNode
action = children[point];
point++;
//[3]"else"
if (point < children.length && isNodeType(children[point], "else")) {
point++;
//[4]IfNode
if (point < children.length && isNodeType(children[point], "if")) {
nextCase = children[point];
}
}
rule.addRuleCases(createRuleCase(condtion, action, words));
if (nextCase != null) {
addRuleCaseByExpress(nextCase, rule, words);
}
}
private static ExpressNode getIfRootNode(ExpressNode parent) {
if (isNodeType(parent, "if")) {
return parent;
}
ExpressNode[] children = parent.getChildren();
if (children != null && children.length > 0) {
for (ExpressNode child : children) {
if (getIfRootNode(child) != null) {
return child;
}
}
}
return null;
}
private static RuleCase createRuleCase(ExpressNode condition, ExpressNode action, Word[] words) {
Condition ruleCondition = new Condition();
transferCondition(condition, ruleCondition, words);
List<Action> actions = new ArrayList<Action>();
if (isNodeType(action, "STAT_BLOCK")) {
ExpressNode[] children = action.getChildren();
for (ExpressNode actionChild : children) {
actions.add(new Action(makeActionString(actionChild,words)));
}
} else {
actions.add(new Action(makeActionString(action,words)));
}
RuleCase ruleCase = new RuleCase(ruleCondition, actions);
return ruleCase;
}
private static void transferCondition(ExpressNode express, Condition condition, Word[] words) {
if (isNodeType(express, "&&")) {
condition.setType(ConditionType.And);
condition.setText("and");
ExpressNode[] children = express.getChildren();
for (ExpressNode child : children) {
Condition subCondition = new Condition();
condition.addChild(subCondition);
transferCondition(child, subCondition, words);
}
} else if (isNodeType(express, "||")) {
condition.setType(ConditionType.Or);
condition.setText("or");
ExpressNode[] children = express.getChildren();
for (ExpressNode child : children) {
Condition subCondition = new Condition();
condition.addChild(subCondition);
transferCondition(child, subCondition, words);
}
} else {
if (isNodeType(express, "CHILD_EXPRESS")||isNodeType(express, "STAT_BLOCK")||isNodeType(express, "STAT_SEMICOLON")) { //注意括号的情况
ExpressNode realExpress = express.getChildren()[0];
condition.setPrior(true);
transferCondition(realExpress, condition, words);
} else {
condition.setType(ConditionType.Leaf);
condition.setText(makeCondtionString(express, words));
}
}
}
private static boolean isNodeType(ExpressNode node, String type) {
return node.getNodeType().getName().equals(type);
}
private static String makeActionString(ExpressNode express, Word[] words)
{
int min = getMinNode(express);
int max = getMaxNode(express);
//最后需要匹配一个)括号的问题,另外还有是无参数的情况 function()
while(max+1<words.length && (words[max+1].word.equals(")")||words[max+1].word.equals("("))){
max++;
}
if(min<0) min = 0;
if(max>=words.length) max = words.length-1;
StringBuilder result = new StringBuilder();
int balance = 0;//小括号的相互匹配数量
for(int i=min;i<=max;i++)
{
if(words[i].word.equals("(")){
balance++;
}else if(words[i].word.equals(")")){
balance--;
}
if(balance<0){
balance++;//当前字符不合并,恢复成0,用于最终的判断
break;
}
result.append(words[i].word);
if(words[i].word.equals("return")){
result.append(" ");
}
}
if(balance!=0){
System.out.println(result);
throw new RuntimeException("括号匹配异常");
}
return result.toString();
}
private static String makeCondtionString(ExpressNode express,Word[] words)
{
int min = getMinNode(express);
int max = getMaxNode(express);
//最后需要匹配一个括号的问题
while(max+1<words.length && (words[max+1].word.equals(")")||words[max+1].word.equals("("))){
max++;
}
if(min<0) min = 0;
if(max>=words.length) max = words.length-1;
StringBuilder result = new StringBuilder();
int balance = 0;//小括号的相互匹配数量
for(int i=min;i<=max;i++)
{
if(words[i].word.equals("(")){
balance++;
}else if(words[i].word.equals(")")){
balance--;
}
if(balance<0){
balance++;//当前字符不合并,恢复成0,用于最终的判断
break;
}
result.append(words[i].word);
}
if(balance!=0){
throw new RuntimeException("括号匹配异常");
}
return result.toString();
}
private static int getMinNode(ExpressNode express)
{
if(express.getChildren()==null||express.getChildren().length==0){
return express.getWordIndex();
}
int wordIndex = express.getWordIndex();
if(express.getChildren()!=null){
for(ExpressNode child : express.getChildren()){
int childIndex = getMinNode(child);
if(wordIndex==-1 || childIndex<wordIndex){
wordIndex = childIndex;
}
}
}
return wordIndex;
}
private static int getMaxNode(ExpressNode express)
{
if(express.getChildren()==null||express.getChildren().length==0){
return express.getWordIndex();
}
int wordIndex = express.getWordIndex();
if(express.getChildren()!=null){
for(ExpressNode child : express.getChildren()){
int childIndex = getMaxNode(child);
if(childIndex>wordIndex){
wordIndex = childIndex;
}
}
}
return wordIndex;
}
public static Condition createCondition(ExpressNode condition, Word[] words) {
Condition ruleCondition = new Condition();
transferCondition(condition, ruleCondition, words);
return ruleCondition;
}
}
package com.ql.util.express.rule;
import java.util.Map;
/**
* Created by tianqiao on 16/12/12.
*/
public class RuleResult {
private boolean hasException = false;
private Rule rule;
private Map<String,Boolean> traceMap;
private Object result;
private String script;
public String getScript() {
return script;
}
public void setScript(String script) {
this.script = script;
}
public boolean isHasException() {
return hasException;
}
public void setHasException(boolean hasException) {
this.hasException = hasException;
}
public Rule getRule() {
return rule;
}
public void setRule(Rule rule) {
this.rule = rule;
}
public Map<String, Boolean> getTraceMap() {
return traceMap;
}
public void setTraceMap(Map<String, Boolean> traceMap) {
this.traceMap = traceMap;
}
public Object getResult() {
return result;
}
public void setResult(Object result) {
this.result = result;
}
}
package com.ql.util.express.bugfix;
import com.ql.util.express.DefaultContext;
import com.ql.util.express.ExpressRunner;
import com.ql.util.express.IExpressContext;
import com.ql.util.express.instruction.op.OperatorIn;
import org.junit.Test;
/**
* Created by tianqiao on 17/6/20.
*/
public class ArrayMapTest {
@Test
public void testMinus() throws Exception{
ExpressRunner runner = new ExpressRunner();
//负数需要加括号来解决,就好比 1+(-1)
String exp = "Map abc = NewMap(1:(-1),2:2); return abc.get(1) + abc.get(2)";
IExpressContext<String, Object> context = new DefaultContext<String, Object>();
Object result = runner.execute(exp,context,null,false,true);
System.out.println(result);
}
}
package com.ql.util.express.bugfix;
import com.ql.util.express.*;
import com.ql.util.express.instruction.op.OperatorBase;
import org.junit.Test;
import java.util.List;
/**
*
* @骆凡
* Created by tianqiao on 17/7/5.
*/
public class ContextMessagePutTest {
class OperatorContextPut extends OperatorBase {
public OperatorContextPut(String aName) {
this.name = aName;
}
@Override
public OperateData executeInner(InstructionSetContext parent, ArraySwap list) throws Exception {
String key = list.get(0).toString();
Object value = list.get(1);
parent.put(key,value);
return null;
}
}
@Test
public void test() throws Exception{
ExpressRunner runner = new ExpressRunner();
OperatorBase op = new OperatorContextPut("contextPut");
runner.addFunction("contextPut",op);
String exp = "contextPut('success','false');contextPut('error','错误信息');contextPut('warning','提醒信息')";
IExpressContext<String, Object> context = new DefaultContext<String, Object>();
context.put("success","true");
Object result = runner.execute(exp,context,null,false,true);
System.out.println(result);
System.out.println(context);
}
}
package com.ql.util.express.bugfix;
import com.ql.util.express.DefaultContext;
import com.ql.util.express.ExpressRunner;
import com.ql.util.express.IExpressContext;
import org.junit.Test;
/**
* Created by tianqiao on 17/6/20.
*/
public class FunctionTest {
@Test
public void testFunction() throws Exception{
ExpressRunner runner = new ExpressRunner();
String exp = "function abc(int a,int b){ return a + b;} return abc(1+100,2*100)";
IExpressContext<String, Object> context = new DefaultContext<String, Object>();
Object result = runner.execute(exp,context,null,false,false);
System.out.println(result);
}
@Test
public void testFunction2() throws Exception{
ExpressRunner runner = new ExpressRunner();
String exp =
"function FAILFUN(Integer errorCode,String message){\n" +
"System.out.println(errorCode+\" \"+message);\n" +
"return NewMap(\"message\":message,\"errorCode\":errorCode,\"success\":false);\n" +
"}\n" +
"FAILFUN(-1,'error')";
IExpressContext<String, Object> context = new DefaultContext<String, Object>();
Object result = runner.execute(exp,context,null,false,false);
System.out.println(result);
}
@Test
public void testFunction3() throws Exception{
ExpressRunner runner = new ExpressRunner();
String funExp =
"function FAILFUN(Integer errorCode,String message){\n" +
"System.out.println(errorCode+\" \"+message);\n" +
"return NewMap(\"message\":message,\"errorCode\":errorCode,\"success\":false);\n" +
"}\n";
runner.loadMutilExpress("",funExp);
String exp = "FAILFUN(-1,'error')";
IExpressContext<String, Object> context = new DefaultContext<String, Object>();
Object result = runner.execute(exp,context,null,false,false);
System.out.println(result);
String exp2 = "FAILFUN(-12,'error')";
IExpressContext<String, Object> context2 = new DefaultContext<String, Object>();
Object result2 = runner.execute(exp2,context2,null,false,false);
System.out.println(result);
}
}
package com.ql.util.express.bugfix;
import com.ql.util.express.DefaultContext;
import com.ql.util.express.ExpressRunner;
import com.ql.util.express.IExpressContext;
import org.junit.Test;
/**
* Created by tianqiao on 17/6/23.
*/
public class ImportClassPath {
@Test
public void test() {
ExpressRunner runner = new ExpressRunner();
String exp ="return new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\").format(new Date())";
IExpressContext<String, Object> context = new DefaultContext<String, Object>();
Object result = null;
try {
result = runner.execute(exp,context,null,false,false);
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void test2() throws Exception {
ExpressRunner runner = new ExpressRunner();
String exp ="return new java.text.SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\").format(new Date())";
IExpressContext<String, Object> context = new DefaultContext<String, Object>();
Object result = null;
result = runner.execute(exp,context,null,false,false);
System.out.println(result);
}
@Test
public void test3() throws Exception {
ExpressRunner runner = new ExpressRunner();
String exp ="import java.text.SimpleDateFormat; return new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\").format(new Date())";
IExpressContext<String, Object> context = new DefaultContext<String, Object>();
Object result = null;
result = runner.execute(exp,context,null,false,false);
System.out.println(result);
}
}
package com.ql.util.express.bugfix;
import com.ql.util.express.DefaultContext;
import com.ql.util.express.ExpressRunner;
import com.ql.util.express.IExpressContext;
import com.ql.util.express.instruction.op.OperatorIn;
import org.junit.Test;
/**
* Created by tianqiao on 17/6/15.
*/
public class InOperatorTest {
@Test
public void testAllByFunction() throws Exception{
ExpressRunner runner = new ExpressRunner();
runner.addOperator("widelyin", new OperatorIn("widelyin") {
@Override
public Object executeInner(Object[] list) throws Exception {
if(list[0]==null){
return false;
}
return super.executeInner(list);
}
});
//注意可以使用 data in (2,3,4) ,但无法使用data widelyin (2,3,4),因为默认addOperator的是二元操作符,
// com.ql.util.express.instruction.InInstructionFactory对语法树做了特殊处理
String exp = "data widelyin [2,3,4]";
IExpressContext<String, Object> context = new DefaultContext<String, Object>();
context.put("data",2);
Object result = runner.execute(exp,context,null,false,true);
System.out.println(result);
}
}
package com.ql.util.express.bugfix;
import com.ql.util.express.DefaultContext;
import com.ql.util.express.ExpressRunner;
import com.ql.util.express.IExpressContext;
import org.junit.Test;
/**
* Created by tianqiao on 17/6/29.
*/
public class LuofanTest {
public class Response
{
}
public static int lenOfAds(Response response)
{
return 1;
}
@Test
public void testDemo() throws Exception{
ExpressRunner runner = new ExpressRunner();
runner.addFunctionOfClassMethod("lenOfAds",LuofanTest.class.getName(),"lenOfAds",new String[]{Response.class.getName()},null);
String exp = "lenOfAds(resp)";
IExpressContext<String, Object> context = new DefaultContext<String, Object>();
context.put("resp",new Response());
Object result = runner.execute(exp,context,null,false,true);
System.out.println(result);
}
}
package com.ql.util.express.bugfix;
import com.ql.util.express.DefaultContext;
import com.ql.util.express.ExpressRunner;
import com.ql.util.express.IExpressContext;
import com.ql.util.express.Operator;
import org.junit.Test;
/**
* Created by tianqiao on 17/3/2.
*/
public class RecursivelyTest {
static ExpressRunner runner = new ExpressRunner();
static ExpressRunner runnerInner = new ExpressRunner();
static{
Operator exeOperator = new Operator() {
@Override
public Object executeInner(Object[] list) throws Exception {
System.out.println("executeInner:r_exeAll");
IExpressContext<String, Object> context = new DefaultContext<String, Object>();
runnerInner.execute("1+2", context, null, false, true);
System.out.println(list[0]);
return null;
}
};
runner.addFunction("r_exeAll",exeOperator );
runnerInner.addFunction("r_exeAll",exeOperator);
}
@Test
public void testAllByFunction() throws Exception{
String exp = "r_exeAll(1,2,3)";
IExpressContext<String, Object> context = new DefaultContext<String, Object>();
runner.execute(exp,context,null,false,true);
}
}
package com.ql.util.express.bugfix;
import com.ql.util.express.ExpressRunner;
import com.ql.util.express.InstructionSet;
import org.junit.Test;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class SerializeTest {
@Test
public void Test() throws Exception {
ExpressRunner runner = new ExpressRunner();
try {
/*
* 添加一个规则方法
* */
runner.addFunctionOfClassMethod("getS", TestExpress.class.getName(),
"getScore", new String[]{TestData.class.getName()}, null);
/*
* 添加一个规则宏
* */
runner.addMacro("获取分数宏", "getS(testInfo)");
} catch (Exception e) {
e.printStackTrace();
}
byte[] bytes1 = null;
byte[] bytes2 = null;
byte[] bytes3 = null;
String express1 = "获取分数宏";
String express2 = "getS(testInfo)";
String express3 = "int score = getS(testInfo)";
/*
* 根据两种不同的规则文本获取指令集
* */
InstructionSet is1 = runner.parseInstructionSet(express1);
InstructionSet is2 = runner.parseInstructionSet(express2);
InstructionSet is3 = runner.parseInstructionSet(express3);
/*
* 对指令集进行序列化
* */
testSerialize(is1);
testSerialize(is2);
testSerialize(is3);
}
private void testSerialize(InstructionSet is)
{
int len = is.getInstructionLength();
for(int i=0;i<len;i++){
System.out.println(is.getInstruction(i));
encode(is.getInstruction(i));
}
}
private byte[] encode(Object object) {
byte[] result = null;
ByteArrayOutputStream baos = null;
ObjectOutputStream oos = null;
try {
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(object);
result = baos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (oos != null) {
oos.close();
baos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
public class TestExpress implements Serializable{
public int getScore(TestData testInfo) {
if (!"None".equals(testInfo.getName()))
return 600;
return 300;
}
}
public class TestData {
private String name = "None";
public TestData() {
}
TestData(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
}
package com.ql.util.express.bugfix;
import com.ql.util.express.DefaultContext;
import com.ql.util.express.ExpressRunner;
import com.ql.util.express.IExpressContext;
import org.junit.Test;
/**
* Created by tianqiao on 17/7/5.
*/
public class StringTest {
@Test
public void testFunction() throws Exception{
ExpressRunner runner = new ExpressRunner();
String exp = "a = \"11111,2222\";p = a.split(\",\");";
System.out.println(exp);
IExpressContext<String, Object> context = new DefaultContext<String, Object>();
Object result = runner.execute(exp,context,null,false,false);
System.out.println(result);
}
}
package com.ql.util.express.bugfix;
import com.ql.util.express.DefaultContext;
import com.ql.util.express.ExpressRunner;
import com.ql.util.express.IExpressContext;
import org.junit.Test;
/**
* 测试重载适配性的case
* Created by tianqiao on 17/6/20.
*/
public class TestAdjustTypes {
public static TestAdjustTypes instance = new TestAdjustTypes();
public Integer test(Integer a){
System.out.println("invoke Integer");
return a;
}
public String test(String a){
System.out.println("invoke String");
return a;
}
public Object test(Object ... a){
System.out.println("invoke dynamic params");
return a[a.length-1];
}
@Test
public void testDemo() throws Exception{
ExpressRunner runner = new ExpressRunner();
runner.addFunctionOfServiceMethod("test",instance,"test",new Class[]{Integer.class},null);
runner.addFunctionOfServiceMethod("testString",instance,"test",new Class[]{String.class},null);
String exp = "test(1) +test(1) + testString('aaaa')";
IExpressContext<String, Object> context = new DefaultContext<String, Object>();
Object result = runner.execute(exp,context,null,false,true);
System.out.println(result);
}
@Test
public void testDemo2() throws Exception{
ExpressRunner runner = new ExpressRunner();
IExpressContext<String, Object> context = new DefaultContext<String, Object>();
context.put("testAdjustTypes",instance);
String exp = "testAdjustTypes.test(1) + testAdjustTypes.test(1) + testAdjustTypes.test('aaaa')";
Object result = runner.execute(exp,context,null,false,true);
System.out.println(result);
}
@Test
public void testDemo3() throws Exception{
ExpressRunner runner = new ExpressRunner();
IExpressContext<String, Object> context = new DefaultContext<String, Object>();
context.put("testAdjustTypes",instance);
String exp = "testAdjustTypes.test(1) + testAdjustTypes.test(1) + testAdjustTypes.test('aaaa')+ testAdjustTypes.test('aaaa','bbbbb')";
Object result = runner.execute(exp,context,null,false,true);
System.out.println(result);
}
}
package com.ql.util.express.bugfix;
import com.ql.util.express.DefaultContext;
import com.ql.util.express.ExpressRunner;
import com.ql.util.express.IExpressContext;
import org.junit.Test;
/**
* Created by tianqiao on 17/6/20.
*/
public class ThrowExceptionTest {
public String testParseLong(String a) throws Exception {
try {
return Long.valueOf(a).toString();
}catch (Exception e) {
throw new Exception("Exception happened!",e);
}
}
public String test(String a) throws Exception {
try {
return testParseLong(a);
}catch (Exception e) {
throw new Exception("Exception happened!",e);
}
}
@Test
public void testException()
{
try {
ExpressRunner runner = new ExpressRunner();
String exp = "a = new com.ql.util.express.bugfix.ThrowExceptionTest();a.testParseLong('11112LL')";
IExpressContext<String, Object> context = new DefaultContext<String, Object>();
Object result = runner.execute(exp, context, null, false, false);
System.out.println(result);
}catch (Exception e){
e.printStackTrace();
e.getCause().printStackTrace();
e.getCause().getCause().printStackTrace();
}
}
}
package com.ql.util.express.example;
import com.ql.util.express.DefaultContext;
import com.ql.util.express.ExpressRunner;
import com.ql.util.express.IExpressContext;
import com.ql.util.express.Operator;
import org.junit.Test;
/**
* Created by tianqiao on 17/6/4.
*/
public class ArgumentTypeMismatchTest {
private static ArgumentTypeMismatchTest singleton = new ArgumentTypeMismatchTest();
public void functionABC(Long a,Integer b,String c)
{
System.out.println("functionABC");
}
@Test
public void test1() throws Exception {
ExpressRunner runner = new ExpressRunner();
runner.addFunctionOfServiceMethod("abc", singleton,"functionABC",new Class[]{Long.class,Integer.class,String.class},null);
String exp = "abc(a,b,c)";
IExpressContext<String, Object> context = new DefaultContext<String, Object>();
context.put("a","1");
context.put("b","2");
context.put("c","3");
try {
runner.execute(exp, context, null, false, false);
}catch (Exception e){
e.printStackTrace();
}
}
@Test
public void test2() throws Exception {
ExpressRunner runner = new ExpressRunner();
runner.addFunction("abc", new Operator() {
@Override
public Object executeInner(Object[] list) throws Exception {
Long paramA = Long.valueOf(list[0].toString());
Integer paramB = Integer.valueOf(list[1].toString());
String paramC = list[2].toString();
singleton.functionABC(paramA,paramB,paramC);
return null;
}
});
String exp = "abc(a,b,c)";
IExpressContext<String, Object> context = new DefaultContext<String, Object>();
context.put("a","1");
context.put("b","2");
context.put("c","3");
try {
runner.execute(exp, context, null, false, false);
}catch (Exception e){
e.printStackTrace();
}
System.out.print("test ok!");
}
}
package com.ql.util.express.rule;
import com.ql.util.express.ExpressRunner;
import org.junit.Test;
/**
* Created by tianqiao on 16/12/21.
*/
public class RuleConditionTest {
@Test
public void test() throws Exception {
ExpressRunner runner = new ExpressRunner();
parseRule("max(metric1,30) < 20 and min(metric2,40) > 30",runner);
}
private void parseRule(String s, ExpressRunner runner) throws Exception {
Condition condition = runner.parseContition(s);
printCondition(condition);
}
private void printCondition(Condition root)
{
if(root.getChildren()==null){
System.out.println(root);
return;
}
for(Condition child : root.getChildren()){
printCondition(child);
}
}
}
package com.ql.util.express.rule;
import com.ql.util.express.ExpressRunner;
import org.junit.Test;
/**
* Created by tianqiao on 16/12/21.
*/
public class RuleParseTest {
@Test
public void test() throws Exception {
ExpressRunner runner = new ExpressRunner();
parseRule("rule 'RULE_FEATURESET_BOOK_TOP_CAT_FEATURE' name '书籍类目增加特征topCategoryId'\n" +
"when inCategory.mainCategory.categoryId == 33\n" +
"then add(inItem.features,'topCategoryId',inCategory.mainCategory.categoryId.cast2String());\n" +
"when inCategory.mainCategory.categoryId != 33\n" +
"then del(inItem.features,'topCategoryId');",runner);
}
private void parseRule(String s, ExpressRunner runner) throws Exception {
Rule rule = runner.parseRule(s);
System.out.println(rule.toSkylight());
System.out.println(rule.toTree());
}
}
package com.ql.util.express.rule;
import com.ql.util.express.DefaultContext;
import com.ql.util.express.ExpressRunner;
import com.ql.util.express.Operator;
import org.junit.Test;
import java.lang.reflect.Array;
import java.util.Arrays;
/**
* Created by tianqiao on 16/12/8.
*/
public class RuleTraceTest {
public class Demo
{
private boolean b = true;
public boolean isB() {
return b;
}
public void setB(boolean b) {
this.b = b;
}
}
@Test
public void testSimpleTrace() throws Exception {
ExpressRunner runner = new ExpressRunner();
DefaultContext<String, Object> context = new DefaultContext<String, Object>();
String express= "if(1+2==3 and 4>3 or b>3){return 'OK';}else if(1+2>1){'OK';}";
RuleResult ruleResult= runner.executeRule(express, context, true, false);
System.out.println("express:\n"+express);
System.out.println("result:\n"+ruleResult.getResult());
System.out.println("tree:\n"+ruleResult.getRule().toTree());
System.out.println("trace:\n"+ruleResult.getTraceMap());
}
@Test
public void testTrace() throws Exception {
ExpressRunner runner = new ExpressRunner();
runner.addFunction("f", new Operator() {
@Override
public Object executeInner(Object[] list) throws Exception {
System.out.println(Arrays.toString(list));
return null;
}
});
DefaultContext<String, Object> context = new DefaultContext<String, Object>();
context.put("demo",new Demo());
context.put("a",1);
context.put("b",2);
context.put("c",3);
context.put("boolValue",true);
context.put("trueValue",true);
executeQl("if(demo.b){a=a+b;f();}",context,runner);
executeQl("if(demo.b){a=a+b;return a+(a+(c+(a+b)));}",context,runner);
executeQl("if(1+2==3 and boolValue or b>3){'OK';}",context,runner);
executeQl("if(1+2==3 and (boolValue or b>3)){'OK';}",context,runner);
executeQl("if(1+2==3 and boolValue or b>3){'OK';}else if(1+2==3 and boolValue or b>3){'OK';}",context,runner);
executeQl("when boolValue then return 'ok';",context,runner);
executeQl("when boolValue then 'ok' else when trueValue then 'shit'",context,runner);
executeQl("when 1+2>3 then 'ok' else when 1+2==3 then 'ok2' else when 1+2==3 then 'ok3'",context,runner);
context.put("name","小明");
context.put("age",12);
context.put("score",150);
executeQl("if(name.equals('小明') and age>10 and score>100)\n{\nSystem.out.println('好学生');\nreturn '小明是个好学生';\n}",context,runner);
}
void executeQl(String express,DefaultContext<String, Object> context,ExpressRunner runner) throws Exception {
RuleResult ruleResult= runner.executeRule(express, context, true, false);
System.out.println("express:\n"+express);
System.out.println("result:\n"+ruleResult.getResult());
System.out.println("tree:\n"+ruleResult.getRule().toTree());
System.out.println("trace:\n"+ruleResult.getTraceMap());
}
}
package com.ql.util.express.test;
import com.ql.util.express.DefaultContext;
import com.ql.util.express.ExpressRunner;
import com.ql.util.express.IExpressContext;
import org.junit.Test;
/**
* Created by tianqiao on 16/12/15.
*/
public class BitTest {
@Test
public void testBit() throws Exception {
assert (~-3 == ~-3L);
IntBit();
LongBit();
}
public void IntBit() throws Exception {
ExpressRunner runner = new ExpressRunner();
IExpressContext<String, Object> context = new DefaultContext<String, Object>();
int num = -10;
context.put("num",num);
testQl("num & 11",num & 11,runner,context);
testQl("num | 11",num | 11,runner,context);
testQl("num ^ 10",num ^ 10,runner,context);
testQl("~num",~ num,runner,context);
testQl("num<<2",num<<2,runner,context);
testQl("num>>2",num>>2,runner,context);
}
public void LongBit() throws Exception {
ExpressRunner runner = new ExpressRunner();
IExpressContext<String, Object> context = new DefaultContext<String, Object>();
long num = -10L;
context.put("num",num);
testQl("num & 11",num & 11,runner,context);
testQl("num | 11",num | 11,runner,context);
testQl("num ^ 10",num ^ 10,runner,context);
testQl("~num",~ num,runner,context);
testQl("num<<2",num<<2,runner,context);
testQl("num>>2",num>>2,runner,context);
}
public void testQl(String express,Object expert,ExpressRunner runner, IExpressContext<String,Object> context) throws Exception {
System.out.print(express);
Object obj = runner.execute(express,context,null,true,false);
System.out.println("="+obj);
assert ((obj==null && expert==null)||obj==expert || obj.equals(expert));
}
}
package com.ql.util.express.test;
import com.ql.util.express.DefaultContext;
import com.ql.util.express.ExpressRunner;
import org.junit.Assert;
import org.junit.Test;
/**
* Created by tianqiao on 16/12/20.
*/
public class DateTest {
@Test
public void testDateCompare() throws Exception {
String express = "a = new Date();b=a;a==b";
DefaultContext<String, Object> context = new DefaultContext<String, Object>();
ExpressRunner runner = new ExpressRunner();
Object r = runner.execute(express,context, null, false,false);
Assert.assertTrue("testDateCompare", (Boolean) r);
}
@Test
public void testDateCompare1() throws Exception {
String express = "a = new Date();for(i=0;i<1000;i++){f=f+i;}b=new Date();a<=b";
DefaultContext<String, Object> context = new DefaultContext<String, Object>();
ExpressRunner runner = new ExpressRunner();
Object r = runner.execute(express,context, null, false,false);
Assert.assertTrue("testDateCompare", (Boolean) r);
}
@Test
public void testDateCompare2() throws Exception {
String express = "a = new Date();for(i=0;i<1000;i++){f=f+i;}b=new Date();b>a";
DefaultContext<String, Object> context = new DefaultContext<String, Object>();
ExpressRunner runner = new ExpressRunner();
Object r = runner.execute(express,context, null, false,false);
Assert.assertTrue("testDateCompare", (Boolean) r);
}
}
package com.ql.util.express.test;
import com.ql.util.express.DefaultContext;
import com.ql.util.express.ExpressRunner;
import org.junit.Assert;
import org.junit.Test;
/**
* Created by tianqiao on 17/9/19.
*/
public class InstanceOfTest {
@Test
public void test() throws Exception{
ExpressRunner runner = new ExpressRunner(false,true);
DefaultContext<String, Object> context = new DefaultContext<String, Object>();
String express ="s='';return s instanceof String";
Object r = runner.execute(express,context, null, false,true);
Assert.assertTrue("InstanceOfTest 出错",r.toString().equals("true"));
System.out.println(r);
express ="s='';return s instanceof Object";
r = runner.execute(express,context, null, false,true);
Assert.assertTrue("InstanceOfTest 出错",r.toString().equals("true"));
System.out.println(r);
}
}
......@@ -9,6 +9,9 @@ public class ObjectBean{
public int getAmount() {
return amount;
}
public int getAmount(int a) {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
......
......@@ -10,7 +10,7 @@ public class ObjectTest {
@Test
public void testABC() throws Exception {
String express = "object.amount*2+object.volume";
ExpressRunner runner = new ExpressRunner();
ExpressRunner runner = new ExpressRunner(false,true);
DefaultContext<String, Object> context = new DefaultContext<String, Object>();
ObjectBean tempObject= new ObjectBean(100,60);
context.put("object", tempObject);
......@@ -19,5 +19,17 @@ public class ObjectTest {
System.out.println(r);
Assert.assertTrue("数据执行错误", r.toString().equals(260) == false);
}
@Test
public void testABC2() throws Exception {
String express = "object.getAmount(1)";
ExpressRunner runner = new ExpressRunner(false,true);
DefaultContext<String, Object> context = new DefaultContext<String, Object>();
ObjectBean tempObject= new ObjectBean(100,60);
context.put("object", tempObject);
Object r = runner.execute(express, context, null, false,
true);
System.out.println(r);
}
}
package com.ql.util.express.test;
import com.ql.util.express.DefaultContext;
import com.ql.util.express.ExpressRunner;
import com.ql.util.express.IExpressContext;
import org.junit.Test;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
* Created by tianqiao on 17/4/1.
*/
public class PrintLineExceptionTest {
@Test
public void testLoadFromFile() throws Exception {
String script = getResourceAsStream("lineTest.ql");
ExpressRunner runner = new ExpressRunner(false, false);
IExpressContext<String, Object> context = new DefaultContext<String, Object>();
try {
Object obj = runner.execute(script, context, null, true, false);
System.out.println(obj);
}catch (Exception e){
e.printStackTrace();
}
}
public static String getResourceAsStream(String path) throws Exception {
InputStream in = Thread.currentThread().getContextClassLoader()
.getResourceAsStream(path);
if (in == null) {
throw new Exception("classLoader中找不到资源文件:" + path);
}
BufferedReader reader = new BufferedReader(new InputStreamReader(in,"utf-8"));
StringBuilder builder = new StringBuilder();
String tmpStr = null;
while ((tmpStr = reader.readLine()) != null) {
builder.append(tmpStr).append("\n");
}
reader.close();
in.close();
return builder.toString();
}
}
......@@ -11,7 +11,7 @@ import java.util.regex.Pattern;
public class SkylightRuleTransferTest {
static Pattern pattern = Pattern.compile("[\\s]+");
static Pattern pattern2 = Pattern.compile("(rule|RULE)[\\s]+[\\S]+[\\s]+(name|NAME)[\\s]+[\\S]+[\\s]+");
static Pattern pattern2 = Pattern.compile("(rule|RULE)[\\s]+([\\S]+)[\\s]+(name|NAME)[\\s]+([\\S]+)[\\s]+");
public class Rule
{
......@@ -26,11 +26,11 @@ public class SkylightRuleTransferTest {
}
private void praseContent() throws Exception {
String[] strs = pattern.split(content);
if(strs.length>5 && (strs[0].equals("rule") || strs[0].equals("RULE")) && (strs[2].equals("name")||strs[2].equals("NAME"))){
this.code = strs[1];
this.name = strs[3];
Matcher matcher =pattern2.matcher(content);
Matcher matcher =pattern2.matcher(content);
if(matcher.find()) {
this.code = matcher.group(2);
this.name = matcher.group(4);
this.ql = matcher.replaceFirst("");
}else{
System.out.println("规则定义不合法");
......
......@@ -36,7 +36,7 @@ public class TestMethodParams {
ExpressRunner runner = new ExpressRunner();
IExpressContext<String,Object> expressContext = new DefaultContext<String,Object>();
runner.addFunctionOfServiceMethod("getTemplate", this, "getTemplate", new Class[]{Object[].class}, null);
runner.addFunctionOfClassMethod("getTemplateStatic", TestMethodParams.class.getName(), "getTemplateStatic", new Class[]{Object.class,String[].class}, null);
//(1)默认的不定参数可以使用数组来代替
Object r = runner.execute("getTemplate([11,'22',33L,true])", expressContext, null,false, false);
System.out.println(r);
......@@ -44,6 +44,8 @@ public class TestMethodParams {
DynamicParamsUtil.supportDynamicParams = true;
r = runner.execute("getTemplate(11,'22',33L,true)", expressContext, null,false, false);
System.out.println(r);
r = runner.execute("getTemplateStatic('22','33','44')", expressContext, null,false, false);
System.out.println(r);
}
//等价于getTemplate(Object[] params)
public Object getTemplate(Object... params) throws Exception{
......@@ -53,6 +55,14 @@ public class TestMethodParams {
}
return result;
}
public static Object getTemplateStatic(Object a,String... params) throws Exception{
String result = "";
for(Object obj:params){
result = result+obj+",";
}
return result;
}
......
......@@ -2,6 +2,7 @@ package com.ql.util.express.test;
import com.ql.util.express.DefaultContext;
import com.ql.util.express.ExpressRunner;
import com.ql.util.express.IExpressContext;
import org.junit.Test;
/**
......@@ -22,5 +23,8 @@ public class TestSet {
express = "abc = [1,2,3]; return abc[1]+abc[2];";
r = runner.execute(express, context, null, false, false);
System.out.println(r);
express = "abc = NewMap(1:(-1),2:2); return abc.get(1) + abc.get(2);";
r = runner.execute(express, context, null, false, false);
System.out.println(r);
}
}
package com.ql.util.express.test.demo;
import java.util.HashMap;
import java.util.Map;
import org.unitils.UnitilsJUnit4;
import org.unitils.spring.annotation.SpringApplicationContext;
import org.unitils.spring.annotation.SpringBeanByName;
@SpringApplicationContext("classpath:spring-express-config.xml")
public class TestQlExpress extends UnitilsJUnit4{
@SpringBeanByName
QlExpressUtil qlExpressUtil;
/**
* 使用qlExpressUtil扩展了QlExpressRunner的expressContext参数,
* 使脚本中可以直接调用spring中的bean
*
* 场景业务逻辑如下:
* ******************************************************************
*
* 用户qlExpress注册一个账号
* 用户qlExpress开了个淘宝店
* 通过自己的苦心经营,星级不断升高,qlExpress不断的期望着能够地店铺升级为商城用户
* 终于有一天他成功了。
*
* ******************************************************************
* @throws Exception
*/
@org.junit.Test
public void testScript() throws Exception{
Map<String, Object> context = new HashMap<String, Object>();
context.put("nick", "qlExpress");
qlExpressUtil.execute("用户A = bizLogicBean.signUser(nick);" +
"bizLogicBean.openShop(用户A );" +
"for(;; bizLogicBean.isShopOpening(用户A ) && !bizLogicBean.upgradeShop(用户A )){bizLogicBean.addScore(用户A );}",
context);
}
/**
*
* 使用预先定义的函数,脚本即逻辑:
* ******************************************************************
*
* "用户A = 注册用户(nick);" +
* "开店(用户A);" +
* "for(;;店铺营业中(用户A) && !店铺升级(用户A)){星级自增(用户A);}
*
* ******************************************************************
* @throws Exception
*/
@org.junit.Test
public void testDeclareMethodScript() throws Exception{
Map<String, Object> context = new HashMap<String, Object>();
context.put("nick", "qlExpress");
qlExpressUtil.execute("用户A = 注册用户(nick);" +
"开店(用户A);" +
"for(;;店铺营业中(用户A) && !店铺升级(用户A)){星级自增(用户A);}",
context);
}
}
package com.ql.util.express.test.demo.biz;
public class BizLogicBean {
/**
* 注册新用户
* @param nick
* @return
*/
public UserDO signUser(String nick){
UserDO user = new UserDO();
user.setNick(nick);
user.setScore(0L);
user.setShopOpen(false);
user.setShopType("no_shop");
System.out.println("创建用户成功:"+user);
return user;
}
/**
* 用户店铺激活
* @param user
*/
public void openShop(UserDO user){
user.setShopOpen(true);
user.setShopType("c2c");
System.out.println("店铺已经激活:"+user);
user.setShopOpen(true);
}
/**
* 用户店铺关闭
* @param user
*/
public void closeShop(UserDO user){
user.setShopOpen(false);
System.out.println("店铺已经关闭:"+user);
user.setShopOpen(false);
}
/**
* 用户星级+1
* @param user
*/
public void addScore(UserDO user){
user.setScore(user.getScore()+1);
System.out.println("用户星级 +1 :"+user);
}
public boolean isShopOpening(UserDO user){
if(user.isShopOpen()){
System.out.println("当前店铺为营业状态.");
return true;
}
System.out.println("当前店铺为关闭状态.");
return false;
}
/**
* 店铺升级
* @param user
* @return
*/
public boolean upgradeShop(UserDO user){
if(user.getShopType().equals("b2c")){
System.out.println("您已经是B商家,不用升级了.");
return false;
}
if(user.getScore().longValue()>5L){
user.setShopType("b2c");
System.out.println("成功升级为B商家:"+user);
return true;
}else{
System.out.println("需要5星级以上卖家,你现在才"+user.getScore()+"星级,再接再厉哦!");
return false;
}
}
public void showShop(UserDO user){
System.out.println(user);
}
}
package com.ql.util.express.test.demo.biz;
public class UserDO {
/**
* 用户昵称
*/
private String nick;
/**
* 开店状态
*/
private boolean shopOpen;
/**
* 星级
*/
private Long score;
/**
* 店铺类型:c2c,b2c
*/
private String shopType;
public String getNick() {
return nick;
}
public void setNick(String nick) {
this.nick = nick;
}
public Long getScore() {
return score;
}
public void setScore(Long score) {
this.score = score;
}
public boolean isShopOpen() {
return shopOpen;
}
public void setShopOpen(boolean shopOpen) {
this.shopOpen = shopOpen;
}
public String getShopType() {
return shopType;
}
public void setShopType(String shopType) {
this.shopType = shopType;
}
public String toString(){
StringBuffer sb = new StringBuffer("用户信息:");
sb.append("\t\t昵称: ").append(nick);
if(shopOpen){
sb.append("\t\t店铺状态: 营业中");
}else{
sb.append("\t\t店铺状态: 关闭中");
}
sb.append("\t\t卖家星级: ").append(score);
sb.append("\t\t店铺类型: ").append(shopType);
return sb.toString();
}
}
package com.ql.util.express.test.spring;
import java.util.Date;
/**
* Created by tianqiao on 17/3/8.
*/
public class BizLogicBean {
public UserDO getUserInfo(String nick)
{
if(nick.equals("小王")) {
UserDO userDO = new UserDO();
userDO.setNick(nick);
userDO.setGmtCreate(new Date());
userDO.setUserId(10086L);
userDO.setPosition("salesman");
userDO.setSalary(5000.0);
return userDO;
}else if(nick.equals("马总")) {
UserDO userDO = new UserDO();
userDO.setNick(nick);
userDO.setGmtCreate(new Date());
userDO.setUserId(1L);
userDO.setPosition("boss");
userDO.setSalary(999999999999.0);
return userDO;
}
return null;
}
}
package com.ql.util.express.test.demo;
package com.ql.util.express.test.spring;
import java.util.HashMap;
import java.util.Map;
import com.ql.util.express.IExpressContext;
import org.springframework.context.ApplicationContext;
import com.ql.util.express.IExpressContext;
import java.util.HashMap;
import java.util.Map;
@SuppressWarnings("serial")
public class QLExpressContext extends HashMap<String, Object> implements
......@@ -17,7 +17,7 @@ public class QLExpressContext extends HashMap<String, Object> implements
}
public QLExpressContext(Map<String, Object> aProperties,
ApplicationContext aContext) {
ApplicationContext aContext) {
super(aProperties);
this.context = aContext;
}
......@@ -41,9 +41,6 @@ public class QLExpressContext extends HashMap<String, Object> implements
}
public Object put(String name, Object object) {
if (name.equalsIgnoreCase("myDbData")) {
throw new RuntimeException("没有实现");
}
return super.put(name, object);
}
......
package com.ql.util.express.test.demo;
import java.util.Map;
package com.ql.util.express.test.spring;
import com.ql.util.express.ExpressRunner;
import com.ql.util.express.IExpressContext;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import com.ql.util.express.ExpressRunner;
import com.ql.util.express.IExpressContext;
import java.util.Map;
/**
* (1)打通了spring容器,通过扩展IExpressContext->QLExpressContext
* 获取本地变量的时候,可以获取到spring的bean
* (2)在runner初始化的时候,使用了函数映射功能:addFunctionOfServiceMethod
* (3)在runner初始化的时候,使用了代码映射功能:addMacro
*/
public class QlExpressUtil implements ApplicationContextAware {
private static ExpressRunner runner;
......@@ -32,21 +37,9 @@ public class QlExpressUtil implements ApplicationContextAware {
initRunner(runner);
IExpressContext expressContext = new QLExpressContext(context,
applicationContext);
statement = initStatement(statement);
return runner.execute(statement, expressContext, null, true, false);
}
/**
* 在此处把一些中文符号替换成英文符号
*
* @param statement
* @return
*/
private String initStatement(String statement) {
return statement.replace("(", "(").replace(")", ")").replace(";", ";")
.replace(",", ",").replace("“", "\"").replace("”", "\"");
}
private void initRunner(ExpressRunner runner) {
if (isInitialRunner == true) {
return;
......@@ -56,12 +49,9 @@ public class QlExpressUtil implements ApplicationContextAware {
return;
}
try {
runner.addFunctionOfServiceMethod("注册用户",applicationContext.getBean("bizLogicBean"), "signUser", new Class[] {String.class}, null);
runner.addFunctionOfServiceMethod("开店",applicationContext.getBean("bizLogicBean"), "openShop", new Class[] {com.ql.util.express.test.demo.biz.UserDO.class}, null);
runner.addFunctionOfServiceMethod("星级自增",applicationContext.getBean("bizLogicBean"), "addScore", new Class[] {com.ql.util.express.test.demo.biz.UserDO.class}, null);
runner.addFunctionOfServiceMethod("店铺升级",applicationContext.getBean("bizLogicBean"), "upgradeShop", new Class[] {com.ql.util.express.test.demo.biz.UserDO.class}, null);
runner.addFunctionOfServiceMethod("店铺营业中",applicationContext.getBean("bizLogicBean"), "isShopOpening", new Class[] {com.ql.util.express.test.demo.biz.UserDO.class}, null);
runner.addFunctionOfServiceMethod("读取用户信息",applicationContext.getBean("bizLogicBean"), "getUserInfo", new Class[] {String.class}, null);
runner.addMacro("判定用户是否vip","userDO.salary>200000");
} catch (Exception e) {
throw new RuntimeException("初始化失败表达式", e);
}
......
package com.ql.util.express.test.spring;
import org.unitils.UnitilsJUnit4;
import org.unitils.spring.annotation.SpringApplicationContext;
import org.unitils.spring.annotation.SpringBeanByName;
import java.util.HashMap;
import java.util.Map;
@SpringApplicationContext("classpath:spring-express-config.xml")
public class SpringDemoTest extends UnitilsJUnit4{
@SpringBeanByName
QlExpressUtil qlExpressUtil;
@org.junit.Test
public void testScript() throws Exception{
String express =
"if(bizLogicBean.getUserInfo(nick)!=null)" +
"{" +
"userDO = bizLogicBean.getUserInfo(nick);" +
"if(userDO.salary>20000 && userDO.salary<20000){" +
"System.out.println('高级客户:'+userDO.nick);" +
"}else if(userDO.salary>=200000){" +
"System.out.println('vip客户:'+userDO.nick);" +
"}else{" +
"System.out.println('普通客户:'+userDO.nick);" +
"}"+
"}else{" +
"System.out.println('用户信息不存在');" +
"}";
Map<String, Object> context = new HashMap<String, Object>();
context.put("nick", "马总");
qlExpressUtil.execute(express,
context);
context.put("nick", "小王");
qlExpressUtil.execute(express,
context);
context.put("nick", "XXX");
qlExpressUtil.execute(express,
context);
}
@org.junit.Test
public void testScript2() throws Exception{
String express =
"userDO = 读取用户信息(nick);"+
"if(userDO!=null)" +
"{" +
"if(判定用户是否vip)" +
"System.out.println('vip客户:'+userDO.nick);" +
"}else{" +
"System.out.println('用户信息不存在');" +
"}";
Map<String, Object> context = new HashMap<String, Object>();
context.put("nick", "马总");
qlExpressUtil.execute(express,
context);
context.put("nick", "小王");
qlExpressUtil.execute(express,
context);
context.put("nick", "XXX");
qlExpressUtil.execute(express,
context);
}
}
package com.ql.util.express.test.spring;
import java.util.Date;
/**
* Created by tianqiao on 17/3/8.
*/
public class UserDO {
private String nick;
private Long userId;
private Date gmtCreate;
private String position;
private Double salary;
public String getNick() {
return nick;
}
public void setNick(String nick) {
this.nick = nick;
}
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public Date getGmtCreate() {
return gmtCreate;
}
public void setGmtCreate(Date gmtCreate) {
this.gmtCreate = gmtCreate;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
public Double getSalary() {
return salary;
}
public void setSalary(Double salary) {
this.salary = salary;
}
}
event = new java.util.HashMap();
auction = new java.util.HashMap();
list = new ArrayList();
if(2>1){
for(i=0;i<10;i++){
for(j=0;j<10;a=1/0){
if(2>1){
auction.put("title","title");
}
}
}
}
auction.put("title","title");
auction.put("category","123456");
return auction;
<?xml version="1.0" encoding="GB2312"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans default-autowire="byName">
<bean id="bizLogicBean" class="com.ql.util.express.test.demo.biz.BizLogicBean"/>
<bean id="qlExpressUtil" class="com.ql.util.express.test.demo.QlExpressUtil"/>
<bean id="bizLogicBean" class="com.ql.util.express.test.spring.BizLogicBean"/>
<bean id="qlExpressUtil" class="com.ql.util.express.test.spring.QlExpressUtil"/>
</beans>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册