提交 56d901bc 编写于 作者: T tianqiao

阿里内部稳定版本同步到github

1、android环境的重大优化:减少编译的内存消耗,堆栈溢出问题
2、空指针的保护策略
3、支持对对象方法的增加和覆盖:比如 “aaa”.isNotBlank()
4、支持对jvm中不存在类的语法检查功能
上级 d174a474
......@@ -6,7 +6,7 @@
<groupId>com.alibaba</groupId>
<artifactId>QLExpress</artifactId>
<packaging>jar</packaging>
<version>3.2.0</version>
<version>3.2.1</version>
<name>QLExpress</name>
<description>QLExpress is a powerful, lightweight, dynamic language for the Java platform aimed at improving developers’ productivity in different business scenes.</description>
<url>https://github.com/alibaba/QLExpress</url>
......@@ -67,6 +67,7 @@
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
......
package com.ql.util.express;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
......@@ -283,6 +280,24 @@ public class ExpressRunner {
aClassName, aFunctionName, aParameterClassTypes,null,null, errorInfo));
}
/**
* 添加一个类的函数定义,例如:Math.abs(double) 映射为表达式中的 "取绝对值(-5.0)"
* @param name 函数名称
* @param aClass 类
* @param aFunctionName 类中的方法名称
* @param aParameterClassTypes 方法的参数类型名称
* @param errorInfo 如果函数执行的结果是false,需要输出的错误信息
* @throws Exception
*/
public void addFunctionOfClassMethod(String name, Class<?> aClass,
String aFunctionName, Class<?>[] aParameterClassTypes,
String errorInfo) throws Exception {
this.addFunction(name, new OperatorSelfDefineClassFunction(name,
aClass, aFunctionName, aParameterClassTypes,null,null, errorInfo));
}
/**
* 添加一个类的函数定义,例如:Math.abs(double) 映射为表达式中的 "取绝对值(-5.0)"
* @param name 函数名称
......@@ -468,7 +483,9 @@ public class ExpressRunner {
* 清除缓存
*/
public void clearExpressCache() {
this.expressInstructionSetCache.clear();
synchronized (expressInstructionSetCache) {
this.expressInstructionSetCache.clear();
}
}
/**
* 根据表达式的名称进行执行
......@@ -735,4 +752,57 @@ public class ExpressRunner {
public void setShortCircuit(boolean isShortCircuit) {
this.isShortCircuit = isShortCircuit;
}
/**
* 是否忽略charset类型的数据,而识别为string,比如'a' -> "a"
* 默认为不忽略,正常识别为String
*/
public boolean isIgnoreConstChar() {
return this.parse.isIgnoreConstChar();
}
public void setIgnoreConstChar(boolean ignoreConstChar) {
this.parse.setIgnoreConstChar(ignoreConstChar);
}
/**
* 提供简答的语法检查,保证可以在运行期本地环境编译成指令
* @param text
* @return
*/
public boolean checkSyntax(String text)
{
return checkSyntax(text,false,null);
}
/**
* 提供复杂的语法检查,(比如检查自定义的java类),不保证运行期在本地环境可以编译成指令
* @param text
* @param mockRemoteJavaClass
* @param remoteJavaClassNames
* @return
*/
public boolean checkSyntax(String text,boolean mockRemoteJavaClass,List<String> remoteJavaClassNames){
try {
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(this.rootExpressPackage, words,text, isTrace, selfDefineClass,mockRemoteJavaClass);
InstructionSet result = createInstructionSet(root, "main");
if (this.isTrace && log.isDebugEnabled()) {
log.debug(result);
}
if(mockRemoteJavaClass && remoteJavaClassNames!=null) {
remoteJavaClassNames.addAll(Arrays.asList(result.getVirClasses()));
}
return true;
}catch (Exception e){
log.error("checkSyntax has Exception",e);
return false;
}
}
}
package com.ql.util.express;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import com.ql.util.express.config.QLExpressRunStrategy;
import org.apache.commons.beanutils.PropertyUtils;
import java.lang.reflect.*;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.beanutils.PropertyUtils;
/**
* 表达式工具类
......@@ -529,6 +525,9 @@ public class ExpressUtil {
public static Object getProperty(Object bean, Object name) {
try {
if(bean==null && QLExpressRunStrategy.isAvoidNullPointer()){
return null;
}
if(bean.getClass().isArray() && name.equals("length")){
return Array.getLength(bean);
}else if (bean instanceof Class) {
......
......@@ -6,16 +6,16 @@ package com.ql.util.express;
*
*/
public interface IExpressContext<K,V> {
/**
* 根据名称从属性列表中提取属性值。如果表达式中用到了Spring的对象,也是通过此方法获取
* @param key 属性名称
* @return
*/
public V get(Object key);
/**
* 表达式计算的结果可以设置回调用系统,例如 userId = 3 + 4
* @param name 属性名称
* @param object 属性值
*/
public V put(K name, V object);
/**
* 根据名称从属性列表中提取属性值。如果表达式中用到了Spring的对象,也是通过此方法获取
* @param key 属性名称
* @return
*/
public V get(Object key);
/**
* 表达式计算的结果可以设置回调用系统,例如 userId = 3 + 4
* @param name 属性名称
* @param object 属性值
*/
public V put(K name, V object);
}
......@@ -38,7 +38,7 @@ public class InstructionSet implements Serializable{
public static String TYPE_FUNCTION ="function";
public static String TYPE_MARCO ="marco";
public static boolean printInstructionError = true;
public static boolean printInstructionError = false;
private String type ="main";
......@@ -82,6 +82,19 @@ public class InstructionSet implements Serializable{
return result.keySet().toArray(new String[0]);
}
public String[] getVirClasses() throws Exception {
Map<String,String> result = new TreeMap<String,String>();
for (int i = 0; i < instructionList.length; i++) {
Instruction instruction = instructionList[i];
if (instruction instanceof InstructionNewVirClass) {
String functionName = ((InstructionNewVirClass)instruction).getClassName();
result.put(functionName, null);
}
}
return result.keySet().toArray(new String[0]);
}
public String[] getOutAttrNames() throws Exception{
Map<String,String> result = new TreeMap<String,String>();
for(Instruction instruction:instructionList){
......
package com.ql.util.express;
import com.ql.util.express.config.QLExpressRunStrategy;
import com.ql.util.express.instruction.OperateDataCacheManager;
import com.ql.util.express.instruction.op.OperatorBase;
......@@ -7,71 +8,78 @@ import java.util.Date;
/**
* 操作符的基类
* @author xuannan
*
* @author xuannan
*/
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++){
parameters[i] = list.get(i).getObject(context);
}
Object result = this.executeInner(parameters);
if(result != null && result.getClass().equals(OperateData.class)){
throw new Exception("操作符号定义的返回类型错误:" + this.getAliasName());
}
if(result == null){
//return new OperateData(null,null);
return OperateDataCacheManager.fetchOperateData(null, null);
}else{
//return new OperateData(result,ExpressUtil.getSimpleDataType(result.getClass()));
return OperateDataCacheManager.fetchOperateData(result,ExpressUtil.getSimpleDataType(result.getClass()));
}
}
public abstract Object executeInner(Object[] list) throws Exception;
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++) {
if(list.get(i)==null && QLExpressRunStrategy.isAvoidNullPointer()){
parameters[i] = null;
}else {
parameters[i] = list.get(i).getObject(context);
}
}
Object result = this.executeInner(parameters);
if (result != null && result.getClass().equals(OperateData.class)) {
throw new Exception("操作符号定义的返回类型错误:" + this.getAliasName());
}
if (result == null) {
//return new OperateData(null,null);
return OperateDataCacheManager.fetchOperateData(null, null);
} else {
//return new OperateData(result,ExpressUtil.getSimpleDataType(result.getClass()));
return OperateDataCacheManager.fetchOperateData(result, ExpressUtil.getSimpleDataType(result.getClass()));
}
}
public abstract Object executeInner(Object[] list) throws Exception;
/**
* 进行对象比较
*
* @param op1
* @param op2
* @return 0--等于 ,负数 < , 正数 >
* @throws Exception
*/
public static int compareData(Object op1,Object op2) throws Exception{
int compareResult = -1;
if(op1 instanceof String){
compareResult = ((String)op1).compareTo(op2.toString());
}else if(op2 instanceof String){
compareResult = op1.toString().compareTo((String)op2);
}else if(op1 instanceof Character || op2 instanceof Character){
if(op1 instanceof Character && op2 instanceof Character ){
compareResult = ((Character) op1) .compareTo ((Character) op2);
}else if(op1 instanceof Number){
compareResult = OperatorOfNumber.compareNumber((Number)op1, (int)((Character) op2).charValue());
}else if(op2 instanceof Number){
compareResult = OperatorOfNumber.compareNumber((int)((Character) op1).charValue(),(Number)op2);
}else {
throw new Exception(op1 + "和" + op2 + "不能执行compare 操作");
}
}else if(op1 instanceof Number && op2 instanceof Number){
//数字比较
compareResult = OperatorOfNumber.compareNumber((Number)op1, (Number)op2);
}
else if ((op1 instanceof Boolean) && (op2 instanceof Boolean))
{
if (((Boolean)op1).booleanValue() ==((Boolean)op2).booleanValue())
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;
}
public static int compareData(Object op1, Object op2) throws Exception {
if(op1 == op2){
return 0;
}
int compareResult = -1;
if (op1 instanceof String) {
compareResult = ((String) op1).compareTo(op2.toString());
} else if (op2 instanceof String) {
compareResult = op1.toString().compareTo((String) op2);
} else if (op1 instanceof Character || op2 instanceof Character) {
if (op1 instanceof Character && op2 instanceof Character) {
compareResult = ((Character) op1).compareTo((Character) op2);
} else if (op1 instanceof Number) {
compareResult = OperatorOfNumber.compareNumber((Number) op1, (int) ((Character) op2).charValue());
} else if (op2 instanceof Number) {
compareResult = OperatorOfNumber.compareNumber((int) ((Character) op1).charValue(), (Number) op2);
} else {
throw new Exception(op1 + "和" + op2 + "不能执行compare 操作");
}
} else if (op1 instanceof Number && op2 instanceof Number) {
//数字比较
compareResult = OperatorOfNumber.compareNumber((Number) op1, (Number) op2);
} else if ((op1 instanceof Boolean) && (op2 instanceof Boolean)) {
if (((Boolean) op1).booleanValue() == ((Boolean) op2).booleanValue())
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;
}
}
package com.ql.util.express.config;
/**
* ExpressRunner设置全局生效的配置,直接使用静态方法控制
*/
public class QLExpressRunStrategy {
private static boolean avoidNullPointer = false;
public static boolean isAvoidNullPointer() {
return avoidNullPointer;
}
public static void setAvoidNullPointer(boolean avoidNullPointer) {
QLExpressRunStrategy.avoidNullPointer = avoidNullPointer;
}
}
......@@ -17,8 +17,12 @@ public class InstructionNewVirClass extends Instruction {
this.className = name;
this.opDataNumber = aOpDataNumber;
}
public void execute(RunEnvironment environment, List<String> errorList)
public String getClassName() {
return className;
}
public void execute(RunEnvironment environment, List<String> errorList)
throws Exception {
ArraySwap parameters = environment.popArray(
environment.getContext(), this.opDataNumber);
......
......@@ -4,6 +4,7 @@ import java.lang.reflect.Array;
import java.util.List;
import com.ql.util.express.Operator;
import com.ql.util.express.config.QLExpressRunStrategy;
public class OperatorIn extends Operator {
public OperatorIn(String aName) {
......@@ -19,6 +20,10 @@ public class OperatorIn extends Operator {
public Object executeInner(Object[] list) throws Exception {
Object obj = list[0];
if (obj == null) {
if(QLExpressRunStrategy.isAvoidNullPointer()){
//避免空指针策略异常则返回false
return false;
}
// 对象为空,不能执行方法
String msg = "对象为空,不能执行方法:";
throw new Exception(msg + this.name);
......
......@@ -6,6 +6,7 @@ import com.ql.util.express.ArraySwap;
import com.ql.util.express.ExpressUtil;
import com.ql.util.express.InstructionSetContext;
import com.ql.util.express.OperateData;
import com.ql.util.express.config.QLExpressRunStrategy;
import com.ql.util.express.instruction.OperateDataCacheManager;
import com.ql.util.express.instruction.opdata.OperateClass;
import com.ql.util.express.instruction.opdata.OperateDataVirClass;
......@@ -35,6 +36,9 @@ public class OperatorMethod extends OperatorBase {
}
if (obj == null) {
if(QLExpressRunStrategy.isAvoidNullPointer()){
return null;
}
// 对象为空,不能执行方法
String msg = "对象为空,不能执行方法:";
throw new Exception(msg + this.methodName);
......
......@@ -20,6 +20,27 @@ public class OperatorSelfDefineClassFunction extends OperatorBase implements Can
Method method;
boolean isReturnVoid;
boolean maybeDynamicParams;
public OperatorSelfDefineClassFunction(String aOperName,Class<?> aOperClass, String aFunctionName,
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;
this.parameterClasses = aParameterClassTypes;
this.parameterTypes = new String[aParameterClassTypes.length];
this.operDataDesc = aParameterDesc;
this.operDataAnnotation = aParameterAnnotation;
for(int i=0;i<this.parameterClasses.length;i++){
this.parameterTypes[i] = this.parameterClasses[i].getName();
}
operClass = aOperClass;
method = operClass.getMethod(functionName,parameterClasses);
this.isReturnVoid = method.getReturnType().equals(void.class);
this.maybeDynamicParams = DynamicParamsUtil.maybeDynamicParams(parameterClasses);
}
public OperatorSelfDefineClassFunction(String aOperName,String aClassName, String aFunctionName,
Class<?>[] aParameterClassTypes,String[] aParameterDesc,String[] aParameterAnnotation,String aErrorInfo) throws Exception {
......
......@@ -2,8 +2,8 @@ package com.ql.util.express.instruction.opdata;
import com.ql.util.express.ExpressUtil;
import com.ql.util.express.InstructionSetContext;
import com.ql.util.express.config.QLExpressRunStrategy;
import com.ql.util.express.parse.AppendingClassFieldManager;
import com.ql.util.express.parse.AppendingClassMethodManager;
public class OperateDataField extends OperateDataAttr {
Object fieldObject;
......@@ -22,7 +22,11 @@ public class OperateDataField extends OperateDataAttr {
public void initialDataField(Object aFieldObject,String aFieldName){
super.initialDataAttr(null, null);
this.name = aFieldObject.getClass().getName() + "." + aFieldName;
if(aFieldObject==null){
this.name = Void.class.getName()+ "." + aFieldName;
}else {
this.name = aFieldObject.getClass().getName() + "." + aFieldName;
}
this.fieldObject = aFieldObject;
this.orgiFieldName = aFieldName;
}
......@@ -90,6 +94,9 @@ public class OperateDataField extends OperateDataAttr {
if(this.fieldObject instanceof OperateDataVirClass){
return ((OperateDataVirClass)this.fieldObject).getValueType(transferFieldName(context,this.orgiFieldName));
}else{
if(this.fieldObject==null && QLExpressRunStrategy.isAvoidNullPointer()){
return Void.class;
}
return ExpressUtil.getPropertyClass(this.fieldObject,transferFieldName(context,this.orgiFieldName));
}
}
......
package com.ql.util.express.match;
public class NodeTypeManagerTestImpl implements INodeTypeManager {
public INodeType findNodeType(String name) {
return new TestNodeTypeImpl(name);
}
}
class TestNodeTypeImpl implements INodeType{
String name;
public TestNodeTypeImpl(String aName){
this.name = aName;
}
public String getName() {
return this.name;
}
public INodeTypeManager getManager() {
throw new RuntimeException("没有实现的方法");
}
@Override
public QLPatternNode getPatternNode() {
throw new RuntimeException("没有实现的方法");
}
}
package com.ql.util.express.match;
import java.util.ArrayList;
import java.util.List;
public class QLMatchResult {
protected List<QLMatchResultTree> matchs;
protected int matchLastIndex;
public INodeType statementNodeType;
public QLMatchResult(List<QLMatchResultTree> aList,int aIndex){
this.matchLastIndex = aIndex;
this.matchs = aList;
private List<QLMatchResultTree> matchs = new ArrayList<QLMatchResultTree>();
private int matchLastIndex;
public void clear(){
this.matchLastIndex =0;
this.matchs.clear();
}
public String toString(){
StringBuilder builder = new StringBuilder();
for(QLMatchResultTree item:matchs){
......@@ -22,14 +24,23 @@ public class QLMatchResult {
return matchs;
}
public void setMatchs(List<QLMatchResultTree> matchs) {
this.matchs = matchs;
public QLMatchResult addQLMatchResultTree(QLMatchResultTree tree){
this.matchs.add(tree);
return this;
}
public QLMatchResult addQLMatchResultTreeList(List<QLMatchResultTree> aList){
this.matchs.addAll(aList);
return this;
}
public int getMatchSize(){
return this.matchs.size();
}
public int getMatchLastIndex() {
return matchLastIndex;
}
public void setMatchLastIndex(int matchLastIndex) {
this.matchLastIndex = matchLastIndex;
}
public QLMatchResult setMatchLastIndex(int index){
this.matchLastIndex = index;
return this;
}
}
......@@ -10,21 +10,45 @@ import org.apache.commons.logging.LogFactory;
public class QLPattern {
private static final Log log = LogFactory.getLog(QLPattern.class);
public static boolean optimizeStackDepth = true;//优化栈的递归深度
public static boolean printStackDepth = false;//打印栈的最大深度
public static QLPatternNode createPattern(INodeTypeManager nodeTypeManager,String name,String pattern) throws Exception{
return new QLPatternNode(nodeTypeManager,name,pattern);
}
public static QLMatchResult findMatchStatement(INodeTypeManager aManager,QLPatternNode pattern ,List<? extends IDataNode> nodes,int point) throws Exception{
AtomicLong maxMatchPoint = new AtomicLong();
QLMatchResult result = findMatchStatementWithAddRoot(aManager,pattern,nodes,point,true,maxMatchPoint);
if(result == null || result.matchs.size() == 0){
AtomicLong maxDeep = new AtomicLong(1);
QLMatchResultCache resultCache =new QLMatchResultCache(5);
ArrayListCache<QLMatchResultTree> arrayListCache = new ArrayListCache<QLMatchResultTree>(50);
MatchParamsPack staticParams = new MatchParamsPack(aManager, nodes, maxDeep, maxMatchPoint,resultCache,arrayListCache);
QLMatchResult result = findMatchStatementWithAddRootOptimizeStack(staticParams, pattern, point, true, 1);
if(printStackDepth) {
log.warn("递归堆栈深度:" + maxDeep.longValue() + " 重用QLMatchResult次数:" + resultCache.fetchCount
+ " 新建QLMatchResult次数:" + resultCache.newCount + " 新建ArrayList数量:" + arrayListCache.newCount);
}
if(result == null || result.getMatchSize() == 0){
throw new Exception("程序错误,不满足语法规范,没有匹配到合适的语法,最大匹配致[0:" + (maxMatchPoint.longValue()-1) +"]");
}else if(result != null && result.matchs.size() != 1){
}else if(result != null && result.getMatchSize() != 1){
throw new Exception("程序错误,不满足语法规范,必须有一个根节点:" + pattern + ",最大匹配致[0:" + (maxMatchPoint.longValue()-1) +"]");
}
return result;
}
private static QLMatchResult findMatchStatementWithAddRoot(INodeTypeManager aManager,QLPatternNode pattern ,List<? extends IDataNode> nodes,int point,boolean isRoot,AtomicLong maxMatchPoint) throws Exception{
private static QLMatchResult findMatchStatementWithAddRootOptimizeStack(MatchParamsPack staticParams,QLPatternNode pattern ,int point,boolean isRoot,int deep) throws Exception{
INodeTypeManager aManager = staticParams.aManager;
List<? extends IDataNode> nodes = staticParams.nodes;
AtomicLong maxMatchPoint = staticParams.maxMatchPoint;
AtomicLong maxDeep = staticParams.maxDeep;
//mark maxDeep
deep++;
if (deep > maxDeep.longValue()){
maxDeep.set(deep);
}
QLMatchResult result = null;
List<QLMatchResultTree> tempList = null;
int count = 0;
......@@ -32,180 +56,312 @@ public class QLPattern {
while(true){
QLMatchResult tempResult = null;
if (pattern.matchMode == MatchMode.DETAIL) {
tempResult = matchDetailOneTime(aManager,pattern,nodes, lastPoint,maxMatchPoint);
//tempResult = matchDetailOneTime(aManager,pattern,nodes, lastPoint,maxMatchPoint,deep,maxDeep);
int pointDetail = lastPoint;
QLMatchResult resultDetail = null;
if(pattern.nodeType == aManager.findNodeType("EOF") && pointDetail == nodes.size()){
resultDetail = staticParams.resultCache.fetch().setMatchLastIndex(pointDetail + 1);
}else if(pattern.nodeType == aManager.findNodeType("EOF") && pointDetail < nodes.size() && nodes.get(pointDetail).getValue().equals("}") ){
resultDetail = staticParams.resultCache.fetch().setMatchLastIndex(pointDetail);
}else if(pointDetail == nodes.size() && pattern.nodeType.getPatternNode() != null){
resultDetail = findMatchStatementWithAddRootOptimizeStack(staticParams,pattern.nodeType.getPatternNode(),pointDetail,false,deep);
}else if( pointDetail < nodes.size()){
INodeType tempNodeType = null;
if(pattern.nodeType.equals(nodes.get(pointDetail).getTreeType())){
tempNodeType = nodes.get(pointDetail).getTreeType();
}else if(pattern.nodeType.equals(nodes.get(pointDetail).getNodeType())){
tempNodeType = nodes.get(pointDetail).getNodeType();
}
if(tempNodeType != null){
resultDetail = staticParams.resultCache.fetch();
resultDetail.addQLMatchResultTree(new QLMatchResultTree(tempNodeType,nodes.get(pointDetail),pattern.targetNodeType));
pointDetail = pointDetail + 1;
resultDetail.setMatchLastIndex(pointDetail);
traceLog(pattern,resultDetail,nodes,pointDetail - 1,1);
}else if(pattern.nodeType.getPatternNode() != null){
resultDetail = findMatchStatementWithAddRootOptimizeStack(staticParams,pattern.nodeType.getPatternNode(),pointDetail,false,deep);
if(pattern.targetNodeType != null && resultDetail != null && resultDetail.getMatchSize() >0){
if(resultDetail.getMatchSize() > 1){
throw new Exception("设置了类型转换的语法,只能有一个根节点");
}
resultDetail.getMatchs().get(0).targetNodeType = pattern.targetNodeType;
}
}
if(pattern.blame == true){//取返处理
if( resultDetail == null){
resultDetail = staticParams.resultCache.fetch();
resultDetail.addQLMatchResultTree(new QLMatchResultTree(tempNodeType,nodes.get(pointDetail),null));
pointDetail = pointDetail + 1;
resultDetail.setMatchLastIndex(pointDetail);
}else{
resultDetail = null;
}
}
}
if(resultDetail != null && resultDetail.getMatchLastIndex() > maxMatchPoint.longValue()){
maxMatchPoint.set(resultDetail.getMatchLastIndex());
}
tempResult = resultDetail;
}else if (pattern.matchMode == MatchMode.AND) {
tempResult = matchAndOneTime(aManager,pattern,nodes, lastPoint,maxMatchPoint);
//tempResult = matchAndOneTime(aManager,pattern,nodes, lastPoint,maxMatchPoint,deep,maxDeep);
int orgiPoint = lastPoint;
int pointAnd = lastPoint;
QLMatchResultTree root = null;
int matchCount =0;//用于调试日志的输出
List<QLMatchResultTree> tempListAnd =null;
boolean isBreak = false;
for (QLPatternNode item : pattern.children) {
if(pointAnd > nodes.size()){
isBreak = true;
break;
}
QLMatchResult tempResultAnd = findMatchStatementWithAddRootOptimizeStack(staticParams,item,
pointAnd,false,deep);
if (tempResultAnd != null) {
if(tempResultAnd.getMatchSize() > 0){
matchCount = matchCount + 1;
}
if(tempListAnd == null){
tempListAnd = staticParams.arrayListCache.fetch();
}
pointAnd = tempResultAnd.getMatchLastIndex();
if (item.isTreeRoot == true && tempResultAnd.getMatchSize() >0) {
if (tempResultAnd.getMatchSize() > 1) {
throw new Exception("根节点的数量必须是1");
}
if (root == null) {
QLMatchResultTree tempTree = tempResultAnd.getMatchs().get(0);
while(tempTree.getLeft()!= null && tempTree.getLeft().size()>0){
tempTree = tempTree.getLeft().get(0);
}
tempTree.addLeftAll(tempListAnd);
tempListAnd.clear();
} else {
tempResultAnd.getMatchs().get(0).addLeft(root);
}
root = tempResultAnd.getMatchs().get(0);
} else if (root != null) {
root.addRightAll(tempResultAnd.getMatchs());
} else {
tempListAnd.addAll(tempResultAnd.getMatchs());
}
//归还QLMatchResult对象到对象池
if (tempResultAnd!= null) {
staticParams.resultCache.sendBack(tempResultAnd);
tempResultAnd = null;
}
}else{
isBreak = true;
break;
}
}
if(root != null){
tempListAnd.add(root);
}
if(isBreak == false){
tempResult = staticParams.resultCache.fetch().addQLMatchResultTreeList(tempListAnd);
tempResult.setMatchLastIndex(pointAnd);
traceLog(pattern,tempResult,nodes,orgiPoint,matchCount);
}else{
tempResult = null;
}
if (tempListAnd != null){
staticParams.arrayListCache.sendBack(tempListAnd);
}
}else if (pattern.matchMode == MatchMode.OR) {
tempResult = matchOrOneTime(aManager,pattern,nodes, lastPoint,maxMatchPoint);
//tempResult = matchOrOneTime(aManager,pattern,nodes, lastPoint,maxMatchPoint,deep,maxDeep);
for (QLPatternNode item : pattern.children) {
tempResult = findMatchStatementWithAddRootOptimizeStack(staticParams,item, lastPoint, false, deep);
if (tempResult != null) {
break;
}
}
}else{
throw new Exception("不正确的类型:" + pattern.matchMode.toString());
}
if(tempResult == null){
if(count >= pattern.minMatchNum && count <=pattern.maxMatchNum){
//正确匹配
if(tempList == null){
tempList = new ArrayList<QLMatchResultTree>();
result = staticParams.resultCache.fetch();
if(tempList != null){
result.addQLMatchResultTreeList(tempList);
}
result = new QLMatchResult(tempList,lastPoint);
result.setMatchLastIndex(lastPoint);
}else{
result = null;
}
break;
}else{
if(tempList == null){
tempList = new ArrayList<QLMatchResultTree>();
tempList =staticParams.arrayListCache.fetch();
}
lastPoint = tempResult.matchLastIndex;
lastPoint = tempResult.getMatchLastIndex();
if(pattern.isTreeRoot == true){
if(tempResult.matchs.size() > 1){
if(tempResult.getMatchSize() > 1){
throw new Exception("根节点的数量必须是1");
}
if(tempList.size() == 0){
tempList.addAll(tempResult.matchs);
tempList.addAll(tempResult.getMatchs());
}else{
tempResult.matchs.get(0).addLeftAll(tempList);
tempList = tempResult.matchs;
tempResult.getMatchs().get(0).addLeftAll(tempList);
//为了能回收QLMatchResult对象,这个地方必须进行数组拷贝
tempList = staticParams.arrayListCache.fetch();
tempList.addAll(tempResult.getMatchs());
}
}else{
tempList.addAll(tempResult.matchs);
tempList.addAll(tempResult.getMatchs());
}
}
/** 归还QLMatchResult */
if(tempResult != null){
staticParams.resultCache.sendBack(tempResult);
tempResult = null;
}
count = count + 1;
if(count == pattern.maxMatchNum){
result = new QLMatchResult(tempList,lastPoint);
result = staticParams.resultCache.fetch();
if(tempList != null){
result.addQLMatchResultTreeList(tempList);
}
result.setMatchLastIndex(lastPoint);
break;
}
}
if(result != null && pattern.isSkip == true){
//忽略跳过所有匹配到的节点
result.matchs.clear();
result.getMatchs().clear();
}
if(result != null && result.matchs.size() >0 && pattern.rootNodeType != null){
if(result != null && result.getMatchSize() >0 && pattern.rootNodeType != null){
QLMatchResultTree tempTree = new QLMatchResultTree(pattern.rootNodeType,nodes.get(0).createExpressNode(pattern.rootNodeType,null));
tempTree.addLeftAll(result.matchs);
result.matchs.clear();
result.matchs.add(tempTree);
tempTree.addLeftAll(result.getMatchs());
result.getMatchs().clear();
result.getMatchs().add(tempTree);
}
if (tempList != null){
staticParams.arrayListCache.sendBack(tempList);
}
return result;
}
private static QLMatchResult matchDetailOneTime(INodeTypeManager aManager,QLPatternNode pattern ,List<? extends IDataNode> nodes,int point,AtomicLong maxMatchPoint) throws Exception{
QLMatchResult result = null;
if(pattern.nodeType == aManager.findNodeType("EOF") && point == nodes.size()){
result = new QLMatchResult(new ArrayList<QLMatchResultTree>(), point + 1);
}else if(pattern.nodeType == aManager.findNodeType("EOF") && point < nodes.size() && nodes.get(point).getValue().equals("}") ){
result = new QLMatchResult(new ArrayList<QLMatchResultTree>(), point);
}else if(point == nodes.size() && pattern.nodeType.getPatternNode() != null){
result = findMatchStatementWithAddRoot(aManager,pattern.nodeType.getPatternNode(),nodes,point,false,maxMatchPoint);
}else if( point < nodes.size()){
INodeType tempNodeType = nodes.get(point).getTreeType();
if(tempNodeType == null){
tempNodeType = nodes.get(point).getNodeType();
}
if(tempNodeType != null && tempNodeType.equals(pattern.nodeType)==false){
tempNodeType = null;
}
if(tempNodeType != null){
List<QLMatchResultTree> tempList = new ArrayList<QLMatchResultTree>();
tempList.add(new QLMatchResultTree(tempNodeType,nodes.get(point),pattern.targetNodeType));
point = point + 1;
result = new QLMatchResult(tempList, point);
traceLog(pattern,result,nodes,point - 1,1);
}else if(pattern.nodeType.getPatternNode() != null){
result = findMatchStatementWithAddRoot(aManager,pattern.nodeType.getPatternNode(),nodes,point,false,maxMatchPoint);
if(pattern.targetNodeType != null && result != null && result.matchs.size() >0){
if(result.matchs.size() > 1){
throw new Exception("设置了类型转换的语法,只能有一个根节点");
}
result.matchs.get(0).targetNodeType = pattern.targetNodeType;
}
}
if(pattern.blame == true){//取返处理
if( result == null){
List<QLMatchResultTree> tempList = new ArrayList<QLMatchResultTree>();
tempList.add(new QLMatchResultTree(tempNodeType,nodes.get(point),null));
point = point + 1;
result = new QLMatchResult(tempList, point);
}else{
result = null;
}
}
}
if(result != null && result.matchLastIndex > maxMatchPoint.longValue()){
maxMatchPoint.set(result.matchLastIndex);
public static void traceLog(QLPatternNode pattern, QLMatchResult result,
List<? extends IDataNode> nodes, int point,int matchCount) {
if (log.isTraceEnabled() && (pattern.matchMode ==MatchMode.DETAIL || pattern.matchMode == MatchMode.AND && matchCount > 1 && pattern.name.equals("ANONY_PATTERN") == false )) {
log.trace("匹配--" + pattern.name +"[" + point + ":" + (result.getMatchLastIndex() -1)+ "]:" + pattern);
}
return result;
}
public static class MatchParamsPack
{
INodeTypeManager aManager;
List<? extends IDataNode> nodes;
AtomicLong maxDeep;
AtomicLong maxMatchPoint;
QLMatchResultCache resultCache;
ArrayListCache arrayListCache;
public MatchParamsPack(INodeTypeManager aManager, List<? extends IDataNode> nodes, AtomicLong maxDeep, AtomicLong maxMatchPoint,QLMatchResultCache aResultCache,ArrayListCache aArrayListCache) {
this.aManager = aManager;
this.nodes = nodes;
this.maxDeep = maxDeep;
this.maxMatchPoint = maxMatchPoint;
this.resultCache = aResultCache;
this.arrayListCache = aArrayListCache;
}
}
}
public static class QLMatchResultCache {
public int newCount =0;
public int fetchCount =0;
private static QLMatchResult matchOrOneTime(INodeTypeManager aManager,
QLPatternNode pattern, List<? extends IDataNode> nodes, int point,
AtomicLong maxMatchPoint) throws Exception {
QLMatchResult result = null;
for (QLPatternNode item : pattern.children) {
QLMatchResult tempResult = findMatchStatementWithAddRoot(aManager,item, nodes, point, false, maxMatchPoint);
if (tempResult != null) {
return tempResult;
private QLMatchResult[] cache ;
private int len= 10;
private int point =9;
public QLMatchResultCache(int aLen){
this.len = aLen;
this.point = this.len -1;
cache = new QLMatchResult[this.len ];
for (int i=0;i<this.len;i++){
cache[i] = new QLMatchResult();
}
}
return result;
}
private static QLMatchResult matchAndOneTime(INodeTypeManager aManager,QLPatternNode pattern ,List<? extends IDataNode> nodes,int point,AtomicLong maxMatchPoint) throws Exception{
int orgiPoint = point;
QLMatchResultTree root = null;
int matchCount =0;//用于调试日志的输出
List<QLMatchResultTree> tempList =null;
for (QLPatternNode item : pattern.children) {
if(point > nodes.size()){
return null;
}
QLMatchResult tempResult = findMatchStatementWithAddRoot(aManager,item,nodes,
point,false,maxMatchPoint);
if (tempResult != null) {
if(tempResult.matchs.size() > 0){
matchCount = matchCount + 1;
}
if(tempList == null){
tempList = new ArrayList<QLMatchResultTree>();
}
point = tempResult.matchLastIndex;
if (item.isTreeRoot == true && tempResult.matchs.size() >0) {
if (tempResult.matchs.size() > 1)
throw new Exception("根节点的数量必须是1");
if (root == null) {
QLMatchResultTree tempTree = tempResult.matchs.get(0);
while(tempTree.getLeft()!= null && tempTree.getLeft().size()>0){
tempTree = tempTree.getLeft().get(0);
}
tempTree.addLeftAll(tempList);
tempList.clear();
} else {
tempResult.matchs.get(0).addLeft(root);
}
root = tempResult.matchs.get(0);
} else if (root != null) {
root.addRightAll(tempResult.matchs);
} else {
tempList.addAll(tempResult.matchs);
}
}else{
return null;
}
}
if(root != null){
tempList.add(root);
public QLMatchResult fetch() {
QLMatchResult result = null;
if (point >=0) {
result = cache[point];
cache[point] = null;
point = point - 1;
fetchCount++;
} else {
result = new QLMatchResult();
newCount++;
}
QLMatchResult result = new QLMatchResult(tempList,point);
traceLog(pattern,result,nodes,orgiPoint,matchCount);
return result;
}
public void sendBack(QLMatchResult result){
if (this.point <this.len -1){
this.point = this.point + 1;
cache[this.point] = result;
cache[this.point].clear();
}
}
}
public static void traceLog(QLPatternNode pattern, QLMatchResult result,
List<? extends IDataNode> nodes, int point,int matchCount) {
if (log.isTraceEnabled() && (pattern.matchMode ==MatchMode.DETAIL || pattern.matchMode == MatchMode.AND && matchCount > 1 && pattern.name.equals("ANONY_PATTERN") == false )) {
log.trace("匹配--" + pattern.name +"[" + point + ":" + (result.matchLastIndex -1)+ "]:" + pattern);
public static class ArrayListCache<T> {
public int newCount =0;
public int fetchCount =0;
private List<T>[] cache ;
private int len= 50;
private int point =49;
public ArrayListCache(int aLen){
this.len = aLen;
this.point = this.len -1;
cache = new List[this.len];
for (int i=0;i<this.len;i++){
cache[i] = new ArrayList<T>();
}
}
public List<T> fetch() {
List<T> result = null;
if (point >=0) {
result = cache[point];
cache[point] = null;
point = point - 1;
fetchCount++;
} else {
result = new ArrayList<T>();
newCount++;
}
return result;
}
public void sendBack(List<T> result){
if (this.point <this.len -1){
this.point = this.point + 1;
cache[this.point] = result;
cache[this.point].clear();
}
}
}
}
......
......@@ -34,7 +34,7 @@ public class QLPatternNode{
/**
* 是否根节点,例如:if^
*/
protected boolean isTreeRoot;
protected boolean isTreeRoot =false;
/**
* 最小匹配次数,0..n
......@@ -66,13 +66,26 @@ public class QLPatternNode{
* 是否匹配成功,但在输出的时候忽略,用"~"表示
* CONST$(,~$CONST)*
*/
protected boolean isSkip;
protected boolean isSkip =false;
/**
* 取反,例如:+@,匹配不是+的所有字符
*/
protected boolean blame = false;
public boolean canMergeDetail(){
if (QLPattern.optimizeStackDepth && this.matchMode == MatchMode.DETAIL && this.name.equals("ANONY_PATTERN")
&& this.nodeType.getPatternNode() != null
&& this.isSkip == false
&& this.blame ==false
&& this.isChildMode == false
&& this.isTreeRoot == false
&& this.minMatchNum ==1
&& this.maxMatchNum == 1){
return true;
}
return false;
}
/**
* 子匹配模式
......@@ -81,9 +94,10 @@ public class QLPatternNode{
protected QLPatternNode(INodeTypeManager aManager,String aName,String aOrgiContent) throws Exception{
this(aManager,aName,aOrgiContent,false,1);
if(this.toString().equals(aOrgiContent)==false){
throw new Exception("语法定义解析后的结果与原始值不一致,原始值:"+ aOrgiContent + " 解析结果:" + this.toString());
}
// if(this.toString().equals(aOrgiContent)==false){
//throw new Exception("语法定义解析后的结果与原始值不一致,原始值:"+ aOrgiContent + " 解析结果:" + this.toString());
//log.error(("语法定义解析后的结果与原始值不一致,原始值:"+ aOrgiContent + " 解析结果:" + this.toString()));
// }
}
protected QLPatternNode(INodeTypeManager aManager,String aName,String aOrgiContent,boolean aIsChildMode,int aLevel) throws Exception{
this.nodeTypeManager = aManager;
......@@ -92,6 +106,16 @@ public class QLPatternNode{
this.isChildMode = aIsChildMode;
this.level = aLevel;
this.splitChild();
for (int i=0;i< children.size();i++){
QLPatternNode t = children.get(i);
if(t.canMergeDetail()) {
this.children.set(i,t.getNodeType().getPatternNode());
if(t.getNodeType().getPatternNode().getNodeType() == null){
t.getNodeType().getPatternNode().nodeType = t.getNodeType();
}
}
}
}
public void splitChild() throws Exception{
if(log.isTraceEnabled()){
......
......@@ -19,11 +19,26 @@ public class ExpressParse {
private static final Log log = LogFactory.getLog(ExpressParse.class);
NodeTypeManager nodeTypeManager;
IExpressResourceLoader expressResourceLoader;
/**
* 是否忽略charset类型的数据,而识别为string,比如'a' -> "a"
* 在计算比如 '1'+'2'=='12'
*/
private boolean ignoreConstChar = false;
/**
* 是否需要高精度计算
*/
private boolean isPrecise = false;
public ExpressParse(NodeTypeManager aNodeTypeManager,IExpressResourceLoader aLoader,boolean aIsPrecise){
public boolean isIgnoreConstChar() {
return ignoreConstChar;
}
public void setIgnoreConstChar(boolean ignoreConstChar) {
this.ignoreConstChar = ignoreConstChar;
}
public ExpressParse(NodeTypeManager aNodeTypeManager, IExpressResourceLoader aLoader, boolean aIsPrecise){
this.nodeTypeManager = aNodeTypeManager;
this.expressResourceLoader = aLoader;
this.isPrecise = aIsPrecise;
......@@ -57,12 +72,16 @@ public class ExpressParse {
}
return result.toArray(new Word[0]);
}
/**
* 进行单词类型分析
* @param words
* @return
* @throws Exception
*/
/**
* 进行单词类型分析
* @param aRootExpressPackage
* @param wordObjects
* @param selfClassDefine
* @param dealJavaClass
* @return
* @throws Exception
*/
public List<ExpressNode> transferWord2ExpressNode(ExpressPackage aRootExpressPackage,Word[] wordObjects,Map<String,String> selfClassDefine,boolean dealJavaClass) throws Exception{
List<ExpressNode> result = new ArrayList<ExpressNode>();
String tempWord;
......@@ -174,7 +193,7 @@ public class ExpressParse {
tempWord = tempWord.substring(1,tempWord.length() -1);
treeNodeType = nodeTypeManager.findNodeType("CONST");
if(tempWord.length() == 1){ //转换为字符串
if(tempWord.length() == 1 && !ignoreConstChar){ //转换为字符串
tempType =nodeTypeManager.findNodeType("CONST_CHAR");
objectValue = tempWord.charAt(0);
}else{
......@@ -331,14 +350,45 @@ public class ExpressParse {
}
return words;
}
public ExpressNode parse(ExpressPackage rootExpressPackage,Word[] words ,String express,boolean isTrace,Map<String,String> selfDefineClass) throws Exception{
public ExpressNode parse(ExpressPackage rootExpressPackage,Word[] words ,String express,boolean isTrace,Map<String,String> selfDefineClass) throws Exception{
return parse(rootExpressPackage,words,express,isTrace,selfDefineClass,false);
}
public ExpressNode parse(ExpressPackage rootExpressPackage,Word[] words ,String express,boolean isTrace,Map<String,String> selfDefineClass,boolean mockRemoteJavaClass) throws Exception{
List<ExpressNode> tempList = this.transferWord2ExpressNode(rootExpressPackage,words,selfDefineClass,true);
if(isTrace == true && log.isDebugEnabled()){
log.debug("单词分析结果:" + printInfo(tempList,","));
}
if(isTrace == true && log.isDebugEnabled()){
log.debug("单词分析结果:" + printInfo(tempList,","));
}
//比如用在远程配置脚本,本地jvm并不包含这个java类,可以
if(mockRemoteJavaClass){
List<ExpressNode> tempList2 = new ArrayList<ExpressNode>();
for(int i=0;i<tempList.size();i++){
ExpressNode node = tempList.get(i);
if(node.getValue().equals("new") && node.getNodeType().getKind() == NodeTypeKind.KEYWORD && i+1<tempList.size() && !"CONST_CLASS".equals(tempList.get(i+1).getNodeType().getName())){
tempList2.add(node);
//取出 ( 前面的类路径作为configClass名称
int end = i+1;
String configClass = tempList.get(end).getValue();
end++;
while (!tempList.get(end).getValue().equals("(")) {
configClass = configClass+tempList.get(end).getValue();
end++;
}
NodeType nodeType = nodeTypeManager.findNodeType("VClass");
ExpressNode vClassNode = new ExpressNode(nodeType,configClass);
tempList2.add(vClassNode);
i = end-1;//因为循环之后,i++,所以i=end-1
}else {
tempList2.add(node);
}
}
tempList = tempList2;
if(isTrace == true && log.isDebugEnabled()){
log.debug("修正后单词分析结果:" + printInfo(tempList,","));
}
}
QLMatchResult result = QLPattern.findMatchStatement(this.nodeTypeManager, this.nodeTypeManager
.findNodeType("PROGRAM").getPatternNode(), tempList,0);
......
package com.ql.util.express.parse;
public class KeyWordDefine4SQL {
public String[] splitWord={
"+", "-","*", "/",//四则运算:
".",",",":",";","(", ")","[", "]","{","}","?",//分隔符号
"!","<", ">", "<=", ">=", "<>","="
};
public String[] keyWords = new String[] {
"select","from","where","and","or","like","if","then","else","as"
};
public String[] nodeTypeDefines = new String[] {
"in:TYPE=KEYWORD",
"EOF:TYPE=WORDDEF",
"FUNCTION_NAME:TYPE=WORDDEF",
"FUNCTION_DEFINE:TYPE=WORDDEF",
"ID:TYPE=WORDDEF",
"LEFT_BRACKET:TYPE=WORDDEF,DEFINE=(",
"RIGHT_BRACKET:TYPE=WORDDEF,DEFINE=)",
"CONST_BYTE:TYPE=WORDDEF",
"CONST_SHORT:TYPE=WORDDEF",
"CONST_INTEGER:TYPE=WORDDEF",
"CONST_LONG:TYPE=WORDDEF",
"CONST_FLOAT:TYPE=WORDDEF",
"CONST_DOUBLE:TYPE=WORDDEF",
"CONST_NUMBER:TYPE=WORDDEF,DEFINE=CONST_BYTE|CONST_SHORT|CONST_INTEGER|CONST_LONG|CONST_FLOAT|CONST_DOUBLE",
"CONST_CHAR:TYPE=WORDDEF",
"CONST_STRING:TYPE=WORDDEF",
"CONST_BOOLEAN:TYPE=WORDDEF",
"CONST_CLASS:TYPE=WORDDEF",
"CONST:TYPE=GROUP,DEFINE=CONST_NUMBER|CONST_CHAR|CONST_STRING|CONST_BOOLEAN|CONST_CLASS",
// "():TYPE=BLOCK,STARTTAG=(,ENDTAG=)",
// "[]:TYPE=BLOCK,STARTTAG=[,ENDTAG=]",
// "{}:TYPE=BLOCK,STARTTAG={,ENDTAG=}",
// "EXPRESS_CHILD:TYPE=GROUP,DEFINE=()|[]",
"OP_LEVEL1:TYPE=OPERATOR,DEFINE=!",
"OP_LEVEL2:TYPE=OPERATOR,DEFINE=*|/",
"OP_LEVEL3:TYPE=OPERATOR,DEFINE=+|-",
"OP_LEVEL4:TYPE=OPERATOR,DEFINE=in|like",
"OP_LEVEL5:TYPE=OPERATOR,DEFINE=>|>=|<|<=|=|<>",
"OP_LEVEL6:TYPE=OPERATOR,DEFINE=and",
"OP_LEVEL7:TYPE=OPERATOR,DEFINE=or",
"TAB_COL_NAME:TYPE=STATEMENT,DEFINE=ID$(.$ID)*#TAB_COL_NAME",
"CHILD_EXPRESS:TYPE=EXPRESS,DEFINE=LEFT_BRACKET~$EXPRESS$RIGHT_BRACKET~",
"OPDATA:TYPE=EXPRESS,DEFINE=CHILD_EXPRESS|CONST|TAB_COL_NAME",
"TAB_COL_NAME_ALIAS:TYPE=STATEMENT,DEFINE=TAB_COL_NAME$(as^$TAB_COL_NAME){0:1}",
"TAB_COL_LIST:TYPE=STATEMENT,DEFINE=TAB_COL_NAME_ALIAS$(,~$TAB_COL_NAME_ALIAS)*",
"EXPRESS_OP_L1:TYPE=EXPRESS,DEFINE=OP_LEVEL1^*$OPDATA",
"EXPRESS_OP_L2:TYPE=EXPRESS,DEFINE=EXPRESS_OP_L1$(OP_LEVEL2^$EXPRESS_OP_L1)^*",
"EXPRESS_OP_L3:TYPE=EXPRESS,DEFINE=EXPRESS_OP_L2$(OP_LEVEL3^$EXPRESS_OP_L2)^*",
"EXPRESS_OP_L4:TYPE=EXPRESS,DEFINE=EXPRESS_OP_L3$(OP_LEVEL4^$EXPRESS_OP_L3)^*",
"EXPRESS_OP_L5:TYPE=EXPRESS,DEFINE=EXPRESS_OP_L4$(OP_LEVEL5^$EXPRESS_OP_L4)^*",
"EXPRESS_OP_L6:TYPE=EXPRESS,DEFINE=EXPRESS_OP_L5$(OP_LEVEL6^$EXPRESS_OP_L5)^*",
"EXPRESS_OP_L7:TYPE=EXPRESS,DEFINE=EXPRESS_OP_L6$(OP_LEVEL7^$EXPRESS_OP_L6)^*",
"EXPRESS:TYPE=STATEMENT,DEFINE=EXPRESS_OP_L7",
"OP_LIST:TYPE=GROUP,DEFINE=OP_LEVEL1|OP_LEVEL2|OP_LEVEL3|OP_LEVEL4|OP_LEVEL5|OP_LEVEL6|OP_LEVEL7|LEFT_BRACKET|RIGHT_BRACKET|[|]",
"PARAMETER_LIST:TYPE=STATEMENT,DEFINE=EXPRESS$(,~$EXPRESS)*",
"SELECT:TYPE=STATEMENT,DEFINE=(select^$TAB_COL_LIST)$(from^$PARAMETER_LIST)$(where^$EXPRESS){0:1}#SELECT",
"STATEMENT:TYPE=STATEMENT",
"PROGRAM:TYPE=STATEMENT,DEFINE=SELECT",
};
}
......@@ -25,13 +25,6 @@ public class NodeTypeManager implements INodeTypeManager {
public NodeTypeManager() {
this(new KeyWordDefine4Java());
}
public NodeTypeManager(KeyWordDefine4SQL keyWorkdDefine){
this.splitWord = keyWorkdDefine.splitWord;
this.keyWords = keyWorkdDefine.keyWords;
this.nodeTypeDefines = keyWorkdDefine.nodeTypeDefines;
this.initial();
}
public NodeTypeManager(KeyWordDefine4Java keyWorkdDefine){
this.splitWord = keyWorkdDefine.splitWord;
com.ql.util.express.parse.WordSplit.sortSplitWord(this.splitWord);
......
......@@ -81,7 +81,7 @@ public class WordSplit
if (point < i ){
list.add(new Word(str.substring(point,i),line,i));
}
list.add(new Word(str.substring(i, i+length),line,i));
list.add(new Word(str.substring(i, i+length),line,i+length));
i = i + length;
point = i;
isFind = true;
......
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.config.QLExpressRunStrategy;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class AvoidNullPointMockTest {
public class DemoObject{
private String code;
private DemoObject parent;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public DemoObject getParent() {
return parent;
}
public void setParent(DemoObject parent) {
this.parent = parent;
}
}
@Before
public void before()
{
QLExpressRunStrategy.setAvoidNullPointer(true);
}
@After
public void after()
{
QLExpressRunStrategy.setAvoidNullPointer(false);
}
@Test
public void testNullPoint() throws Exception{
ExpressRunner runner = new ExpressRunner(false,true);
String[] explist = new String[]{
"x in(1,2,3)",
"demo.code",
"demo.parent.code",
"demo.parent.getCode()",
"demo.getParent().getCode()",
"demo.getParent().getCode() in (1,2,3)",
};
for(String exp:explist) {
IExpressContext<String, Object> context = new DefaultContext<String, Object>();
System.out.println(exp);
((DefaultContext<String, Object>) context).put("demo",new DemoObject());
Object result = runner.execute(exp, context, null, true, false);
System.out.println(result);
}
}
}
package com.ql.util.express.bugfix;
import com.ql.util.express.ExpressRunner;
import org.junit.Assert;
import org.junit.Test;
import java.util.ArrayList;
/**
* Created by tianqiao on 18/2/26.
*/
public class CheckySyntaxTest {
@Test
public void testCheckySyntax0() throws Exception{
ExpressRunner runner = new ExpressRunner(false,true);
String[] expList = new String[]{
"import java.text.SimpleDateFormat;new SimpleDateFormat()",
"a = new java.text.SimpleDateFormat()",
};
for(String exp :expList) {
Assert.assertTrue(runner.checkSyntax(exp));
}
for(String exp :expList) {
ArrayList<String> mockClasses = new ArrayList<String>();
Assert.assertTrue(runner.checkSyntax(exp,true,mockClasses));
System.out.println("未识别的java类列表:"+mockClasses);
}
}
@Test
public void testCheckySyntax() throws Exception{
ExpressRunner runner = new ExpressRunner(false,true);
String[] expList = new String[]{
"import com.taobao.ABC;a = new ABC();",
"import com.taobao.*;a = new ABC();",
"import com.taobao.ABC;a = new com.taobao.ABC();",
"a = new com.taobao.ABC();if('new'.equals(op)){System.out.println('ok');}"
};
for(String exp :expList) {
ArrayList<String> mockClasses = new ArrayList<String>();
Assert.assertTrue(runner.checkSyntax(exp,true,mockClasses));
System.out.println("未识别的java类列表:"+mockClasses);
}
}
}
......@@ -8,7 +8,7 @@ import org.junit.Test;
public class CompareObjectTest {
@Test
public void test() throws Exception{
public void test() throws Exception {
System.out.println('a'<98);
ExpressRunner runner = new ExpressRunner();
......
......@@ -31,7 +31,7 @@ public class CrashTest {
/**
* 版本3.0.9以下存在多线程初始化问题,这个类作为一个样例
*/
public static void main(String[] args) throws InterruptedException, BrokenBarrierException {
public void testCrash() throws InterruptedException, BrokenBarrierException {
System.out.println(Arrays.asList(splitWord));
for (int j = 0; j < 1000; j++) {
CyclicBarrier barrier = new CyclicBarrier(11, null);
......
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 18/1/29.
*/
public class IgnoreConstCharTest {
@Test
public void test() throws Exception{
ExpressRunner runner = new ExpressRunner();
runner.setIgnoreConstChar(true);
String exp = "'1'+'2'==\"12\"";
IExpressContext<String, Object> context = new DefaultContext<String, Object>();
Object result = runner.execute(exp,context,null,false,true);
assert ((Boolean) result);
}
}
......@@ -3,6 +3,7 @@ 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.Assert;
import org.junit.Test;
/**
......@@ -21,8 +22,13 @@ public class ImportClassPath {
result = runner.execute(exp,context,null,false,false);
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
System.out.println("SimpleDateFormat 没有定义,此处应该报错");
//e.printStackTrace();
Assert.assertTrue(true);
return;
}
Assert.assertTrue(false);
}
@Test
......
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;
import java.util.ArrayList;
import java.util.Collection;
/**
* 自定义的LoopAnd,LoopOr,LoopSet function功能
* Created by tianqiao on 18/2/8.
*/
public class LoopFunctionTest {
@Test
public void test() throws Exception{
ExpressRunner runner = new ExpressRunner(false,true);
runner.addFunction("loopAnd", new Operator() {
private ExpressRunner loppRunner = new ExpressRunner();
@Override
public Object executeInner(Object[] list) throws Exception {
if(list[0]==null){
return false;
}
if(!(list[0] instanceof Collection)||((Collection)list[0]).size()==0){
return false;
}
Collection objs = (Collection) list[0];
String exp = (String) list[1];
Integer index = 0;
for(Object obj : objs) {
IExpressContext<String, Object> map = new DefaultContext<String, Object>();
map.put("x",obj);
map.put("index",index++);
try {
Object r = loppRunner.execute(exp, map, null, true, false);
if(r!=null && r instanceof Boolean && (Boolean) r){
continue;
}else{
return false;
}
}catch (Exception e){
return false;
}
}
return true;
}
});
runner.addFunction("loopOr", new Operator() {
private ExpressRunner loppRunner = new ExpressRunner();
@Override
public Object executeInner(Object[] list) throws Exception {
if(list[0]==null){
return false;
}
if(!(list[0] instanceof Collection)||((Collection)list[0]).size()==0){
return false;
}
Collection objs = (Collection) list[0];
String exp = (String) list[1];
Integer index=0;
for(Object obj : objs) {
IExpressContext<String, Object> map = new DefaultContext<String, Object>();
map.put("x",obj);
map.put("index",index++);
try {
Object r = loppRunner.execute(exp, map, null, true, false);
if(r!=null && r instanceof Boolean && (Boolean) r){
return true;
}else{
continue;
}
}catch (Exception e){
return false;
}
}
return false;
}
});
runner.addFunction("loopSet", new Operator() {
private ExpressRunner loppRunner = new ExpressRunner();
@Override
public Object executeInner(Object[] list) throws Exception {
if(list[0]==null){
return false;
}
if(!(list[0] instanceof Collection)||((Collection)list[0]).size()==0){
return false;
}
Collection objs = (Collection) list[0];
String exp = (String) list[1];
Integer index=0;
for(Object obj : objs) {
IExpressContext<String, Object> map = new DefaultContext<String, Object>();
map.put("x",obj);
map.put("index",index++);
try {
loppRunner.execute(exp, map, null, true, false);
}catch (Exception e){
return null;
}
}
return null;
}
});
ArrayList<SkuDO> skuList = createSkuList();
IExpressContext<String, Object> context = new DefaultContext<String, Object>();
String exp = "loopAnd(skuList,'x.price>10')";
context.put("skuList",skuList);
Object result = runner.execute(exp,context,null,false,true);
assert ((Boolean)result);
exp = "loopSet(skuList,'if(index>=2){x.price=9.9}')";
runner.execute(exp,context,null,false,true);
assert (skuList.get(0).getPrice()==10.1);
assert (skuList.get(1).getPrice()==10.1);
assert (skuList.get(2).getPrice()==9.9);
exp = "loopOr(skuList,'x.price<10')";
result = runner.execute(exp,context,null,false,true);
assert ((Boolean)result);
}
private ArrayList<SkuDO> createSkuList() {
ArrayList<SkuDO> skuList = new ArrayList<SkuDO>();
for(int i=0;i<5;i++) {
SkuDO sku = new SkuDO();
sku.setPrice(10.1);
skuList.add(sku);
}
return skuList;
}
public class SkuDO{
private Long id;
private Double price;
private String title;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
}
package com.ql.util.express.bugfix;
import com.ql.util.express.ExpressRunner;
import com.ql.util.express.InstructionSet;
import com.ql.util.express.match.QLPattern;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
public class TestCompileMemory {
@Test
public void test() throws Exception {
QLPattern.printStackDepth = true;
List<String> expressList = new ArrayList<String>();
String demo = "fieldList = formDO.getFieldList();\n" +
"submitBtn = formDO.getSubmitBtn();\n" +
"leaf = parentCat.leaf;\n" +
"if (parentCat.getCatId() == 0){\n" +
" firstLevel = true;\n" +
"} else {\n" +
" firstLevel = false;\n" +
"}\n" +
"\n" +
"mustLeaf = parentCat.getNamePaths()!=null&&parentCat.getNamePaths().length == 2;\n" +
"leafFeatureList = new HashMap ();\n" +
"leafFeatureList.put(\"CBU_DEFAULT_SKUPRICE\", \"1\");\n" +
"leafFeatureList.put(\"CBU_ISSUPPORTONLINE\", \"1\");\n" +
"leafFeatureList.put(\"CBU_MIXED_BATCH\", \"1\");\n" +
"leafFeatureList.put(\"CBU_SUPPORT_WHOLESALE\", \"1\");\n" +
"leafFeatureList.put(\"CBU_TEMPLATE\", \"1\");\n" +
"leafFeatureList.put(\"CBU_USE_SPU\", \"1\");\n" +
"firstLevelFeatureList = new HashMap ();\n" +
"firstLevelFeatureList.put(\"CBU_TRADE_TYPE\", \"1\");\n" +
"\n" +
"\n" +
"\n" +
"for (int i = 0; i < fieldList.size(); i++)\n" +
"{\n" +
" field = fieldList.get(i);\n" +
" name = field.getName();\n" +
" if (leaf == true){\n" +
" field.setDisabled(true);\n" +
" }\n" +
" if (name.equals(\"namePaths\")){\n" +
" field.setValue(parentCat.getNamePathsStr());\n" +
" }\n" +
"\n" +
" if (name.equals(\"sortOrder\")){\n" +
" field.setValue(-1);\n" +
" field.setOptions(subCatList);\n" +
" }\n" +
" if (name.equals(\"CBU_OPERATOR\")){\n" +
" field.setValue(operator);\n" +
" }\n" +
" if (name.equals(\"gmtModified\")){\n" +
" field.setValue(gmtModified);\n" +
" }\n" +
" if (name.equals(\"leaf\")){\n" +
" if (firstLevel == true){\n" +
" field.setDisabled(true);\n" +
" field.setValue(false);\n" +
" } else {\n" +
" field.setDisabled(false);\n" +
" }\n" +
" if (mustLeaf){\n" +
" field.setDisabled(true);\n" +
" field.setValue(true);\n" +
" }\n" +
" }\n" +
"\n" +
" val = leafFeatureList.get(name);\n" +
" if (val!=null&&val.equals(\"1\")){\n" +
" if (mustLeaf){\n" +
" field.setVisible(true);\n" +
" } else {\n" +
" field.setVisible(false);\n" +
" }\n" +
"\n" +
" }\n" +
" val = firstLevelFeatureList.get(name);\n" +
" if (val!=null&&val.equals(\"1\")){\n" +
" if (firstLevel == false){\n" +
" field.setVisible(false);\n" +
" }\n" +
" }\n" +
" if (hasPermission == false){\n" +
" field.disabled = true;\n" +
" }\n" +
"\n" +
"}\n" +
"if (hasPermission == false){\n" +
" submitBtn.getSubmitBtn().setVisible(false);\n" +
" field.setDisabled(true);\n" +
" applyHref = submitBtn.getSubmitBtn().getHref();\n" +
" globalerror.setUiType(\"globalError\");\n" +
" globalerror.setValue(\"无操作权限,请点击申请\");\n" +
" globalerror.setHref(applyHref);\n" +
" fieldList.add(globalerror);\n" +
"} else if (leaf == true){\n" +
" submitBtn.getSubmitBtn().setDisabled(true);\n" +
" globalerror.setUiType(\"globalError\");\n" +
" globalerror.setValue(\"叶子类目下不能添加子类目\");\n" +
" fieldList.add(globalerror)\n" +
"} else {\n" +
" submitBtn.getSubmitBtn().setDisabled(false);\n" +
" submitBtn.getSubmitBtn().setVisible(true);\n" +
"}\n" +
"formDO.setFieldList(fieldList);\n" +
"return formDO;";
expressList.add(demo);
demo = "max(1,max(2,max(3,max(4,max(5,max(6,7))))))";
expressList.add(demo);
demo = "for(i=0;i<100;i++){System.out.println(11111)}";
expressList.add(demo);
for(String express : expressList) {
ExpressRunner runner2 = new ExpressRunner();
InstructionSet result2 = runner2.parseInstructionSet(express);
System.out.println(express + " 编译结果如下:\n" + result2);
}
QLPattern.printStackDepth = false;
}
}
package com.ql.util.express.bugfix;
import org.junit.Test;
public class TestOverFlow {
public class Result{
private int a = 0;
private String b = "我是一个长长的字符串";
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
public String getB() {
return b;
}
public void setB(String b) {
this.b = b;
}
}
private int count = 0;
public void fun(){
count ++;
fun();
}
public void fun_a(int a){
count ++;
fun_a(a);
}
public int funReturn(){
count ++;
int a = funReturn();
return 1 + a + 1;
}
public Result funBigReturn(){
count ++;
Result a = funBigReturn();
a.setA(1);
return a;
}
public void fun_abc(int a,int b,int c){
count ++;
fun_abc(a+1,b+1,c+1);
}
public void fun_abc2(int a,int b,int c){
count ++;
fun_a(a,b,c);
}
public void fun_a(int a,int b,int c){
count ++;
fun_abc2(a+1,b,c);
}
public void fun_b(int a,int b,int c){
count ++;
fun_abc2(a,b+1,c);
}
public void fun_c(int a,int b,int c){
count ++;
fun_abc2(a,b,c+1);
}
public void test(){
try{
this.count = 0;
fun();
}catch(Throwable e){
System.out.println("fun() 最大栈深度:"+count);
}
}
public void test_a(){
try{
this.count = 0;
fun_a(1);
}catch(Throwable e){
System.out.println("fun_a() 最大栈深度:"+count);
}
}
public void testReturn(){
try{
this.count = 0;
funReturn();
}catch(Throwable e){
System.out.println("funReturn() 最大栈深度:"+count);
}
try{
this.count = 0;
funBigReturn();
}catch(Throwable e){
System.out.println("funBigReturn() 最大栈深度:"+count);
}
}
public void test_abc() {
try {
this.count = 0;
fun_abc(1, 1, 1);
} catch (Throwable e) {
System.out.println("fun_abc() 最大栈深度:" + count);
}
}
public void test_abc2(){
try{
this.count = 0;
fun_abc2(1,1,1);
}catch(Throwable e){
System.out.println("fun_abc2() 最大栈深度:"+count);
}
}
public void testOverFlow()
{
test();
test_a();
testReturn();
test_abc();
test_abc2();
}
@Test
public void testOverflow(){
new TestOverFlow().testOverFlow();
}
}
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.match.QLPattern;
import org.junit.Test;
public class TestStackOverFlowTest {
@Test
public void test() throws Exception {
String expressList[] = new String[]{
"1",
"1+2",
"max(1,2)",
"max(1,max(2,3))",
"max(1,max(2,max(3,4)))",
"max(1,max(2,max(3,max(4,5))))",
"max(1,max(2,max(3,max(4,max(5,6)))))",
"max(1,max(2,max(3,max(4,max(5,max(6,7))))))",
};
for(String express: expressList) {
QLPattern.printStackDepth = true;
QLPattern.optimizeStackDepth = false;
ExpressRunner runner = new ExpressRunner();
IExpressContext<String, Object> context = new DefaultContext<String, Object>();
Object result = runner.execute(express, context, null, true, false);
System.out.println(express + " = " + result);
System.out.println("优化栈深度之后:");
QLPattern.printStackDepth = true;
QLPattern.optimizeStackDepth = true;
ExpressRunner runner2 = new ExpressRunner();
Object result2 = runner2.execute(express, context, null, true, false);
System.out.println(express + " = " + result2);
QLPattern.printStackDepth = false;
}
}
}
......@@ -3,6 +3,7 @@ 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.Assert;
import org.junit.Test;
/**
......@@ -14,14 +15,7 @@ public class ThrowExceptionTest {
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) {
// e.printStackTrace();
throw new Exception("Exception happened!",e);
}
}
......@@ -36,9 +30,23 @@ public class ThrowExceptionTest {
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();
// e.printStackTrace();
String keywords = "run QlExpress Exception at line 1";
String exceptionString = e.toString();
Assert.assertTrue(exceptionString.contains(keywords));
keywords = "java.lang.reflect.InvocationTargetException";
exceptionString = e.getCause().toString();
Assert.assertTrue(exceptionString.contains(keywords));
keywords = "Exception happened";
exceptionString = e.getCause().getCause().toString();
Assert.assertTrue(exceptionString.contains(keywords));
keywords = "java.lang.NumberFormatException";
exceptionString = e.getCause().getCause().getCause().toString();
Assert.assertTrue(exceptionString.contains(keywords));
}
}
}
......@@ -25,14 +25,10 @@ public class ArgumentTypeMismatchTest {
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("a",1L);
context.put("b",2);
context.put("c","3");
try {
runner.execute(exp, context, null, false, false);
}catch (Exception e){
e.printStackTrace();
}
runner.execute(exp, context, null, false, false);
}
@Test
......@@ -53,12 +49,7 @@ public class ArgumentTypeMismatchTest {
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!");
runner.execute(exp, context, null, false, false);
}
@Test
......@@ -90,12 +81,8 @@ public class ArgumentTypeMismatchTest {
System.out.println("before execute instructionSet = " + instructionSet);
System.out.println("outFunctionNames = " + ToStringBuilder.reflectionToString(outFunctionNames, ToStringStyle.MULTI_LINE_STYLE));
System.out.println("outVarNames = " + ToStringBuilder.reflectionToString(outVarNames, ToStringStyle.MULTI_LINE_STYLE));
try {
runner.execute(exp, context, null, false, false);
} catch (Exception e) {
e.printStackTrace();
}
runner.execute(exp, context, null, false, false);
instructionSet = runner.getInstructionSetFromLocalCache(exp);
outFunctionNames = runner.getOutFunctionNames(exp);
......@@ -103,7 +90,5 @@ public class ArgumentTypeMismatchTest {
System.out.println("after execute instructionSet = " + instructionSet);
System.out.println("outFunctionNames = " + ToStringBuilder.reflectionToString(outFunctionNames, ToStringStyle.MULTI_LINE_STYLE));
System.out.println("outVarNames = " + ToStringBuilder.reflectionToString(outVarNames, ToStringStyle.MULTI_LINE_STYLE));
System.out.println("test ok!");
}
}
......@@ -13,6 +13,14 @@ import com.ql.util.express.example.operator.ApproveOperator;
*
*/
public class WorkflowTest {
public void print(String s) {
System.out.print(s);
}
public void println(String s) {
System.out.println(s);
}
/**
* 执行一段文本
......@@ -49,7 +57,7 @@ public class WorkflowTest {
runner.addOperatorWithAlias("否则", "else",null);
runner.addOperatorWithAlias("大于", ">",null);
//
runner.addFunctionOfServiceMethod("打印", System.out, "println",new String[] { "String" }, null);
runner.addFunctionOfServiceMethod("打印", new WorkflowTest(), "println",new String[] { "String" }, null);
//定义方法
runner.addFunction("审批通过", new ApproveOperator(1));
runner.addFunction("报销入账", new ApproveOperator(2));
......@@ -62,7 +70,7 @@ public class WorkflowTest {
expressContext.put("申请人", "小强");
expressContext.put("金额", new Integer(4000));
//执行表达式
// runner.execute(exp, expressContext, null,false, false);
runner.execute(exp, expressContext, null,false, false);
}
/**
......@@ -77,7 +85,7 @@ public class WorkflowTest {
runner.addOperatorWithAlias("否则", "else",null);
runner.addOperatorWithAlias("大于", ">",null);
//
runner.addFunctionOfServiceMethod("打印", System.out, "println",new String[] { "String" }, null);
runner.addFunctionOfServiceMethod("打印", new WorkflowTest(), "println",new String[] { "String" }, null);
//定义方法
runner.addFunction("审批通过", new ApproveOperator(1));
runner.addFunction("报销入账", new ApproveOperator(2));
......@@ -94,7 +102,7 @@ public class WorkflowTest {
expressContext.put("申请人", "小强");
expressContext.put("金额", new Integer(5000));
// runner.executeByExpressName("example/approve1", expressContext, null, false,false,null);
runner.executeByExpressName("example/approve1", expressContext, null, false,false,null);
}
/**
......@@ -109,7 +117,7 @@ public class WorkflowTest {
runner.addOperatorWithAlias("否则", "else",null);
runner.addOperatorWithAlias("大于", ">",null);
//
runner.addFunctionOfServiceMethod("打印", System.out, "println",new String[] { "String" }, null);
runner.addFunctionOfServiceMethod("打印", new WorkflowTest(), "println",new String[] { "String" }, null);
//加载文件
runner.loadExpress("example/approve");
//设置上下文变量
......@@ -120,7 +128,7 @@ public class WorkflowTest {
expressContext.put("申请人", "小强");
expressContext.put("金额", new Integer(6000));
// runner.executeByExpressName("example/approve", expressContext, null, false,false,null);
runner.executeByExpressName("example/approve", expressContext, null, false,false,null);
}
/**
......@@ -135,7 +143,7 @@ public class WorkflowTest {
runner.addOperatorWithAlias("否则", "else",null);
runner.addOperatorWithAlias("大于", ">",null);
//
runner.addFunctionOfServiceMethod("打印", System.out, "println",new String[] { "String" }, null);
runner.addFunctionOfServiceMethod("打印", new WorkflowTest(), "println",new String[] { "String" }, null);
//加载文件
runner.loadExpress("example/approve1");
......@@ -148,7 +156,7 @@ public class WorkflowTest {
expressContext.put("申请人", "小强");
expressContext.put("金额", new Integer(7000));
// runner.executeByExpressName("example/approve1", expressContext, null, false,false,null);
runner.executeByExpressName("example/approve1", expressContext, null, false,false,null);
}
}
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 com.ql.util.express.Operator;
import org.junit.Test;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class DateFormatTest
{
@Test
public void testDateFormatCompare() throws Exception {
ExpressRunner runner = new ExpressRunner();
runner.addFunction("DateFormat",new Operator() {
private Map<String,Date> cache = new HashMap<String,Date>();
@Override
public Object executeInner(Object[] objects) throws Exception {
String s = objects[0].toString();
Date d = cache.get(s);
if(d!=null){
return d;
}else {
d = new SimpleDateFormat("yyyy-MM-dd").parse(s);
cache.put(s,d);
return d;
}
}
});
IExpressContext<String, Object> context = new DefaultContext<String, Object>();
context.put("nowStr",new SimpleDateFormat("yyyy-MM-dd").parse("2018-02-23"));
String sb = "nowStr.before(new Date(2018,2,22))";
testTimeCost(runner, sb, context);
String sb2 = "nowStr > DateFormat('2018-02-22')";
testTimeCost(runner, sb2, context);
String sb3 = "nowStr > DateFormat('2018-02-22') and nowStr < DateFormat('2018-02-24') and nowStr == DateFormat('2018-02-23')";
testTimeCost(runner, sb3, context);
}
private static void testTimeCost(ExpressRunner runner, String sb, IExpressContext<String, Object> context) throws Exception {
//预热编译
Object r = runner.execute(sb, context, null, true, false);
System.out.println( sb+" 运行结果:"+r);
long start = System.currentTimeMillis();
int count=100000;//运行10W次
while(count-->0) {
runner.execute(sb, context, null, true, false);
}
long cost = System.currentTimeMillis()-start;
System.out.println( sb+" 运行10万次,耗时:"+cost+"ms");
}
}
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 com.ql.util.express.InstructionSet;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
public class ErrorListTest {
public boolean isVIP(String nick)
{
return nick.contains("vip_");
}
public Integer getUserLevel(String nick)
{
if(nick.contains("vip_")){
return 3;
}
return 2;
}
@Test
public void testErrorList() throws Exception {
ExpressRunner runner = new ExpressRunner(false, false);
runner.addFunctionOfServiceMethod("isVIP", new ErrorListTest(),
"isVIP", new Class[]{String.class},"$1不是vip");
runner.addFunctionOfServiceMethod("getUserLevel", new ErrorListTest(),
"getUserLevel", new Class[]{String.class},"");
runner.addOperatorWithAlias("大于",">","用户等级不够");
runner.addOperatorWithAlias("是否VIP","isVIP","亲爱的$1,你还不是VIP用户");
testExample(runner,"isVIP('vip_11111')");
testExample(runner,"isVIP('common_11111')");
testExample(runner,"getUserLevel('vip_11111') 大于 2");
testExample(runner,"getUserLevel('common_11111') 大于 2");
}
public void testExample(ExpressRunner runner,String express) throws Exception {
IExpressContext<String, Object> context = new DefaultContext<String, Object>();
List<String> errorList = new ArrayList<String>();
Object r = runner.execute(express,context,errorList,false,false,null);
System.out.println(r);
for(int i=0;i<errorList.size();i++){
System.out.println(errorList.get(i));
}
}
}
package com.ql.util.express.test;
import org.junit.Test;
import com.ql.util.express.DefaultContext;
import com.ql.util.express.ExpressRunner;
import com.ql.util.express.IExpressContext;
import org.junit.Test;
/**
* @author tianqiao
......@@ -23,14 +22,9 @@ public class MethodInvokeTest {
null);
IExpressContext<String,Object> expressContext = new DefaultContext<String,Object>();
try{
Object r = runner.execute("getSearchResult(null)",
expressContext, null, false, false);
System.out.print("r=" + r);
}catch(Exception e){
e.printStackTrace();
throw new Exception(e);
}
Object r = runner.execute("getSearchResult(null)",
expressContext, null, false, false);
System.out.print("r=" + r);
}
@Test
......@@ -50,14 +44,10 @@ public class MethodInvokeTest {
null);
IExpressContext<String,Object> expressContext = new DefaultContext<String,Object>();
try{
Object r = runner.execute("getSearchResult(getOnlinePersonalShopInfo(123L))",
expressContext, null, false, false);
System.out.print("r=" + r);
}catch(Exception e){
e.printStackTrace();
throw new Exception(e);
}
Object r = runner.execute("getSearchResult(getOnlinePersonalShopInfo(123L))",
expressContext, null, false, false);
System.out.print("r=" + r);
}
@Test
......@@ -72,14 +62,9 @@ public class MethodInvokeTest {
String express = "info = getOnlinePersonalShopInfo(127L);";
IExpressContext<String,Object> expressContext = new DefaultContext<String,Object>();
try{
Object r = runner.execute(express,
expressContext, null, false, false);
System.out.print("r=" + r);
}catch(Exception e){
e.printStackTrace();
throw new Exception(e);
}
Object r = runner.execute(express,
expressContext, null, false, false);
System.out.print("r=" + r);
}
@Test
......@@ -94,14 +79,9 @@ public class MethodInvokeTest {
String express = "info = getOnlinePersonalShopInfo(127L);";
IExpressContext<String,Object> expressContext = new DefaultContext<String,Object>();
try{
Object r = runner.execute(express,
expressContext, null, false, false);
System.out.print("r=" + r);
}catch(Exception e){
e.printStackTrace();
throw new Exception(e);
}
Object r = runner.execute(express,
expressContext, null, false, false);
System.out.print("r=" + r);
}
@Test
......@@ -121,7 +101,6 @@ public class MethodInvokeTest {
expressContext, null, false, false);
System.out.println("r=" + r);
}catch(Exception e){
e.printStackTrace();
System.out.println("return void checked success!");
return;
}
......
package com.ql.util.express.test;
import com.ql.util.express.instruction.op.OperatorEqualsLessMore;
/**
* Created by tianqiao on 18/4/3.
*/
public class NullableOperatorEqualsLessMore extends OperatorEqualsLessMore {
public NullableOperatorEqualsLessMore(String aName) {
super(aName);
}
public NullableOperatorEqualsLessMore(String aAliasName, String aName, String aErrorInfo) {
super(aAliasName, aName, aErrorInfo);
}
public Object executeInner(Object op1,Object op2) throws Exception {
boolean result = executeInner(this.name, op1, op2);
return result;
}
public static boolean executeInner(String opStr, Object obj1, Object obj2)
throws Exception {
if(obj1==null||obj2==null){
return false;
}
return OperatorEqualsLessMore.executeInner(opStr,obj1,obj2);
}
}
\ No newline at end of file
......@@ -3,6 +3,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.Assert;
import org.junit.Test;
import java.io.BufferedReader;
......@@ -24,7 +25,8 @@ public class PrintLineExceptionTest {
Object obj = runner.execute(script, context, null, true, false);
System.out.println(obj);
}catch (Exception e){
e.printStackTrace();
// e.printStackTrace();
Assert.assertTrue(e.toString().contains("at line 7"));;
}
}
......
package com.ql.util.express.test;
import com.ql.util.express.ExpressRunner;
import com.ql.util.express.instruction.op.OperatorBase;
import com.ql.util.express.instruction.op.OperatorLike;
import org.junit.Test;
/**
* Created by tianqiao on 18/4/3.
*/
public class ReplaceComapreOpetatorTest {
@Test
public void testReplaceOperatorTest() throws Exception {
String express = "null > 1 || null < 1 || null == 1 || null >= 1 || null <= 1 ||null like '%222%'";
ExpressRunner runner = new ExpressRunner();
runner.replaceOperator("<",new NullableOperatorEqualsLessMore("<"));
runner.replaceOperator(">",new NullableOperatorEqualsLessMore(">"));
runner.replaceOperator("<=",new NullableOperatorEqualsLessMore("<="));
runner.replaceOperator(">=",new NullableOperatorEqualsLessMore(">="));
runner.replaceOperator("==",new NullableOperatorEqualsLessMore("=="));
runner.replaceOperator("!=",new NullableOperatorEqualsLessMore("!="));
runner.replaceOperator("<>",new NullableOperatorEqualsLessMore("<>"));
runner.replaceOperator("like",new NullableOperatorLike("like"));
Object r = runner.execute(express, null, null,false, false);
System.out.println(r);
}
public class NullableOperatorLike extends OperatorLike {
public NullableOperatorLike(String name) {
super(name);
}
public Object executeInner(Object op1,Object op2) throws Exception {
if(op1==null||op2==null){
return false;
}
return super.executeInner(op1,op2);
}
}
}
package com.ql.util.express.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import com.ql.util.express.ExpressRunner;
import com.ql.util.express.IExpressContext;
import com.ql.util.express.Operator;
import com.ql.util.express.instruction.OperateDataCacheManager;
public class RunExample implements ApplicationContextAware, Runnable {
private ApplicationContext applicationContext;
ExpressRunner runner;
String[][] expressTest1 = new String[][]{
{ "( 2 属于 (4,3,5)) or isVIP(\"qhlhl2010@gmail.com\") or isVIP(\"qhlhl2010@gmail.com\")", "false" },
};
String[][] expressTest = new String[][] {
{ "isVIP(\"qh\") ; isVIP(\"xuannan\"); return isVIP(\"qh\") ;", "false" },
{ "如果 三星卖家 则 'a' love 'b' 否则 'b' love 'd' ", "b{a}b" },
{"int defVar = 100; defVar = defVar + 100;", "200"},
{"int a=0; if false then a = 5 else a=10+1 ; return a ","11"},
{ " 3+ (1==2?4:3) +8","14"},
{ " 如果 (true) 则 {2+2;} 否则 {20 + 20;} ","4"},
{"'AAAAAAA' +'-' + \"\" +'' + \"B\"","AAAAAAA-B"},
//{ "System.out.println(\"ss\")", "null" },
{"unionName = new com.ql.util.express.test.BeanExample(\"张三\").unionName(\"李四\")",
"张三-李四" },
{ "group(2,3,4)", "9" },
{ "取绝对值(-5.0)", "5.0" },
{ "取绝对值TWO(-10.0)", "10.0" },
{ "max(2,3,4,10)", "10" },
{"max(2,-1)","2"},
{ "max(3,2) + 转换为大写(\"abc\")", "3ABC" },
{ "c = 1000 + 2000", "3000" },
{ "b = 累加(1,2,3)+累加(4,5,6)", "21" },
{ "三星卖家 and 消保用户 ", "true" },
{ "new String(\"12345\").length()" ,"5"},
{ "'a' love 'b' love 'c' love 'd'", "d{c{b{a}b}c}d" },
{ "10 * (10 + 1) + 2 * (3 + 5) * 2", "142" },
{ "( 2 属于 (4,3,5)) or isVIP(\"qhlhl2010@gmail.com\") or isVIP(\"qhlhl2010@gmail.com\")", "false" },
{" 1!=1 and isVIP(\"qhlhl2010@gmail.com\")","false"},
{" 1==1 or isVIP(\"qhlhl2010@gmail.com\") ","true"},
{ "abc == 1", "true" },
{ "2+2 in 2+2", "true" },
{ "true or null", "true" },
{ "null or true", "true" },
{ "null or null", "false" },
{ "true and null", "false" },
{ "null and true", "false" },
{ "null and null", "false" },
{ "'a' nor null", "a" },
{ "'a' nor 'b'", "a" },
{ " null nor null", "null" },
{ " null nor 'b'", "b" },
// { "testLong(abc)", "toString-long:1" },
{ "bean.testLongObject(abc)", "toString-LongObject:1" },
{"sum=0;n=7.3;for(i=0;i<n;i=i+1){sum=sum+i;};sum;","28"},
{"int[] abc = [1,2,3];return abc[2]","3"},
{"int[][] abc = [[11,12,13],[21,22,23]];return abc[1][2]","23"},
{"String[] abc = [\"xuannan\",\"qianghui\"];return abc[1]","qianghui"},
{"String[] abc = [\"xuannan\"+100,\"qianghui\"+100];return abc[1]","qianghui100"},
{"Object[] abc = [];return abc.length","0"},
{"Map abc = NewMap(1:1,2:2); return abc.get(1) + abc.get(2)","3"},
{"Map abc = NewMap(\"a\":1,\"b\":2); return abc.a + abc.b","3"},
{"int o1 =10; int o2=20;String k1 =\"a\";String k2 =\"b\"; Map abc = NewMap(k1:o1,k2:o2); return abc.a + abc.b","30"},
{"Map abc = NewMap(1:\"xuannan\",2:\"qianghui\"); return abc.get(1) +\"-\"+ abc.get(2)","xuannan-qianghui"},
{"List abc = NewList(1,2,3); return abc.get(1)","2"},
};
public RunExample()throws Exception{
runner = new ExpressRunner();
initialRunner(runner);
}
public RunExample(ExpressRunner runner) {
this.runner = runner;
}
public void setApplicationContext(ApplicationContext context) {
this.applicationContext = context;
}
public static void initialRunner(ExpressRunner runner) throws Exception{
runner.addOperatorWithAlias("如果", "if",null);
runner.addOperatorWithAlias("则", "then",null);
runner.addOperatorWithAlias("否则", "else",null);
runner.addOperator("love", new LoveOperator("love"));
runner.addOperatorWithAlias("属于", "in", "用户$1不在允许的范围");
runner.addOperatorWithAlias("myand", "and", "用户$1不在允许的范围");
runner.addFunction("累加", new GroupOperator("累加"));
runner.addFunction("group", new GroupOperator("group"));
runner.addFunctionOfClassMethod("isVIP", BeanExample.class.getName(),
"isVIP", new String[] { "String" }, "$1不是VIP用户");
runner.addFunctionOfClassMethod("取绝对值", Math.class.getName(), "abs",
new String[] { "double" }, null);
runner.addFunctionOfClassMethod("取绝对值TWO", Math.class.getName(), "abs",
new Class[] { double.class }, null);
runner.addFunctionOfClassMethod("转换为大写", BeanExample.class.getName(),
"upper", new String[] { "String" }, null);
runner.addFunctionOfClassMethod("testLong", BeanExample.class.getName(),
"testLong", new String[] { "long" }, null);
IExpressContext<String,Object> expressContext = new ExpressContextExample(null);
expressContext.put("b", new Integer(200));
expressContext.put("c", new Integer(300));
expressContext.put("d", new Integer(400));
expressContext.put("bean", new BeanExample());
expressContext.put("abc",1l);
expressContext.put("defVar",1000);
}
public static void main(String[] args) throws Exception {
ExpressRunner runner = new ExpressRunner(false,true);
initialRunner(runner);
new RunExample(runner).run(1); //111
//new RunExample(runner).run(100000); // 8466
for (int i = 0; i < 5; i++) {
new Thread(new RunExample(runner)).start();
}
// System.out.println(OperateDataCacheManager.getFetchCount());
}
public void run() {
run(1000000000);
}
public void run(int num) {
long start = System.currentTimeMillis();
try {
for (int j = 0; j < num; j++) {
IExpressContext<String,Object> expressContext = new ExpressContextExample( this.applicationContext);
expressContext.put("a", j);
expressContext.put("b", new Integer(200));
expressContext.put("c", new Integer(300));
expressContext.put("d", new Integer(400));
expressContext.put("bean", new BeanExample());
for (int point = 0; point < expressTest.length; point++) {
String s = expressTest[point][0];
// 批量处理的时候可以先预处理,会加快执行效率
//List<String> errorList = new ArrayList<String>();
// Object result = runner.parseInstructionSet(s);
runner.execute(s, expressContext, null, true, false);
// if (expressTest[point][1].equalsIgnoreCase("null")
// && result != null
// || result != null
// && expressTest[point][1].equalsIgnoreCase(result
// .toString()) == false) {
// throw new Exception("处理错误,计算结果与预期的不匹配");
// }
// System.out.println(s + " 执行结果 : " + result);
// System.out.println("错误信息" + errorList);
}
// System.out.println(expressContext);
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread() + "耗时:"
+ (System.currentTimeMillis() - start));
}
public void run2(int num) {
long start = System.currentTimeMillis();
try {
for (int j = 0; j < num; j++) {
String[][] expressTest = new String[][] {
// { "System.out.println(\"ss\")", "null" },
{"unionName = new com.ql.util.express.test.BeanExample(\"张三\").unionName(\"李四\")",
"张三-李四" },
{ "max(2,3,4,10)", "10" },
{ " max(3,2) + 转换为大写(\"abc\")", "3ABC" },
{ " null == null", "true" },
{ " c = 1000 + 2000", "3000" },
{ "b = 累加(1,2,3)+累加(4,5,6)", "21" },
{ "三星卖家 and 消保用户 ", "true" },
{ " ((1 + 1) 属于 (4,3,5)) and isVIP(\"qhlhl2010@gmail.com\")", "false" },
{ "group(2,3,4)", "9" }, { "取绝对值(-5)", "5.0" },
{ "2 属于(3,4)", "false" },
{ "true myand false", "false" },
{ "'a' love 'b' love 'c' love 'd'", "d{c{b{a}b}c}d" },
{ " 10 * 10 + 1 + 2 * 3 + 5 * 2", "117" },
{" 1!=1 and 2==2 and 1 == 2","false"},
{" 80 > \"300\"","true"}
};
IExpressContext<String,Object> expressContext = new ExpressContextExample( this.applicationContext);
expressContext.put("a", j);
expressContext.put("b", new Integer(200));
expressContext.put("c", new Integer(300));
expressContext.put("d", new Integer(400));
expressContext.put("bean", new BeanExample());
for (int point = 0; point < expressTest.length; point++) {
String s = expressTest[point][0];
// 批量处理的时候可以先预处理,会加快执行效率
//List<String> errorList = new ArrayList<String>();
Object result = runner.execute(s,expressContext, null, false,false);
if (expressTest[point][1].equalsIgnoreCase("null")
&& result != null
|| result != null
&& expressTest[point][1].equalsIgnoreCase(result
.toString()) == false) {
throw new Exception("处理错误,计算结果与预期的不匹配");
}
// System.out.println(s + " 执行结果 : " + result);
// System.out.println("错误信息" + errorList);
}
// System.out.println(expressContext);
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread() + "耗时:"
+ (System.currentTimeMillis() - start));
}
}
class EqualIn extends Operator{
@Override
public Object executeInner(Object[] list) throws Exception {
for (int i = 0 ; i < list.length ; i ++){
System.out.println(list[i]);
}
return Boolean.TRUE;
}
}
......@@ -41,7 +41,6 @@ public class TestSerializable {
{
e.printStackTrace();
throw e;
}
......
......@@ -17,12 +17,12 @@ public class SimpleShortCircuitLogicTest {
private ExpressRunner runner = new ExpressRunner();
public void initial() throws Exception {
public void initial() throws Exception{
runner.getOperatorFactory().getOperator("<").setErrorInfo("$1 < $2 = false");
runner.getOperatorFactory().getOperator(">").setErrorInfo("$1 > $2 = false");
}
public boolean calculateLogicTest(String expression, IExpressContext<String,Object> expressContext, List<String> errorInfo) throws Exception {
public boolean calculateLogicTest(String expression,IExpressContext<String,Object> expressContext,List<String> errorInfo) throws Exception {
Boolean result = (Boolean)runner.execute(expression, expressContext, errorInfo, true, false);
if(result.booleanValue() == true){
return true;
......@@ -57,7 +57,7 @@ public class SimpleShortCircuitLogicTest {
}
/**
* 测试非短路逻辑,并且输出s出错信息
* 测试非短路逻辑,并且输出出错信息
* @throws Exception
*/
@Test
......
package com.ql.util.express.test.newmatch;
import java.util.List;
import org.junit.Test;
import com.ql.util.express.match.QLMatchResult;
import com.ql.util.express.match.QLPattern;
import com.ql.util.express.match.QLPatternNode;
import com.ql.util.express.parse.ExpressNode;
import com.ql.util.express.parse.ExpressParse;
import com.ql.util.express.parse.KeyWordDefine4Java;
import com.ql.util.express.parse.NodeTypeManager;
import com.ql.util.express.parse.Word;
import com.ql.util.express.parse.WordSplit;
public class PatternTest {
@Test
public void testMatch() throws Exception{
String[][] defines = new String[][]{
// {"EXPRESS","(3-2)*(2-1)"},
// {"OPDATA","ABC.B"},
// {"EXPRESS_OP_L1","!ABC"},
// {"EXPRESS","!!3 * !!4 * 5 + 8 + 7 +9 like ABC"},
// {"EXPRESS_OP_L5","7+!!3*4 like 9 +!!2*4"},
// {"SELECT","select TAB.TABLE_NAME + '-ABC',TAB.COL_NAME.B * 100 from A,B"},
{"EXPRESS_OP_L4","-3*-5"},
};
NodeTypeManager manager = new NodeTypeManager(new KeyWordDefine4Java());
if( manager.findNodeType("OP_LIST").isContainerChild(manager.findNodeType("*")) ==false){
throw new Exception("寻找儿子失败");
}
ExpressParse parse = new ExpressParse(manager,null,false);
for(String[] row : defines){
Word[] words = WordSplit.parse(manager.splitWord,row[1]);
// System.out.println("单词分解结果:" + WordSplit.getPrintInfo(words,","));
List<ExpressNode> tempList = parse.transferWord2ExpressNode(null,words,null,true);
System.out.println("单词分析结果:" + ExpressParse.printInfo(tempList,","));
QLPatternNode pattern = manager.findNodeType(row[0]).getPatternNode();
QLMatchResult result =QLPattern.findMatchStatement(manager, pattern, tempList, 0);
if(result == null){
throw new Exception("没有正确的匹配:" + row[0] + ":" + row[1]);
}
System.out.println(result);
}
}
}
package com.ql.util.express.test.newmatch;
import org.junit.Test;
import com.ql.util.express.match.INodeTypeManager;
import com.ql.util.express.match.NodeTypeManagerTestImpl;
import com.ql.util.express.match.QLPattern;
import com.ql.util.express.match.QLPatternNode;
public class QLPatternDefineTest {
INodeTypeManager manager = new NodeTypeManagerTestImpl();
@Test
public void testDefine() throws Exception {
String[] defines = new String[] {
//"ABC",
//"ABC^*",
// "\\(~$ID$\\)~#()",
// "CONST$(+^$(CONST|ID))^{1:222}#SQL",
// "(CONST|ID)$((*|/)^$CONST)^*",
// "(CONST|ID)$(,~$(CONST|ID))*#PARAMETER_LIST",
// "OPDATA$(.->FIELD_CALL^$ID->CONST_STRING)^*",
// "\\(->CHILD_EXPRESS",
"OP_LEVEL1|OP_LEVEL2|OP_LEVEL3|OP_LEVEL4|OP_LEVEL5|OP_LEVEL6|OP_LEVEL7|OP_LEVEL8|OP_LEVEL9|=|LEFT_BRACKET|RIGHT_BRACKET"
};
for (String s : defines) {
QLPatternNode t = QLPattern.createPattern(manager,"ANONY_PATTERN", s);
System.out.println(t);
}
}
}
package com.ql.util.express.test.newmatch;
import org.junit.Test;
import com.ql.util.express.parse.ExpressNode;
import com.ql.util.express.parse.ExpressParse;
import com.ql.util.express.parse.KeyWordDefine4SQL;
import com.ql.util.express.parse.NodeTypeManager;
public class SqlTest {
public String[] testString ={
"select id as id2 from upp_biz_order",
"select id as id2,name as name2 from upp_biz_order where a=1",
"select id as id2,name from upp_biz_order where 1=1",
};
@Test
public void testDefine() throws Exception {
NodeTypeManager manager = new NodeTypeManager(new KeyWordDefine4SQL());
ExpressParse parse = new ExpressParse(manager,null,false);
for(String text : testString){
ExpressNode result = parse.parse(null, text, true, null);
System.out.print(result);
}
}
}
package com.ql.util.express.test.newmatch;
import java.util.ArrayList;
import java.util.List;
import com.ql.util.express.ExpressRunner;
import com.ql.util.express.IExpressContext;
import com.ql.util.express.test.ExpressContextExample;
public class TestMatch {
@org.junit.Test
public void testExpress() throws Exception{
ExpressRunner runner = new ExpressRunner(false,true);
String[][] expressTest = new String[][] {
{"1+2","3"},
{"2-1","1"},
{"2+(-1)","1"},
{"(3+3)*(4+4)/3 + 8 - 2*2","20"},
{"7==8","false"},
{"!((8>=8) && !false) || 9==9","true"},
{"a=(b=9)","9"},
{"int a = 1+3","4"},
{"(int[][] a = new int[2][2]).length","2"},
{" f = (exportDef int b = (int a = 2+3))","5"},
{"name=new String() + 100","100"},
{"name=new String((3+3)*4+\"$\") + 100","24$100"},
{"name=new String(\"xuannan-\") + 100","xuannan-100"},
{"new String[2][10].length","2"},
{"[1,2,3,4,5].length","5"},
{"[1,2,3,4,5][2]","3"},
{"[[1,2],[3,4]].length","2"},
{"1000 + new String(\"abc\").substring(1).substring(1).length() + 100","1101"},
{"new Object().getClass().getAnnotations().length","0"},
{"new Object().getClass().getMethods()[1].getName()","wait"},
// {"Object.class.getName().getClass().getMethods().length","72"},
{"1/2","0"},
{"1/(double)2","0.5"},
{"(double)1/2","0.5"},
{"((Object)\"ABC\").getClass().getName()","java.lang.String"},
{"[[1,2],[3,4]][0][1]","2"},
{"(new String[2])[1]","null"},
{"max(2,100)","100"},
{"max(max(1,2,3),min(2,100))","3"},
{"true?1:2","1"},
{"9==9?100+200:10+20","300"},
{"9==8?100+200:20+20","40"},
{"return a=100+90","190"},
{"alias xuannan qianghui","null"},
{"max 2-1,3,4+2","6"},
{"int a = 2 + 1;b=100;return a + b","103"},
{"{int a = 10;{int a = 20;} return a;}","10"},
{"{int a = 10;{a = 20;} return a;}","20"},
{"if true then return 100 else return 200","100"},
{"if true then {return 100;} else {return 200;}","100"},
{"if (false) then return 100 else return 200","200"},
{"if (1!=1) then {return 100;} else {return 200;}","200"},
{"if true then return 100","100"},
{"if true then {return 100;} ","100"},
{"if (false) then return 100","null"},
{"if (1!=1) then {return 100;}","null"},
{"if (true) return 100; else return 200","100"},
{"if (true) {return 100;} else {return 200;}","100"},
{"if (false) return 100; else return 200","200"},
{"if (1!=1) {return 100;} else {return 200;}","200"},
{"if (false) if(false) return 100;else return 200; else return 300;","300"},
{"int a = 0;{a = a + 100;}{ a= a+ 200;}","300"},
{"int a =0;for(int i=1;i<=10;i++){a = a + i;} return a;","55"},
{"int a =0;for(int i=1;i<10;i++){if(i >5) break; a = a + 100;} return a;","500"},
{"function abc(){return 100;} return abc()","100"},
{"function abc(int a,int b){ return a + b;} return abc(1+100,2*100)","301"},
{"macro abc { return a + 100;} int a = 100; return abc + 100","300"},
{"class Person(String aName,int aYear){" +
"String name = aName;" +
"int year = aYear;" +
"function getName(){return name;}" +
"function getYear(){return year;}" +
"} " +
"Person person =new Person(\"xuannan\",100);" +
"return person.getName() + '-' + person.getYear();"
,"xuannan-100"},
{"map = NewMap('ABC':100,'BCD':200,'DEF':1000 + 1000);return map.get('BCD')","200"},
{"Object[] abc = [];return abc.length","0"},
{"2 in 2","true"},
{"2 in (4,5,6)","false"},
{"(-1)","-1"},
{"/**1,2,3,4**/1+2","3"},
{"1+/**1,2,3,4**/2+3","6"},
{"(new String[3][5])[1].length","5"},
{"class ABC(com.ql.util.express.test.BeanExample bean,String name){"
+"InnerClass a = new InnerClass();"
+ "哈希值:{bean.hashCode();};"
+ "class InnerClass(){" +
"int 计数 =200;" +
"};"
+ "}" +
"return new ABC(new com.ql.util.express.test.BeanExample(),'xuannan').a.计数" ,
"200"
},
{";i=100;;","100"}
};
for (int point = 0; point < expressTest.length; point++) {
String expressStr = expressTest[point][0];
List<String> errorList = new ArrayList<String>();
IExpressContext<String,Object> expressContext = new ExpressContextExample(null);
Object result = runner.execute(expressStr,expressContext, null, false,false);
if (expressTest[point][1].equalsIgnoreCase("null")
&& result != null
|| expressTest[point][1].equalsIgnoreCase(result==null?"null":result.toString()) == false) {
throw new Exception("处理错误,计算结果与预期的不匹配:" + expressStr + " = " + result + "但是期望值是:" + expressTest[point][1]);
}
System.out.println("Example " + point + " : " + expressStr + " = " + result);
System.out.println(expressContext);
if(errorList.size() > 0){
System.out.println("\t\t系统输出的错误提示信息:" + errorList);
}
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册