写点什么

案例研究之聊聊 QLExpress 源码 (九)

发布于: 2021 年 01 月 18 日
案例研究之聊聊 QLExpress 源码 (九)

九、other

9.1、ArraySwap(数组交换)

package com.ql.util.express;
/** * 数组交换 * @author xiaochengxinyizhan */public final class ArraySwap { OperateData[] arrays; int start; public int length; public void swap(OperateData[] aArrays,int aStart ,int aLength){ this.arrays = aArrays; this.start = aStart; this.length = aLength; } public OperateData get(int i){ return this.arrays[i+start]; }
}

复制代码

9.2、CacheObject(简单的缓存对象)

package com.ql.util.express;
import java.io.Serializable;
/** * 简单的缓存对象 * @author tianqiao * */public class CacheObject implements Serializable{
private static final long serialVersionUID = -145121001676214513L; /** * 表达式名字 */ private String expressName; /** * 文本 */ private String text; /** * 指令集 */ private InstructionSet instructionSet;
public String getExpressName() { return expressName; }
public void setExpressName(String name) { this.expressName = name; }
public String getText() { return text; }
public void setText(String text) { this.text = text; }
public InstructionSet getInstructionSet() { return instructionSet; }
public void setInstructionSet(InstructionSet instructionSet) { this.instructionSet = instructionSet; }
}

复制代码

9.3、CallResult(调用结果)

package com.ql.util.express;
/** * 调用结果 * @author xiaochengxinyizhan */public class CallResult{ /** * 返回值 */ private Object returnValue; /** * 是否退出 */ private boolean isExit; public CallResult(Object aReturnValue,boolean aIsExit){ this.initial(aReturnValue, aIsExit); } public void initial(Object aReturnValue,boolean aIsExit){ this.returnValue = aReturnValue; this.isExit = aIsExit; } public void clear(){ this.returnValue = null; this.isExit = false; } public Object getReturnValue() { return returnValue; } public boolean isExit() { return isExit; } }


复制代码

9.4、DefaultContext(默认上下文)

package com.ql.util.express;
import java.util.HashMap;
/** * 警告,以后会下掉不建议使用 * @param <K> * @param <V> */@SuppressWarnings("serial")public class DefaultContext<K,V> extends HashMap<K,V> implements IExpressContext<K,V> { }

复制代码

9.5、DefaultExpressResourceLoader(默认的表达式资源加载器)

package com.ql.util.express;
import com.ql.util.express.exception.QLException;
import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;
/** * 默认的表达式资源加载器 * @author xiaochengxinyizhan */public class DefaultExpressResourceLoader implements IExpressResourceLoader { @Override public String loadExpress(String expressName) throws Exception { expressName = expressName.replace('.', '/') + ".ql"; InputStream in = Thread.currentThread().getContextClassLoader() .getResourceAsStream(expressName); if (in == null) { throw new QLException("不能找到表达式文件:" + expressName); } BufferedReader reader = new BufferedReader(new InputStreamReader(in)); StringBuilder builder = new StringBuilder(); String tmpStr = null; while ((tmpStr = reader.readLine()) != null) { builder.append(tmpStr).append("\n"); } reader.close(); in.close(); return builder.toString(); }}

复制代码

9.6、DynamicParamsUtil(动态参数工具类)

package com.ql.util.express;
import com.ql.util.express.exception.QLException;
import java.lang.reflect.Array;
/** * 动态参数工具类 * Created by tianqiao on 16/9/12. */public class DynamicParamsUtil {
public static boolean supportDynamicParams = false;
/** * 转成动态参数 * @param context * @param list * @param delaredParamsClasses * @param maybeDynamicParams * @return * @throws Exception */ public static Object[] transferDynamicParams(InstructionSetContext context, ArraySwap list, Class<?>[] delaredParamsClasses,boolean maybeDynamicParams) throws Exception {
Object[] params = null; //参数定义不符合动态参数形式 || 用户自定义不支持 || 用户传入的参数不符合 if(!maybeDynamicParams || !supportDynamicParams || !maybeDynamicParams(context,list,delaredParamsClasses)){ if(delaredParamsClasses.length != list.length){ throw new QLException("定义的参数长度与运行期传入的参数长度不一致"); } params = new Object[list.length]; for (int i = 0; i < list.length; i++) { params[i] = list.get(i).getObject(context); } return params; }
//支持不定参数的使用 function(arg1,arg2,arg3...) //list -> parameres[] // arg1,arg2 -> arg1,arg2,[] // arg1,arg2,arg3,arg4,arg5 -> arg1,arg2,[arg3,arg4,arg5] int paramLength = delaredParamsClasses.length; int beforeCount = paramLength-1; int paramsCount = list.length - beforeCount;
if(beforeCount>=0 && ((Class<?>)(delaredParamsClasses[beforeCount])).isArray() && paramsCount>=0){ Class<?>componentType = delaredParamsClasses[beforeCount].getComponentType(); params = new Object[beforeCount+1]; Object[] lastParameres = (Object[]) Array.newInstance(componentType,paramsCount); params[beforeCount] = lastParameres; for (int i = 0; i < list.length; i++) { if(i<beforeCount) { params[i] = list.get(i).getObject(context); }else{ lastParameres[i-beforeCount] = list.get(i).getObject(context); } } }else { throw new QLException("定义的参数长度与运行期传入的参数长度不一致"); } return params;
}
/** * 是否动态参数 * @param delaredParamsClasses * @return */ public static boolean maybeDynamicParams(Class<?>[] delaredParamsClasses) { int length = delaredParamsClasses.length; if(length>0 && delaredParamsClasses[length-1].isArray()) { return true; } return false; }
/** * 是否动态参数 * @param context * @param list * @param delaredParamsClasses * @return * @throws Exception */ private static boolean maybeDynamicParams(InstructionSetContext context, ArraySwap list, Class<?>[] delaredParamsClasses) throws Exception {
//长度不一致,有可能 if(delaredParamsClasses.length != list.length) { return true; } //长度一致的不定参数:不定参数的数组,只输入了一个参数并且为array,有可能 int length = list.length; Object lastParam = list.get(length-1).getObject(context); if(lastParam!=null && !lastParam.getClass().isArray()) { return true; } return false; }}

复制代码

9.7、ExportItem(输出给其它指令共享使用的对象)

package com.ql.util.express;
import java.io.Serializable;
/** * 输出给其它指令共享使用的对象 * @author xuannan * */public class ExportItem implements Serializable{ private static final long serialVersionUID = 5440012774123494760L; public static String TYPE_ALIAS ="alias"; public static String TYPE_DEF ="def"; public static String TYPE_FUNCTION ="function"; public static String TYPE_MACRO ="macro"; String globeName; String name; String type;//def,alias String desc;//类名或者别名 public ExportItem(String aName,String aType,String aDesc){ this.globeName = aName; this.name = aName; this.type =aType; this.desc = aDesc; } public ExportItem(String aGlobeName,String aName,String aType,String aDesc){ this.globeName = aGlobeName; this.name = aName; this.type =aType; this.desc = aDesc; } public String toString(){ return this.globeName + "["+ this.type +":" + this.name +" " + this.desc + "]"; } public String getGlobeName() { return globeName; } public void setGlobeName(String globeName) { this.globeName = globeName; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } }

复制代码

9.8、ExpressClassLoader(表达式类加载器)

package com.ql.util.express;
import java.lang.reflect.Array;import java.lang.reflect.Method;
/** * 表达式类加载器 * @author xiaochengxinyizhan */public class ExpressClassLoader extends ClassLoader { public ExpressClassLoader(ClassLoader parent){ super(parent); } public Class<?> loadClass(String name, byte[] code) { return this.defineClass(name, code, 0, code.length); }
@Override public synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { //System.out.print("开始查找 类" + name + "。。。。。。。。。。。"); Class<?> clasz = findLoadedClass(this, name); if (clasz != null) { //System.out.println(clasz.getClassLoader()); return clasz; } if (clasz == null) { clasz = parentLoadClass(this, name); } if (clasz == null && name.startsWith("[")) { // 进行数组处理 int index = name.indexOf("L"); String str = name.substring(0, index); String componentClassName = name.substring(index + 1, name.length() - 1); int[] dimes = new int[str.length()]; for (int i = 0; i < dimes.length; i++) { dimes[i] = 0; } try { Class<?> componentType = this.loadClass(componentClassName); clasz = Array.newInstance(componentType, dimes).getClass(); } catch (Exception e) { // 不错处理 } }
if (clasz == null) throw new ClassNotFoundException(name); return clasz; }
/** * 查找加载类 * @param loader * @param name * @return * @throws ClassNotFoundException */ public static Class<?> findLoadedClass(ClassLoader loader, String name) throws ClassNotFoundException { Method m = null; try { m = ClassLoader.class.getDeclaredMethod("findLoadedClass", new Class[] { String.class }); m.setAccessible(true); Class<?> result = (Class<?>) m.invoke(loader, new Object[] { name }); if (result == null) { result = (Class<?>) m.invoke(loader.getClass().getClassLoader(), new Object[] { name }); } if (result == null) { result = (Class<?>) m.invoke(Thread.currentThread() .getContextClassLoader(), new Object[] { name }); } return result; } catch (Exception ex) { throw new ClassNotFoundException(ex.getMessage()); } finally { if (m != null) { m.setAccessible(false); } } }
public static Class<?> parentLoadClass(ClassLoader loader, String name) throws ClassNotFoundException { // 如果存在这个类,则直接返回 Class<?> clasz = null; if (clasz == null) { try { clasz = loader.getClass().getClassLoader().loadClass(name); } catch (Throwable e) { } } if (clasz == null) try { clasz = Thread.currentThread().getContextClassLoader() .loadClass(name); } catch (Throwable e) { } return clasz; }}

复制代码

9.9、ExpressLoader(表达式装载器)

package com.ql.util.express;
import java.util.Map;import java.util.TreeMap;import java.util.concurrent.ConcurrentHashMap;
import com.ql.util.express.exception.QLException;import com.ql.util.express.instruction.FunctionInstructionSet;

/** * 表达式装载器 * * @author xuannan * */public class ExpressLoader { /** * 表达式指令集缓存 */ private ConcurrentHashMap<String, InstructionSet> expressInstructionSetCache = new ConcurrentHashMap<String, InstructionSet>(); /** * 表达式运行器 */ ExpressRunner creator; public ExpressLoader(ExpressRunner aCreator){ this.creator = aCreator; } public InstructionSet loadExpress(String expressName) throws Exception { return parseInstructionSet(expressName,this.creator.getExpressResourceLoader().loadExpress(expressName)); }
/** * 添加指令集 * @param expressName * @param set * @throws Exception */ public void addInstructionSet(String expressName, InstructionSet set) throws Exception { synchronized (expressInstructionSetCache) { if (expressInstructionSetCache.containsKey(expressName)) { throw new QLException("表达式定义重复:" + expressName); } expressInstructionSetCache.put(expressName, set); } }
/** * 解析指令集合 * @param expressName * @param expressString * @return * @throws Exception */ public InstructionSet parseInstructionSet(String expressName, String expressString) throws Exception { InstructionSet parseResult = null; if (expressInstructionSetCache.containsKey(expressName)) { throw new QLException("表达式定义重复:" + expressName); } synchronized (expressInstructionSetCache) { parseResult = this.creator.parseInstructionSet(expressString); parseResult.setName(expressName); parseResult.setGlobeName(expressName); // 需要将函数和宏定义都提取出来 for (FunctionInstructionSet item : parseResult .getFunctionInstructionSets()) { this.addInstructionSet(item.name, item.instructionSet); item.instructionSet.setName(item.name); item.instructionSet.setGlobeName(expressName+ "." + item.name); } if(parseResult.hasMain()){ this.addInstructionSet(expressName, parseResult); } } return parseResult; }
/** * 清除指令集缓存 */ public void clear(){ this.expressInstructionSetCache.clear(); }
/** * 获取指令集 * @param expressName * @return */ public InstructionSet getInstructionSet(String expressName) { return expressInstructionSetCache.get(expressName); }
/** * 获取导出信息 * @return */ public ExportItem[] getExportInfo(){ Map<String,ExportItem> result = new TreeMap<String,ExportItem>(); for(InstructionSet item:expressInstructionSetCache.values()){ for(ExportItem var:item.getExportDef()){ var.setGlobeName(item.getGlobeName() + "." + var.name); result.put(var.getGlobeName(),var); } result.put(item.getGlobeName(),new ExportItem(item.getGlobeName(), item.getName(),item.getType(),item.toString())); } return (ExportItem[])result.values().toArray(new ExportItem[0]); }}

复制代码

9.10、ExpressRemoteCacheRunner(远程缓存对象)

package com.ql.util.express;
import java.util.List;
import org.apache.commons.logging.Log;
/** * 远程缓存对象 * @author tianqiao * */public abstract class ExpressRemoteCacheRunner {

/** * 加载缓存 * @param expressName * @param text */ public void loadCache(String expressName,String text){ InstructionSet instructionSet; try { instructionSet = getExpressRunner().parseInstructionSet(text); CacheObject cache = new CacheObject(); cache.setExpressName(expressName); cache.setText(text); cache.setInstructionSet(instructionSet); this.putCache(expressName, cache); } catch (Exception e) { throw new RuntimeException("解析指令并缓存过程出现错误.",e); } }
/** * 执行 * @param name * @param context * @param errorList * @param isTrace * @param isCatchException * @param aLog * @return */ public Object execute(String name,IExpressContext<String,Object> context, List<String> errorList, boolean isTrace,boolean isCatchException, Log aLog){ try { CacheObject cache = (CacheObject) this.getCache(name); if(cache==null){ throw new RuntimeException("未获取到缓存对象."); } return getExpressRunner().execute(cache.getInstructionSet(), context, errorList, isTrace, isCatchException, aLog); } catch (Exception e) { throw new RuntimeException("获取缓存信息,并且执行指令集出现错误.",e); } } /** * 获取执行器ExpressRunner * @return */ public abstract ExpressRunner getExpressRunner(); /** * 获取缓存对象 * @param key * @return */ public abstract Object getCache(String key); /** * 放置缓存的对象 * @param key * @param object */ public abstract void putCache(String key,Object object );
}

复制代码

9.11、ExpressRunner(语法分析和计算的入口类)

package com.ql.util.express;
import java.util.*;import java.util.regex.Matcher;import java.util.regex.Pattern;
import com.ql.util.express.config.QLExpressTimer;import com.ql.util.express.exception.QLCompileException;import com.ql.util.express.exception.QLException;import com.ql.util.express.exception.QLTimeOutException;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;
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;
/** * 语法分析和计算的入口类 * @author xuannan * */public class ExpressRunner {
private static final Log log = LogFactory.getLog(ExpressRunner.class); private static final String GLOBAL_DEFINE_NAME="全局定义"; /** * 是否输出所有的跟踪信息,同时还需要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; /** * 语法定义的管理器 */ private NodeTypeManager manager; /** * 操作符的管理器 */ private OperatorFactory operatorManager; /** * 语法分析器 */ private ExpressParse parse ;
/** * 缺省的Class查找的包管理器 */ ExpressPackage rootExpressPackage = new ExpressPackage(null);
public AppendingClassMethodManager getAppendingClassMethodManager() { return appendingClassMethodManager; }
private AppendingClassMethodManager appendingClassMethodManager;
public AppendingClassFieldManager getAppendingClassFieldManager() { return appendingClassFieldManager; }
private AppendingClassFieldManager appendingClassFieldManager;
private ThreadLocal<IOperateDataCache> m_OperateDataObjectCache = new ThreadLocal<IOperateDataCache>(){ protected IOperateDataCache initialValue() { return new OperateDataCacheImpl(30); } }; public IOperateDataCache getOperateDataCache(){ return this.m_OperateDataObjectCache.get(); }
public ExpressRunner(){ this(false,false); } /** * * @param aIsPrecise 是否需要高精度计算支持 * @param aIstrace 是否跟踪执行指令的过程 */ public ExpressRunner(boolean aIsPrecise,boolean aIstrace){ this(aIsPrecise,aIstrace,new DefaultExpressResourceLoader(),null); } public ExpressRunner(boolean aIsPrecise,boolean aIstrace,NodeTypeManager aManager){ this(aIsPrecise,aIstrace,new DefaultExpressResourceLoader(),aManager); } /** * * @param aIsPrecise 是否需要高精度计算支持 * @param aIstrace 是否跟踪执行指令的过程 * @param aExpressResourceLoader 表达式的资源装载器 */ public ExpressRunner(boolean aIsPrecise,boolean aIstrace,IExpressResourceLoader aExpressResourceLoader,NodeTypeManager aManager){ this.isTrace = aIstrace; this.isPrecise = aIsPrecise; this.expressResourceLoader = aExpressResourceLoader; if(aManager == null){ manager = new NodeTypeManager(); }else{ manager = aManager; } this.operatorManager = new OperatorFactory(this.isPrecise); this.loader = new ExpressLoader(this); this.parse = new ExpressParse(manager,this.expressResourceLoader,this.isPrecise); rootExpressPackage.addPackage("java.lang"); rootExpressPackage.addPackage("java.util"); this.addSystemFunctions(); 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")); }
/** * 获取语法定义的管理器 * @return */ public NodeTypeManager getNodeTypeManager(){ return this.manager; } /** * 获取操作符号管理器 * @return */ public OperatorFactory getOperatorFactory(){ return this.operatorManager; } public IExpressResourceLoader getExpressResourceLoader(){ return this.expressResourceLoader; } /** * 添加宏定义 例如: macro 玄难 { abc(userinfo.userId);} * @param macroName:玄难 * @param express :abc(userinfo.userId); * @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{ if(groupName == null || groupName.trim().length() ==0){ groupName = GLOBAL_DEFINE_NAME; } this.loader.parseInstructionSet(groupName,express); } /** * 装载文件中定义的Express * @param expressName * @throws Exception */ public void loadExpress(String expressName) throws Exception { this.loader.loadExpress(expressName); } /** * 添加函数定义 * @param name 函数名称 * @param op 对应的操作实现类 */ public void addFunction(String name, OperatorBase op) { this.operatorManager.addOperator(name, op); this.manager.addFunctionName(name); };
/** * 添加函数定义扩展类的方法 * @param name * @param bindingClass * @param op */ public void addFunctionAndClassMethod(String name,Class<?>bindingClass, OperatorBase op) { this.addFunction(name,op); this.addClassMethod(name,bindingClass,op);
};
/** * 添加类的方法 * @param field * @param bindingClass * @param op */ public void addClassField(String field,Class<?>bindingClass,Operator op) { this.addClassField(field,bindingClass,Object.class,op); }
/** * 添加类的方法 * @param field * @param bindingClass * @param returnType * @param op */ public void addClassField(String field,Class<?>bindingClass,Class<?>returnType,Operator op) { if(this.appendingClassFieldManager==null){ this.appendingClassFieldManager = new AppendingClassFieldManager(); } this.appendingClassFieldManager.addAppendingField(field, bindingClass,returnType,op); }
/** * 添加类的方法 * @param name * @param bindingClass * @param op */ public void addClassMethod(String name,Class<?>bindingClass,OperatorBase op) { if(this.appendingClassMethodManager==null){ this.appendingClassMethodManager = new AppendingClassMethodManager(); } this.appendingClassMethodManager.addAppendingMethod(name, bindingClass, op); } /** * 获取函数定义,通过函数定义可以拿到参数的说明信息 * @param name 函数名称 * @return */ public OperatorBase getFunciton(String name){ return this.operatorManager.getOperator(name); } /** * 添加一个类的函数定义,例如:Math.abs(double) 映射为表达式中的 "取绝对值(-5.0)" * @param name 函数名称 * @param aClassName 类名称 * @param aFunctionName 类中的方法名称 * @param aParameterClassTypes 方法的参数类型名称 * @param errorInfo 如果函数执行的结果是false,需要输出的错误信息 * @throws Exception */ public void addFunctionOfClassMethod(String name, String aClassName, String aFunctionName, Class<?>[] aParameterClassTypes, String errorInfo) throws Exception { this.addFunction(name, new OperatorSelfDefineClassFunction(name, 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 函数名称 * @param aClassName 类名称 * @param aFunctionName 类中的方法名称 * @param aParameterClassTypes 方法的参数类型名称 * @param aParameterDesc 方法的参数说明 * @param aParameterAnnotation 方法的参数注解 * @param errorInfo 如果函数执行的结果是false,需要输出的错误信息 * @throws Exception */ public void addFunctionOfClassMethod(String name, String aClassName, String aFunctionName, Class<?>[] aParameterClassTypes, String[] aParameterDesc,String[] aParameterAnnotation, String errorInfo) throws Exception { this.addFunction(name, new OperatorSelfDefineClassFunction(name, aClassName, aFunctionName, aParameterClassTypes,aParameterDesc,aParameterAnnotation, errorInfo));
} /** * 添加一个类的函数定义,例如:Math.abs(double) 映射为表达式中的 "取绝对值(-5.0)" * @param name 函数名称 * @param aClassName 类名称 * @param aFunctionName 类中的方法名称 * @param aParameterTypes 方法的参数类型名称 * @param errorInfo 如果函数执行的结果是false,需要输出的错误信息 * @throws Exception */ public void addFunctionOfClassMethod(String name, String aClassName, String aFunctionName, String[] aParameterTypes, String errorInfo) throws Exception { this.addFunction(name, new OperatorSelfDefineClassFunction(name, aClassName, aFunctionName, aParameterTypes, null,null,errorInfo)); } /** * 添加一个类的函数定义,例如:Math.abs(double) 映射为表达式中的 "取绝对值(-5.0)" * @param name 函数名称 * @param aClassName 类名称 * @param aFunctionName 类中的方法名称 * @param aParameterTypes 方法的参数类型名称 * @param aParameterDesc 方法的参数说明 * @param aParameterAnnotation 方法的参数注解 * @param errorInfo 如果函数执行的结果是false,需要输出的错误信息 * @throws Exception */ public void addFunctionOfClassMethod(String name, String aClassName, String aFunctionName, String[] aParameterTypes, String[] aParameterDesc,String[] aParameterAnnotation, String errorInfo) throws Exception { this.addFunction(name, new OperatorSelfDefineClassFunction(name, aClassName, aFunctionName, aParameterTypes, aParameterDesc,aParameterAnnotation,errorInfo));
} /** * 用于将一个用户自己定义的对象(例如Spring对象)方法转换为一个表达式计算的函数 * @param name * @param aServiceObject * @param aFunctionName * @param aParameterClassTypes * @param errorInfo * @throws Exception */ public void addFunctionOfServiceMethod(String name, Object aServiceObject, String aFunctionName, Class<?>[] aParameterClassTypes, String errorInfo) throws Exception { this.addFunction(name, new OperatorSelfDefineServiceFunction(name, aServiceObject, aFunctionName, aParameterClassTypes,null,null, errorInfo));
} /** * 用于将一个用户自己定义的对象(例如Spring对象)方法转换为一个表达式计算的函数 * @param name * @param aServiceObject * @param aFunctionName * @param aParameterClassTypes * @param aParameterDesc 方法的参数说明 * @param aParameterAnnotation 方法的参数注解 * @param errorInfo * @throws Exception */ public void addFunctionOfServiceMethod(String name, Object aServiceObject, String aFunctionName, Class<?>[] aParameterClassTypes, String[] aParameterDesc,String[] aParameterAnnotation, String errorInfo) throws Exception { this.addFunction(name, new OperatorSelfDefineServiceFunction(name, aServiceObject, aFunctionName, aParameterClassTypes,aParameterDesc,aParameterAnnotation, errorInfo));
} /** * 用于将一个用户自己定义的对象(例如Spring对象)方法转换为一个表达式计算的函数 * @param name * @param aServiceObject * @param aFunctionName * @param aParameterTypes * @param errorInfo * @throws Exception */ public void addFunctionOfServiceMethod(String name, Object aServiceObject, String aFunctionName, String[] aParameterTypes, String errorInfo) throws Exception { this.addFunction(name, new OperatorSelfDefineServiceFunction(name, aServiceObject, aFunctionName, aParameterTypes,null,null, errorInfo));
} public void addFunctionOfServiceMethod(String name, Object aServiceObject, String aFunctionName, String[] aParameterTypes, String[] aParameterDesc,String[] aParameterAnnotation, String errorInfo) throws Exception { this.addFunction(name, new OperatorSelfDefineServiceFunction(name, aServiceObject, aFunctionName, aParameterTypes,aParameterDesc,aParameterAnnotation, errorInfo));
} /** * 添加操作符号,此操作符号的优先级与 "*"相同,语法形式也是 data name data * @param name * @param op * @throws Exception */ public void addOperator(String name,Operator op) throws Exception { this.addOperator(name, "*", op); } /** * 添加操作符号,此操作符号与给定的参照操作符号在优先级别和语法形式上一致 * @param name 操作符号名称 * @param aRefOpername 参照的操作符号,例如 "+","--"等 * @param op * @throws Exception */ public void addOperator(String name,String aRefOpername,Operator op) throws Exception { this.manager.addOperatorWithLevelOfReference(name, aRefOpername); this.operatorManager.addOperator(name, op); }
/** * 添加操作符和关键字的别名,同时对操作符可以指定错误信息。 * 例如:addOperatorWithAlias("加","+",null) * @param keyWordName * @param realKeyWordName * @param errorInfo * @throws Exception */ public void addOperatorWithAlias(String keyWordName, String realKeyWordName, String errorInfo) throws Exception { if(errorInfo != null && errorInfo.trim().length() == 0){ errorInfo = null; } //添加函数别名 if(this.manager.isFunction(realKeyWordName)){ this.manager.addFunctionName(keyWordName); this.operatorManager.addOperatorWithAlias(keyWordName, realKeyWordName, errorInfo); return; } NodeType realNodeType = this.manager.findNodeType(realKeyWordName); if(realNodeType == null){ throw new QLException("关键字:" + realKeyWordName +"不存在"); } boolean isExist = this.operatorManager.isExistOperator(realNodeType.getName()); if(isExist == false && errorInfo != null){ throw new QLException("关键字:" + realKeyWordName +"是通过指令来实现的,不能设置错误的提示信息,errorInfo 必须是 null"); } if(isExist == false || errorInfo == null){ //不需要新增操作符号,只需要建立一个关键子即可 this.manager.addOperatorWithRealNodeType(keyWordName, realNodeType.getName()); }else{ this.manager.addOperatorWithLevelOfReference(keyWordName, realNodeType.getName()); this.operatorManager.addOperatorWithAlias(keyWordName, realNodeType.getName(), errorInfo); } } /** * 替换操作符处理 * @param name */ public OperatorBase replaceOperator(String name,OperatorBase op){ return this.operatorManager.replaceOperator(name, op); }
public ExpressPackage getRootExpressPackage(){ return this.rootExpressPackage; } /** * 清除缓存 */ public void clearExpressCache() { synchronized (expressInstructionSetCache) { this.expressInstructionSetCache.clear(); } } /** * 根据表达式的名称进行执行 * @param name * @param context * @param errorList * @param isTrace * @param isCatchException * @param aLog * @return * @throws Exception */ public Object executeByExpressName(String name,IExpressContext<String,Object> context, List<String> errorList, boolean isTrace,boolean isCatchException, Log aLog) throws Exception { return InstructionSetRunner.executeOuter(this,this.loader.getInstructionSet(name),this.loader,context, errorList, isTrace,isCatchException,aLog,false);
}
/** * 执行指令集(兼容老接口,请不要自己管理指令缓存,直接使用execute(InstructionSet instructionSets,....... ) * 清理缓存可以使用clearExpressCache()函数 * @param instructionSets * @param context * @param errorList * @param isTrace * @param isCatchException * @param aLog * @return * @throws Exception */ @Deprecated public Object execute(InstructionSet[] instructionSets,IExpressContext<String,Object> context, List<String> errorList, boolean isTrace,boolean isCatchException, Log aLog) throws Exception { return InstructionSetRunner.executeOuter(this,instructionSets[0],this.loader,context, errorList, isTrace,isCatchException,aLog,false); }
/** * 执行指令集 * @param instructionSets * @param context * @param errorList * @param isTrace * @param isCatchException * @param aLog * @return * @throws Exception */ public Object execute(InstructionSet instructionSets,IExpressContext<String,Object> context, List<String> errorList, boolean isTrace,boolean isCatchException, Log aLog) throws Exception { return InstructionSetRunner.executeOuter(this,instructionSets,this.loader,context, errorList, isTrace,isCatchException,aLog,false); } /** * 执行一段文本 * @param expressString 程序文本 * @param context 执行上下文 * @param errorList 输出的错误信息List * @param isCache 是否使用Cache中的指令集 * @param isTrace 是否输出详细的执行指令信息 * @param timeoutMillis 超时毫秒时间 * @return * @throws Exception */ public Object execute(String expressString, IExpressContext<String,Object> context, List<String> errorList, boolean isCache, boolean isTrace,long timeoutMillis) throws Exception { //设置超时毫秒时间 QLExpressTimer.setTimer(timeoutMillis); try { return this.execute(expressString, context, errorList, isCache, isTrace, null); }finally { QLExpressTimer.reset(); } }
/** * 执行一段文本 * @param expressString 程序文本 * @param context 执行上下文 * @param errorList 输出的错误信息List * @param isCache 是否使用Cache中的指令集 * @param isTrace 是否输出详细的执行指令信息 * @return * @throws Exception */ public Object execute(String expressString, IExpressContext<String,Object> context, List<String> errorList, boolean isCache, boolean isTrace) throws Exception { return this.execute(expressString, context, errorList, isCache, isTrace, null); } /** * 执行一段文本 * @param expressString 程序文本 * @param context 执行上下文 * @param errorList 输出的错误信息List * @param isCache 是否使用Cache中的指令集 * @param isTrace 是否输出详细的执行指令信息 * @param aLog 输出的log * @return * @throws Exception */ public Object execute(String expressString, IExpressContext<String,Object> context, List<String> errorList, boolean isCache, boolean isTrace, Log aLog) throws Exception { InstructionSet parseResult = null; if (isCache == true) { parseResult = expressInstructionSetCache.get(expressString); if (parseResult == null) { synchronized (expressInstructionSetCache) { parseResult = expressInstructionSetCache.get(expressString); if (parseResult == null) { parseResult = this.parseInstructionSet(expressString); expressInstructionSetCache.put(expressString, parseResult); } } } } else { parseResult = this.parseInstructionSet(expressString); } return InstructionSetRunner.executeOuter(this,parseResult,this.loader,context, errorList, 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 * @return * @throws Exception */ public InstructionSet parseInstructionSet(String text) throws Exception { 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()); } }
ExpressNode root = this.parse.parse(this.rootExpressPackage, text, isTrace, selfDefineClass); InstructionSet result = createInstructionSet(root, "main"); if (this.isTrace && log.isDebugEnabled()) { log.debug(result); } return result; }catch (QLCompileException e){ throw e; }catch (Exception e){ throw new QLCompileException("编译异常:\n"+text,e); } } /** * 输出全局定义信息 * @return */ public ExportItem[] getExportInfo(){ return this.loader.getExportInfo(); }
/** * 优先从本地指令集缓存获取指令集,没有的话生成并且缓存在本地 * @param expressString * @return * @throws Exception */ public InstructionSet getInstructionSetFromLocalCache(String expressString) throws Exception { InstructionSet parseResult = expressInstructionSetCache.get(expressString); if (parseResult == null) { synchronized (expressInstructionSetCache) { parseResult = expressInstructionSetCache.get(expressString); if (parseResult == null) { parseResult = this.parseInstructionSet(expressString); expressInstructionSetCache.put(expressString, parseResult); } } } return parseResult; }
public InstructionSet createInstructionSet(ExpressNode root, String type) throws Exception { InstructionSet result = new InstructionSet(type); createInstructionSet(root, result); return result; }
public void createInstructionSet(ExpressNode root, InstructionSet result) throws Exception { Stack<ForRelBreakContinue> forStack = new Stack<ForRelBreakContinue>(); createInstructionSetPrivate(result, forStack, root, true); if (forStack.size() > 0) { throw new QLCompileException("For处理错误"); } }
public boolean createInstructionSetPrivate(InstructionSet result, Stack<ForRelBreakContinue> forStack, ExpressNode node, boolean isRoot) throws Exception { InstructionFactory factory = InstructionFactory .getInstructionFactory(node.getInstructionFactory()); boolean hasLocalVar = factory.createInstruction(this,result, forStack, node, isRoot); return hasLocalVar; } /** * 获取一个表达式需要的外部变量名称列表 * @param express * @return * @throws Exception */ public String[] getOutVarNames(String express) throws Exception{ return this.parseInstructionSet(express).getOutAttrNames(); }
public String[] getOutFunctionNames(String express) throws Exception{ return this.parseInstructionSet(express).getOutFunctionNames(); }

public boolean isShortCircuit() { return isShortCircuit; } 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; } }}

复制代码

9.12、ExpressUtil(表达式工具类)

package com.ql.util.express;
import com.ql.util.express.config.QLExpressRunStrategy;import com.ql.util.express.exception.QLException;import org.apache.commons.beanutils.PropertyUtils;
import java.lang.reflect.*;import java.math.BigDecimal;import java.util.ArrayList;import java.util.List;import java.util.Map;import java.util.concurrent.ConcurrentHashMap;import java.util.regex.Matcher;import java.util.regex.Pattern;

/** * 表达式工具类 * * @author qhlhl2010@gmail.com * */@SuppressWarnings("unchecked")public class ExpressUtil { public static final String DT_STRING = "String"; public static final String DT_SHORT = "Short"; public static final String DT_INTEGER = "Integer"; public static final String DT_LONG = "Long"; public static final String DT_DOUBLE = "Double"; public static final String DT_FLOAT = "Float"; public static final String DT_BYTE = "Byte"; public static final String DT_CHAR = "Char"; public static final String DT_BOOLEAN = "Boolean"; public static final String DT_DATE = "Date"; public static final String DT_TIME = "Time"; public static final String DT_DATETIME = "DateTime"; public static final String DT_OBJECT = "Object";
public static final String DT_short = "short"; public static final String DT_int = "int"; public static final String DT_long = "long"; public static final String DT_double = "double"; public static final String DT_float = "float"; public static final String DT_byte = "byte"; public static final String DT_char = "char"; public static final String DT_boolean = "boolean";
public static Map<String,Object> methodCache = new ConcurrentHashMap<String, Object>(); public static Class<?>[][] classMatchs =new Class[][]{ //原始数据类型 {BigDecimal.class,double.class},{BigDecimal.class,float.class},{BigDecimal.class,long.class},{BigDecimal.class,int.class}, {BigDecimal.class,short.class},{BigDecimal.class,byte.class}, {double.class,float.class},{double.class,long.class},{double.class,int.class}, {double.class,short.class},{double.class,byte.class},{double.class,BigDecimal.class}, {float.class,long.class}, {float.class,int.class}, {float.class,short.class},{float.class,byte.class},{float.class,BigDecimal.class}, {long.class,int.class}, {long.class,short.class}, {long.class,byte.class}, {int.class,short.class}, {int.class,byte.class}, {short.class,byte.class}, //--------- {char.class,Character.class},{Character.class,char.class}, {boolean.class,Boolean.class},{Boolean.class,boolean.class} };
/** * 获取简单的数据类型 * @param aClass * @return */ public static Class<?> getSimpleDataType(Class<?> aClass) { if (aClass.isPrimitive()){ if (Integer.class.equals(aClass)) return Integer.TYPE; if (Short.class.equals(aClass)) return Short.TYPE; if (Long.class.equals(aClass)) return Long.TYPE; if (Double.class.equals(aClass)) return Double.TYPE; if (Float.class.equals(aClass)) return Float.TYPE; if (Byte.class.equals(aClass)) return Byte.TYPE; if (Character.class.equals(aClass)) return Character.TYPE; if (Boolean.class.equals(aClass)) return Boolean.TYPE; return aClass; }else{ return aClass; } }
/** * 是否可分配 * @param target * @param source * @return */ public static boolean isAssignable(Class<?> target, Class<?> source) { if (target == source) return true; if(target.isArray() && source.isArray()){ return isAssignable(target.getComponentType(),source.getComponentType()); } return isAssignablePrivate(target,source); }
/** * 是否是私有权限 * @param target * @param source * @return */ public static boolean isAssignablePrivate(Class<?> target, Class<?> source) { if (target == source) return true;
if (target == null) return false; if (source == null)//null转换 return !target.isPrimitive(); if (target.isAssignableFrom(source) == true){ return true; } if(source.isPrimitive() && target == Object.class){ return true; } if (target.isPrimitive() == false) { if (target == Byte.class) target = byte.class; else if (target == Short.class) target = short.class; else if (target == Integer.class) target = int.class; else if (target == Long.class) target = long.class; else if (target == Float.class) target = float.class; else if (target == Double.class) target = double.class; } if (source.isPrimitive() == false) { if (source == Byte.class) source = byte.class; else if (source == Short.class) source = short.class; else if (source == Integer.class) source = int.class; else if (source == Long.class) source = long.class; else if (source == Float.class) source = float.class; else if (source == Double.class) source = double.class; } if (target == source)// 转换后需要在判断一下 return true;
for (int i = 0; i < classMatchs.length; i++) { if (target == classMatchs[i][0] && source == classMatchs[i][1]) { return true; } } return false; } public static boolean isAssignableOld(Class<?> lhsType, Class<?> rhsType) { if (lhsType == null) return false; if (rhsType == null) return !lhsType.isPrimitive();
if (lhsType.isPrimitive() && rhsType.isPrimitive()) { if (lhsType == rhsType) return true;
if ((rhsType == Byte.TYPE) && (lhsType == Short.TYPE || lhsType == Integer.TYPE || lhsType == Long.TYPE || lhsType == Float.TYPE || lhsType == Double.TYPE)) return true;
if ((rhsType == Short.TYPE) && (lhsType == Integer.TYPE || lhsType == Long.TYPE || lhsType == Float.TYPE || lhsType == Double.TYPE)) return true;
if ((rhsType == Character.TYPE) && (lhsType == Integer.TYPE || lhsType == Long.TYPE || lhsType == Float.TYPE || lhsType == Double.TYPE)) return true;
if ((rhsType == Integer.TYPE) && (lhsType == Long.TYPE || lhsType == Float.TYPE || lhsType == Double.TYPE)) return true;
if ((rhsType == Long.TYPE) && (lhsType == Float.TYPE || lhsType == Double.TYPE)) return true;
if ((rhsType == Float.TYPE) && (lhsType == Double.TYPE)) return true; } else if (lhsType.isAssignableFrom(rhsType)) return true;
return false; }
public static boolean isSignatureAssignable(Class<?>[] from, Class<?>[] to) { for (int i = 0; i < from.length; i++) if (!isAssignable(to[i], from[i])) return false; return true; }
public static int findMostSpecificSignature(Class<?>[] idealMatch, Class<?>[][] candidates) { Class<?>[] bestMatch = null; int bestMatchIndex = -1;
for (int i = candidates.length - 1; i >= 0; i--) {// 先从基类开始查找 Class<?>[] targetMatch = candidates[i]; if (ExpressUtil.isSignatureAssignable(idealMatch, targetMatch) && ((bestMatch == null) || ExpressUtil .isSignatureAssignable(targetMatch, bestMatch))) { bestMatch = targetMatch; bestMatchIndex = i; } }
if (bestMatch != null) return bestMatchIndex; else return -1; }
public static String createCacheKey(Class<?> aBaseClass, String aMethodName, Class<?>[] aTypes, boolean aPublicOnly, boolean aIsStatic) { StringBuilder builder = new StringBuilder();// builder.append(aPublicOnly).append("-").append(aIsStatic).append("-"); builder.append(aBaseClass.getName()).append(".").append(aMethodName) .append("."); if (aTypes == null) { builder.append("null"); } else { for (int i = 0; i < aTypes.length; i++) { if (i > 0) { builder.append(","); } if(aTypes[i]== null){ builder.append("null"); }else{ builder.append(aTypes[i].getName()); } } }// builder.append(")"); return builder.toString();
} public static Method findMethodWithCache(Class<?> baseClass, String methodName, Class<?>[] types, boolean publicOnly, boolean isStatic){ String key = createCacheKey(baseClass, methodName, types, publicOnly, isStatic); Object result = methodCache.get(key); if(result == null){ result = findMethod(baseClass, methodName, types, publicOnly, isStatic); if(result == null){ methodCache.put(key, void.class); }else{ ((Method)result).setAccessible(true); methodCache.put(key,result); } }else if(result == void.class){ result = null; } return (Method)result; } public static Method findMethod(Class<?> baseClass, String methodName, Class<?>[] types, boolean publicOnly, boolean isStatic) { List<Method> candidates = gatherMethodsRecursive(baseClass, methodName, types.length, publicOnly, isStatic, null /* candidates */); Method method = findMostSpecificMethod(types, (Method[]) candidates .toArray(new Method[0])); return method; }
public static Constructor<?> findConstructorWithCache(Class<?> baseClass, Class<?>[] types) { String key = createCacheKey(baseClass, "new", types, true, false); Constructor<?> result = (Constructor<?>)methodCache.get(key); if(result == null){ result = findConstructor(baseClass,types); methodCache.put(key, result); } return result; } private static Constructor<?> findConstructor(Class<?> baseClass, Class<?>[] types) { Constructor<?>[] constructors = baseClass.getConstructors(); List<Constructor<?>> constructorList = new ArrayList<Constructor<?>>(); List<Class<?>[]> listClass = new ArrayList<Class<?>[]>(); for (int i = 0; i < constructors.length; i++) { if (constructors[i].getParameterTypes().length == types.length) { listClass.add(constructors[i].getParameterTypes()); constructorList.add(constructors[i]); } }
int match = findMostSpecificSignature(types, (Class[][]) listClass .toArray(new Class[0][])); return match == -1 ? null : constructorList.get(match); }
public static Method findMostSpecificMethod(Class<?>[] idealMatch, Method[] methods) { Class<?>[][] candidateSigs = new Class[methods.length][]; for (int i = 0; i < methods.length; i++) candidateSigs[i] = methods[i].getParameterTypes();
int match = findMostSpecificSignature(idealMatch, candidateSigs); return match == -1 ? null : methods[match];
}
private static List<Method> gatherMethodsRecursive(Class<?> baseClass, String methodName, int numArgs, boolean publicOnly, boolean isStatic, List<Method> candidates) { if (candidates == null) candidates = new ArrayList<Method>();
addCandidates(baseClass.getDeclaredMethods(), methodName, numArgs, publicOnly, isStatic, candidates);
Class<?>[] intfs = baseClass.getInterfaces(); for (int i = 0; i < intfs.length; i++) gatherMethodsRecursive(intfs[i], methodName, numArgs, publicOnly, isStatic, candidates);
Class<?> superclass = baseClass.getSuperclass(); if (superclass != null) gatherMethodsRecursive(superclass, methodName, numArgs, publicOnly, isStatic, candidates);
return candidates; }
private static List<Method> addCandidates(Method[] methods, String methodName, int numArgs, boolean publicOnly, boolean isStatic, List<Method> candidates) { for (int i = 0; i < methods.length; i++) { Method m = methods[i]; if (m.getName().equals(methodName) && (m.getParameterTypes().length == numArgs) && (publicOnly == false || isPublic(m) && (isStatic == false || isStatic(m)))) candidates.add(m); } return candidates; }
public static boolean isPublic(Class<?> c) { return Modifier.isPublic(c.getModifiers()); }
public static boolean isPublic(Method m) { return Modifier.isPublic(m.getModifiers()); }
public static boolean isStatic(Method m) { return Modifier.isStatic(m.getModifiers()); }
public static Class<?> getJavaClass(String type) { int index = type.indexOf("[]"); if (index < 0) return getJavaClassInner(type);
StringBuilder arrayString = new StringBuilder(); arrayString.append("["); String baseType = type.substring(0, index); while ((index = type.indexOf("[]", index + 2)) >= 0) { arrayString.append("["); } Class<?> baseClass = getJavaClassInner(baseType);
try { String baseName = ""; if (baseClass.isPrimitive() == false) { return loadClass(arrayString.toString() + "L" + baseClass.getName() + ";"); } else { if (baseClass.equals(boolean.class)) { baseName = "Z"; } else if (baseClass.equals(byte.class)) { baseName = "B"; } else if (baseClass.equals(char.class)) { baseName = "C"; } else if (baseClass.equals(double.class)) { baseName = "D"; } else if (baseClass.equals(float.class)) { baseName = "F"; } else if (baseClass.equals(int.class)) { baseName = "I"; } else if (baseClass.equals(long.class)) { baseName = "J"; } else if (baseClass.equals(short.class)) { baseName = "S"; } return loadClass(arrayString.toString() + baseName); } } catch (ClassNotFoundException ex) { throw new RuntimeException(ex); }
}
public static Class<?> getJavaClassInner(String type) {
if (type.equals(DT_STRING)) return String.class; if (type.equals(DT_SHORT)) return Short.class; if (type.equals(DT_INTEGER)) return Integer.class; if (type.equals(DT_LONG)) return Long.class; if (type.equals(DT_DOUBLE)) return Double.class; if (type.equals(DT_FLOAT)) return Float.class; if (type.equals(DT_BYTE)) return Byte.class; if (type.equals(DT_CHAR) || type.equals("Character")) return Character.class; if (type.equals(DT_BOOLEAN)) return Boolean.class; if (type.equals(DT_DATE)) return java.sql.Date.class; if (type.equals(DT_TIME)) return java.sql.Time.class; if (type.equals(DT_DATETIME)) return java.sql.Timestamp.class; if (type.equals(DT_OBJECT)) return Object.class; if (type.equals(DT_short)) return short.class; if (type.equals(DT_int)) return int.class; if (type.equals(DT_long)) return long.class; if (type.equals(DT_double)) return double.class; if (type.equals(DT_float)) return float.class; if (type.equals(DT_byte)) return byte.class; if (type.equals(DT_char)) return char.class; if (type.equals(DT_boolean)) return boolean.class; try { return loadClass(type); } catch (ClassNotFoundException ex) { throw new RuntimeException(ex); } }
public static String getClassName(Class<?> className) { if(className == null){ return null; } String name = className.getName(); return getClassName(name); }
private static String getClassName(String name) { String arrays = ""; if (name.indexOf("[") >= 0) { int point = 0; while (name.charAt(point) == '[') { arrays = arrays + "[]"; ++point; } if (name.charAt(point) == 'L') { name = name.substring(point + 1, name.length() - 1); } else if (name.charAt(point) == 'Z') { name = "boolean"; } else if (name.charAt(point) == 'B') { name = "byte"; } else if (name.charAt(point) == 'C') { name = "char"; } else if (name.charAt(point) == 'D') { name = "double"; } else if (name.charAt(point) == 'F') { name = "float"; } else if (name.charAt(point) == 'I') { name = "int"; } else if (name.charAt(point) == 'J') { name = "long"; } else if (name.charAt(point) == 'S') { name = "short"; } } int index = name.lastIndexOf('.'); if (index > 0 && name.substring(0, index).equals("java.lang") == true) { name = name.substring(index + 1); } name = name + arrays; return name; } public static Class<?> loadClass(String name) throws ClassNotFoundException { return Class.forName(name); }
/** * 替换字符串中的参数 replaceString("$1强化$2实施$2",new String[]{"qq","ff"}) * ="qq 强化 ff 实施 ff" * * @param str * @param parameters * @return * @throws Exception */ public static String replaceString(String str, Object[] parameters) throws Exception { if (str == null || parameters == null || parameters.length == 0) { return str; } Pattern p = Pattern.compile("\\$\\d+"); Matcher m = p.matcher(str); StringBuffer sb = new StringBuffer(); while (m.find()) { int index = Integer.parseInt(m.group().substring(1)) - 1; if (index < 0 || index >= parameters.length) { throw new QLException("设置的参数位置$" + (index + 1) + "超过了范围 " + parameters.length); } m.appendReplacement(sb, " " + parameters[index].toString() + " "); } m.appendTail(sb); return sb.toString(); }
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) { if(name.equals("class")){ return bean; }else{ Field f = ((Class<?>) bean).getDeclaredField(name.toString()); return f.get(null); } }else if(bean instanceof Map ){ return ((Map<?,?>)bean).get(name); }else { Object obj = PropertyUtils.getProperty(bean, name.toString()); return obj; } } catch (Exception e) { throw new RuntimeException(e); } } public static Class<?> getPropertyClass(Object bean, Object name) { try { if(bean.getClass().isArray() && name.equals("length")){ return int.class; }else if (bean instanceof Class) { if(name.equals("class")){ return Class.class; }else{ Field f = ((Class<?>) bean).getDeclaredField(name.toString()); return f.getType(); } }else if(bean instanceof Map ){ Object o = ((Map<?,?>)bean).get(name); if(o == null){ return null; }else{ return o.getClass(); } }else { return PropertyUtils.getPropertyDescriptor(bean, name.toString()).getPropertyType(); } } catch (Exception e) { throw new RuntimeException(e); } } public static void setProperty(Object bean, Object name, Object value) { try { if (bean instanceof Class) { Field f = ((Class<?>) bean).getDeclaredField(name.toString()); f.set(null, value); }else if(bean instanceof Map ){ ((Map<Object,Object>)bean).put(name, value); } else { Class<?> filedClass = PropertyUtils.getPropertyType(bean, name.toString()); PropertyUtils.setProperty(bean, name.toString(),ExpressUtil.castObject(value, filedClass, false)); } } catch (Exception e) { throw new RuntimeException("不能访问" + bean + "的property:" + name,e); } }
public static Object[] transferArray(Object[] values,Class<?>[] types){ for(int i=0;i <values.length;i++){ values[i] = castObject(values[i],types[i],false); } return values; } /** * * @param value * @param type * @param isForce 是否强制转换 * @return */ public static Object castObject(Object value, Class<?> type,boolean isForce){ if (value == null) return null; if (value.getClass() == type || type.isAssignableFrom(value.getClass())) { return value; } if (value instanceof Number && (type.isPrimitive() || Number.class.isAssignableFrom(type))) { return OperatorOfNumber.transfer((Number)value, type, isForce); }else if(type.isArray() && value.getClass().isArray()) { //需要对元素做兼容性,如果value的元素全部为null并且和声明的不一致,转化为所声明的类型 Class<?> valueType = value.getClass().getComponentType(); Class<?> declareType = type.getComponentType(); if(declareType!=valueType){ Object[] values = (Object[]) value; boolean allBlank = true; for(int i=0;i<values.length;i++) { if(values[i]!=null){ allBlank = false; break; } } if(allBlank){ return Array.newInstance(declareType,values.length); } } return value;
}else{ return value; } }
public static void main(String[] args) throws Exception { System.out.println(replaceString("$1强化$2实施$2", new String[] { "qq", "ff" })); System.out.println(Number.class.isAssignableFrom(Long.class)); Object obj = castObject(Double.valueOf(1d),Double.class,false); System.out.println(obj +":" + obj.getClass()); } }

复制代码

9.13、IExpressContext(表达式计算的数据注入接口)

package com.ql.util.express;
/** * 表达式计算的数据注入接口 * @author qhlhl2010@gmail.com * */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);}

复制代码

9.14、IExpressResourceLoader(加载表达式资源接口)

package com.ql.util.express;
/** * 加载表达式资源接口 * @author xuannan * */public interface IExpressResourceLoader { /** * 根据表达式名称获取表达式的内容 * @param expressName * @return * @throws Exception */ public String loadExpress(String expressName) throws Exception;}

复制代码

9.15、InstructionSet(表达式执行编译后形成的指令集合)

package com.ql.util.express;
import java.io.Serializable;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.TreeMap;import java.util.concurrent.atomic.AtomicInteger;
import com.ql.util.express.config.QLExpressTimer;import com.ql.util.express.exception.QLException;import com.ql.util.express.instruction.detail.*;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;
import com.ql.util.express.instruction.FunctionInstructionSet;import com.ql.util.express.instruction.OperateDataCacheManager;import com.ql.util.express.instruction.opdata.OperateDataLocalVar;


/** * 表达式执行编译后形成的指令集合 * @author qhlhl2010@gmail.com * */
public class InstructionSet implements Serializable{
/** * */ private static final long serialVersionUID = 1841743860792681669L; private static final transient Log log = LogFactory.getLog(InstructionSet.class); public static AtomicInteger uniqIndex = new AtomicInteger(1); public static String TYPE_MAIN ="main"; public static String TYPE_CLASS ="VClass"; public static String TYPE_FUNCTION ="function"; public static String TYPE_MARCO ="marco"; public static boolean printInstructionError = false; private String type ="main"; private String name; private String globeName; /** * 指令 */ private Instruction[] instructionList = new Instruction[0]; /** * 函数和宏定义 */ private Map<String,FunctionInstructionSet> functionDefine = new HashMap<String,FunctionInstructionSet>(); //为了增加性能,开始的时候缓存为数组 private Map<String,Object> cacheFunctionSet = null; private List<ExportItem> exportVar = new ArrayList<ExportItem>(); /** * 函数参数定义 */ private List<OperateDataLocalVar> parameterList = new ArrayList<OperateDataLocalVar>(); public static int getUniqClassIndex(){ return uniqIndex.getAndIncrement(); } public InstructionSet(String aType){ this.type = aType; }
public String[] getOutFunctionNames() 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 InstructionCallSelfDefineFunction) { String functionName = ((InstructionCallSelfDefineFunction)instruction).getFunctionName(); if(!functionDefine.containsKey(functionName)) { result.put(functionName, null); } } } 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){ if(instruction instanceof InstructionLoadAttr){ if("null".equals(((InstructionLoadAttr)instruction).getAttrName())){ continue; } result.put(((InstructionLoadAttr)instruction).getAttrName(),null); } } //剔除本地变量定义和别名定义 for (int i = 0; i < instructionList.length; i++) { Instruction instruction = instructionList[i]; if (instruction instanceof InstructionOperator) { String opName = ((InstructionOperator) instruction) .getOperator().getName(); if(opName != null){//addOperator(op)中op.name有可能为空 if (opName.equalsIgnoreCase("def") || opName.equalsIgnoreCase("exportDef")) { String varLocalName = (String) ((InstructionConstData) instructionList[i - 1]) .getOperateData().getObject(null); result.remove(varLocalName); } else if (opName.equalsIgnoreCase("alias") || opName.equalsIgnoreCase("exportAlias")) { String varLocalName = (String) ((InstructionConstData) instructionList[i - 2]) .getOperateData().getObject(null); result.remove(varLocalName); } } } } return result.keySet().toArray(new String[0]); }
/** * 添加指令,为了提高运行期的效率,指令集用数组存储 * @param item * @return */ private void addArrayItem(Instruction item){ Instruction[] newArray = new Instruction[this.instructionList.length + 1]; System.arraycopy(this.instructionList, 0, newArray, 0, this.instructionList.length); newArray[this.instructionList.length] = item; this.instructionList = newArray; } /** * 插入数据 * @param aPoint * @param item */ private void insertArrayItem(int aPoint,Instruction item){ Instruction[] newArray = new Instruction[this.instructionList.length + 1]; System.arraycopy(this.instructionList, 0, newArray, 0, aPoint); System.arraycopy(this.instructionList, aPoint, newArray, aPoint + 1,this.instructionList.length - aPoint); newArray[aPoint] = item; this.instructionList = newArray; }
/** * * @param environmen * @param context * @param errorList * @param isReturnLastData 是否最后的结果,主要是在执行宏定义的时候需要 * @param aLog * @return * @throws Exception */ public CallResult excute(RunEnvironment environmen,InstructionSetContext context, List<String> errorList,boolean isReturnLastData,Log aLog) throws Exception { //将函数export到上下文中,这儿就是重入也没有关系,不需要考虑并发 if(cacheFunctionSet == null){ Map<String,Object> tempMap = new HashMap<String,Object>(); for(FunctionInstructionSet s : this.functionDefine.values()){ tempMap.put(s.name,s.instructionSet); } cacheFunctionSet = tempMap; } context.addSymbol(cacheFunctionSet); this.executeInnerOrigiInstruction(environmen, errorList, aLog); if (environmen.isExit() == false) {// 是在执行完所有的指令后结束的代码 if (environmen.getDataStackSize() > 0) { OperateData tmpObject = environmen.pop(); if (tmpObject == null) { environmen.quitExpress(null); } else { if(isReturnLastData == true){ if(tmpObject.getType(context) != null && tmpObject.getType(context).equals(void.class)){ environmen.quitExpress(null); }else{ environmen.quitExpress(tmpObject.getObject(context)); } }else{ environmen.quitExpress(tmpObject); } } } } if (environmen.getDataStackSize() > 1) { throw new QLException("在表达式执行完毕后,堆栈中还存在多个数据"); } CallResult result = OperateDataCacheManager.fetchCallResult(environmen.getReturnValue(), environmen.isExit()); return result; } public void executeInnerOrigiInstruction(RunEnvironment environmen,List<String> errorList,Log aLog) throws Exception{ Instruction instruction =null; try { while (environmen.programPoint < this.instructionList.length) { QLExpressTimer.assertTimeOut(); instruction = this.instructionList[environmen.programPoint]; instruction.setLog(aLog);// 设置log instruction.execute(environmen, errorList); } } catch (Exception e) { if (printInstructionError) { log.error("当前ProgramPoint = " + environmen.programPoint); log.error("当前指令" + instruction); log.error(e); } throw e; } } public int getInstructionLength(){ return this.instructionList.length; } public void addMacroDefine(String macroName,FunctionInstructionSet iset){ this.functionDefine.put(macroName, iset); } public FunctionInstructionSet getMacroDefine(String macroName){ return this.functionDefine.get(macroName); } public FunctionInstructionSet[] getFunctionInstructionSets(){ return this.functionDefine.values().toArray(new FunctionInstructionSet[0]); } public void addExportDef(ExportItem e){ this.exportVar.add(e); } public List<ExportItem> getExportDef(){ List<ExportItem> result = new ArrayList<ExportItem> (); result.addAll(this.exportVar); return result; }
public OperateDataLocalVar[] getParameters() { return this.parameterList.toArray(new OperateDataLocalVar[0]); }
public void addParameter(OperateDataLocalVar localVar) { this.parameterList.add(localVar); } public void addInstruction(Instruction instruction){ this.addArrayItem(instruction); } public void insertInstruction(int point,Instruction instruction){ this.insertArrayItem(point, instruction); } public Instruction getInstruction(int point){ return this.instructionList[point]; } public int getCurrentPoint(){ return this.instructionList.length - 1; } public String getName() { return name;}
public void setName(String name) { this.name = name;}
public String getGlobeName() { return globeName;}
public void setGlobeName(String globeName) { this.globeName = globeName;}public boolean hasMain(){ return this.instructionList.length >0;}public String getType() { return type;}public void appendSpace(StringBuffer buffer,int level){ for(int i=0;i<level;i++){ buffer.append(" "); }}public String toString() { return "\n" + toString(0);} public String toString(int level) { try { StringBuffer buffer = new StringBuffer(); // 输出宏定义 for (FunctionInstructionSet set : this.functionDefine.values()) { appendSpace(buffer,level); buffer.append(set.type + ":" + set.name).append("("); for (int i=0;i<set.instructionSet.parameterList.size();i++) { OperateDataLocalVar var = set.instructionSet.parameterList.get(i); if(i > 0){ buffer.append(","); } buffer.append(var.getType(null).getName()).append(" ").append(var.getName()); } buffer.append("){\n"); buffer.append(set.instructionSet.toString(level + 1)); appendSpace(buffer,level); buffer.append("}\n"); } for (int i = 0; i < this.instructionList.length; i++) { appendSpace(buffer,level); buffer.append(i + 1).append(":").append(this.instructionList[i]) .append("\n"); } return buffer.toString(); } catch (Exception e) { throw new RuntimeException(e); } }}


复制代码

9.16、InstructionSetContext(指令集上下文)

package com.ql.util.express;
import java.util.HashMap;import java.util.Map;
import com.ql.util.express.exception.QLException;import com.ql.util.express.instruction.OperateDataCacheManager;
/** * 指令集上下文 */public class InstructionSetContext implements IExpressContext<String,Object> { /* * 没有知道数据类型的变量定义是否传递到最外层的Context */ private boolean isExpandToParent = true; /** * 表达式上下文 */ private IExpressContext<String,Object> parent = null; /** * 内容 */ private Map<String,Object> content; /** * 符号表 */ private Map<String,Object> symbolTable =new HashMap<String,Object>(); /** * 表达式装载器 */ private ExpressLoader expressLoader; /** * 是否支持动态属性名字 */ private boolean isSupportDynamicFieldName = false;
/** * 获取运行器 * @return */ public ExpressRunner getRunner() { return runner; }
/** * 表达式运行器 */ private ExpressRunner runner;
/** * 构造函数指令集上下文 * @param aIsExpandToParent * @param aRunner * @param aParent * @param aExpressLoader * @param aIsSupportDynamicFieldName */ public InstructionSetContext(boolean aIsExpandToParent,ExpressRunner aRunner,IExpressContext<String,Object> aParent,ExpressLoader aExpressLoader,boolean aIsSupportDynamicFieldName){ this.initial(aIsExpandToParent, aRunner, aParent, aExpressLoader, aIsSupportDynamicFieldName); }
/** * 初始化 * @param aIsExpandToParent * @param aRunner * @param aParent * @param aExpressLoader * @param aIsSupportDynamicFieldName */ public void initial(boolean aIsExpandToParent,ExpressRunner aRunner,IExpressContext<String,Object> aParent,ExpressLoader aExpressLoader,boolean aIsSupportDynamicFieldName){ this.isExpandToParent = aIsExpandToParent; this.runner = aRunner; this.parent = aParent; this.expressLoader = aExpressLoader; this.isSupportDynamicFieldName = aIsSupportDynamicFieldName; }
/** * 清除 */ public void clear(){ isExpandToParent = true; parent = null; content = null; expressLoader = null; isSupportDynamicFieldName = false; runner = null; symbolTable.clear(); }
/** * 导出符号 * @param varName * @param aliasNameObject * @throws Exception */ public void exportSymbol(String varName,Object aliasNameObject) throws Exception{ if( this.parent != null && this.parent instanceof InstructionSetContext){ ((InstructionSetContext)this.parent).exportSymbol(varName, aliasNameObject); }else{ this.addSymbol(varName, aliasNameObject); } }
/** * 添加符号 * @param varName * @param aliasNameObject * @throws Exception */ public void addSymbol(String varName,Object aliasNameObject) throws Exception{ if(this.symbolTable.containsKey(varName)){ throw new QLException("变量" + varName + "已经存在,不能重复定义,也不能再从函数内部 exprot "); } this.symbolTable.put(varName,aliasNameObject); }
/** * 添加符号 * @param aliasNameObjects * @throws Exception */ public void addSymbol(Map<String,Object> aliasNameObjects) throws Exception{ this.symbolTable.putAll(aliasNameObjects); } public void setSupportDynamicFieldName(boolean isSupportDynamicFieldName) { this.isSupportDynamicFieldName = isSupportDynamicFieldName; }
/** * 是支持动态属性名字 * @return */ public boolean isSupportDynamicFieldName(){ return this.isSupportDynamicFieldName; }
/** * 获取表达式运行器 * @return */ public ExpressRunner getExpressRunner(){ return this.runner; }
/** * 查找别名或者定义的符号 * @param varName * @return * @throws Exception */ public Object findAliasOrDefSymbol(String varName)throws Exception{ Object result = this.symbolTable.get(varName); if(result == null){ if( this.parent != null && this.parent instanceof InstructionSetContext){ result = ((InstructionSetContext)this.parent).findAliasOrDefSymbol(varName); }else{ result = null; } } return result; }
/** * 获取符号 * @param varName * @return * @throws Exception */ public Object getSymbol(String varName) throws Exception{ Object result = this.symbolTable.get(varName); if( result == null && this.expressLoader != null){ result = this.expressLoader.getInstructionSet(varName); } if(result == null){ if (this.isExpandToParent == true && this.parent != null && this.parent instanceof InstructionSetContext) { result = ((InstructionSetContext) this.parent) .getSymbol(varName); } else { result = OperateDataCacheManager.fetchOperateDataAttr(varName, null); this.addSymbol(varName, result); } } return result; }
/** * 获取表达式装载器 * @return */ public ExpressLoader getExpressLoader() { return expressLoader; }
/** * 获取表达式上下文 * @return */ public IExpressContext<String,Object> getParent(){ return this.parent; }
/** * 获取对象 * @param key 属性名称 * @return */ @Override public Object get(Object key){ if(this.content != null && this.content.containsKey(key)){ return this.content.get(key); }else if(this.isExpandToParent == true && this.parent != null){ return this.parent.get(key); } return null; }
/** * 存放对象 * @param key * @param value * @return */ @Override public Object put(String key, Object value){ if(this.content != null && this.content.containsKey(key) ){ return this.content.put(key,value); }else if (this.isExpandToParent == false){ if(this.content == null){ this.content = new HashMap<String,Object>(); } return this.content.put(key,value); }else if(this.parent != null){ return this.parent.put(key,value); }else{ throw new RuntimeException("没有定义局部变量:" + key +",而且没有全局上下文"); } }
}

复制代码

9.17、InstructionSetRunner(指令集运行器)

package com.ql.util.express;
import java.util.List;
import com.ql.util.express.config.QLExpressTimer;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;
import com.ql.util.express.instruction.OperateDataCacheManager;
/** * 指令集运行器 */public class InstructionSetRunner { private static final Log log = LogFactory.getLog(InstructionSetRunner.class); public static Object executeOuter(ExpressRunner runner,InstructionSet sets,ExpressLoader loader, IExpressContext<String,Object> aContext, List<String> errorList, boolean isTrace,boolean isCatchException, Log aLog,boolean isSupportDynamicFieldName) throws Exception{ try{
//开始计时 QLExpressTimer.startTimer();
OperateDataCacheManager.push(runner); return execute(runner,sets, loader, aContext, errorList, isTrace, isCatchException,true, aLog,isSupportDynamicFieldName); }finally{ OperateDataCacheManager.resetCache(runner); } }
/** * 批量执行指令集合,指令集间可以共享 变量和函数 * @param runner * @param sets * @param loader * @param aContext * @param errorList * @param isTrace * @param isCatchException * @param isReturnLastData * @param aLog * @param isSupportDynamicFieldName * @return * @throws Exception */ public static Object execute(ExpressRunner runner,InstructionSet sets,ExpressLoader loader, IExpressContext<String,Object> aContext, List<String> errorList, boolean isTrace,boolean isCatchException, boolean isReturnLastData,Log aLog,boolean isSupportDynamicFieldName) throws Exception { InstructionSetContext context = OperateDataCacheManager.fetchInstructionSetContext ( true,runner,aContext,loader,isSupportDynamicFieldName); Object result = execute(sets,context,errorList,isTrace,isCatchException,isReturnLastData,aLog); return result; }
public static Object execute(InstructionSet set, InstructionSetContext context, List<String> errorList, boolean isTrace,boolean isCatchException, boolean isReturnLastData,Log aLog) throws Exception { RunEnvironment environmen = null; Object result = null; environmen = OperateDataCacheManager.fetRunEnvironment(set, (InstructionSetContext) context, isTrace); try { CallResult tempResult = set.excute(environmen, context, errorList, isReturnLastData, aLog); if (tempResult.isExit() == true) { result = tempResult.getReturnValue(); } } catch (Exception e) { if (isCatchException == true) { if (aLog != null) { aLog.error(e.getMessage(), e); } else { log.error(e.getMessage(), e); } } else { throw e; } } return result;
}}

复制代码

9.18、LocalExpressCacheRunner(作为表达式)

package com.ql.util.express;
import java.util.HashMap;import java.util.Map;
/** * 作为表达式 * @author tianqiao * */public class LocalExpressCacheRunner extends ExpressRemoteCacheRunner{ /** * 表达式集合map */ private static Map<String,Object> expressMap = new HashMap<String,Object> (); /** * 表达式运行器 */ private ExpressRunner expressRunner;
/** * 本地表达式缓存运行器 * @param expressRunner */ public LocalExpressCacheRunner(ExpressRunner expressRunner){ this.expressRunner = expressRunner; } @Override public final Object getCache(String key) { return expressMap.get(key); }
@Override public final void putCache(String key, Object object) { expressMap.put(key, object); }
@Override public final ExpressRunner getExpressRunner() { return this.expressRunner; }
}

复制代码

9.19、OperateData(数据类型定义)

package com.ql.util.express;

import com.ql.util.express.exception.QLException;
/** * 数据类型定义 * @author qhlhl2010@gmail.com * */
public class OperateData implements java.io.Serializable { private static final long serialVersionUID = 4749348640699065036L; protected Object dataObject; protected Class<?> type;
public OperateData(Object obj, Class<?> aType) { this.type = aType; this.dataObject = obj; } /** * 给对象缓存接口使用 * @param obj * @param aType */ public void initial(Object obj, Class<?> aType) { this.type = aType; this.dataObject = obj; } public void clear(){ this.dataObject = null; this.type = null; } public Class<?> getDefineType(){ throw new RuntimeException(this.getClass().getName() + "必须实现方法:getDefineType"); } public Class<?> getOrgiType(){ return this.type; } public Class<?> getType(InstructionSetContext parent) throws Exception { if (type != null) return type;
Object obj = this.getObject(parent); if (obj == null) return null; else return obj.getClass(); }
public final Object getObject(InstructionSetContext context) throws Exception { if(this.type != null && this.type.equals(void.class)){ throw new QLException("void 不能参与任何操作运算,请检查使用在表达式中使用了没有返回值的函数,或者分支不完整的if语句"); } return getObjectInner(context); } public Object getObjectInner(InstructionSetContext context) throws Exception{ return this.dataObject; } public void setObject(InstructionSetContext parent, Object object) throws Exception { throw new RuntimeException("必须在子类中实现此方法"); } public String toJavaCode(){ if(this.getClass().equals(OperateData.class) == false){ throw new RuntimeException(this.getClass().getName() + "没有实现:toJavaCode()"); } String result ="new " + OperateData.class.getName() +"("; if(String.class.equals(this.type)){ result = result + "\"" + this.dataObject + "\""; }else if(this.type.isPrimitive()){ result = result + this.dataObject.getClass().getName() +".valueOf(\"" + this.dataObject + "\")"; }else{ result = result + "new " + this.dataObject.getClass().getName() + "(\"" + this.dataObject.toString() + "\")"; } result = result + "," + type.getName() + ".class"; result = result + ")"; return result; } public String toString() { if( this.dataObject == null) return this.type + ":null"; else{ if(this.dataObject instanceof Class){ return ExpressUtil.getClassName((Class<?>)this.dataObject); }else{ return this.dataObject.toString(); } } } public void toResource(StringBuilder builder,int level){ if(this.dataObject != null){ builder.append(this.dataObject.toString()); }else{ builder.append("null"); } }}

复制代码

9.20、Operator(操作符的基类)

package com.ql.util.express;
import com.ql.util.express.config.QLExpressRunStrategy;import com.ql.util.express.exception.QLException;import com.ql.util.express.instruction.OperateDataCacheManager;import com.ql.util.express.instruction.op.OperatorBase;
import java.util.Date;
/** * 操作符的基类 * * @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++) { 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 QLException("操作符号定义的返回类型错误:" + 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 * @throws Exception */ public static boolean objectEquals(Object op1, Object op2) throws Exception{ if (op1 == null && op2 == null) { return true; } if (op1 == null || op2 == null) { return false; } //Character的值比较 if(op1 instanceof Character || op2 instanceof Character){ int compareResult = 0; if (op1 instanceof Character && op2 instanceof Character) { return ((Character) op1).equals((Character) op2); }else if (op1 instanceof Number) { compareResult = OperatorOfNumber.compareNumber((Number) op1, (int) ((Character) op2).charValue()); return compareResult==0; } else if (op2 instanceof Number) { compareResult = OperatorOfNumber.compareNumber((int) ((Character) op1).charValue(), (Number) op2); return compareResult==0; } } //数值的值比较 if (op1 instanceof Number && op2 instanceof Number) { //数字比较 int compareResult = OperatorOfNumber.compareNumber((Number) op1, (Number) op2); return compareResult==0; } //调用原始Object的比较 return op1.equals(op2); } /** * 进行对象比较 * * @param op1 * @param op2 * @return 0 等于 ,负数 小于 , 正数 大于 * @throws Exception */ 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 QLException(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 QLException(op1 + "和" + op2 + "不能执行compare 操作"); return compareResult; } }

复制代码

9.21、OperatorOfNumber(数值的操作)

package com.ql.util.express;
import com.ql.util.express.exception.QLException;
import java.math.BigDecimal;
/** * 数字运行函数集合 * @author qhlhl2010@gmail.com * */
interface NumberType{ public int NUMBER_TYPE_BYTE = 1; public int NUMBER_TYPE_SHORT = 2; public int NUMBER_TYPE_INT = 3; public int NUMBER_TYPE_LONG = 4; public int NUMBER_TYPE_FLOAT = 5; public int NUMBER_TYPE_DOUBLE = 6; public int NUMBER_TYPE_BIGDECIMAL = 7;}
/** * 数值的操作 * @author xiaochengxinyizhan */public class OperatorOfNumber { public static double round(double v, int scale) { if (scale < 0) { throw new IllegalArgumentException( "The scale must be a positive integer or zero"); } BigDecimal b = new BigDecimal(Double.toString(v)); BigDecimal one = new BigDecimal("1"); return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).doubleValue(); }
/** * 获取数据类型精度顺序 * @param aClass * @return */ public static int getSeq(Class<?> aClass){ if(aClass == Byte.class || aClass == byte.class) return NumberType.NUMBER_TYPE_BYTE; if(aClass == Short.class || aClass == short.class) return NumberType.NUMBER_TYPE_SHORT; if(aClass == Integer.class || aClass == int.class) return NumberType.NUMBER_TYPE_INT; if(aClass == Long.class || aClass == long.class) return NumberType.NUMBER_TYPE_LONG; if(aClass == Float.class || aClass == float.class) return NumberType.NUMBER_TYPE_FLOAT; if(aClass == Double.class || aClass == double.class) return NumberType.NUMBER_TYPE_DOUBLE; if(aClass == BigDecimal.class) return NumberType.NUMBER_TYPE_BIGDECIMAL; throw new RuntimeException("不能处理的数据类型:" + aClass.getName()); } /** * 进行数据类型转换 * @param value * @param type * @return */ public static Number transfer(Number value,Class<?> type,boolean isForce){ if (isForce == true || value instanceof BigDecimal == false) { if (type.equals(byte.class) || type.equals(Byte.class)) { return ((Number) value).byteValue(); } else if (type.equals(short.class) || type.equals(Short.class)) { return ((Number) value).shortValue(); } else if (type.equals(int.class) || type.equals(Integer.class)) { return ((Number) value).intValue(); } else if (type.equals(long.class) || type.equals(Long.class)) { return ((Number) value).longValue(); } else if (type.equals(float.class) || type.equals(Float.class)) { return ((Number) value).floatValue(); } else if (type.equals(double.class) || type.equals(Double.class)) { return ((Number) value).doubleValue(); } else if (type.equals(BigDecimal.class)) { return new BigDecimal(value.toString()); }else{ throw new RuntimeException("没有处理的数据类型:" + type.getName()); } } else { if (type.equals(byte.class) || type.equals(Byte.class)) { if(((BigDecimal)value).scale() >0 ){ throw new RuntimeException("有小数位,不能转化为:"+ type.getName()); } return ((Number) value).byteValue(); } else if (type.equals(short.class) || type.equals(Short.class)) { if(((BigDecimal)value).scale() >0 ){ throw new RuntimeException("有小数位,不能转化为:"+ type.getName()); } return ((Number) value).shortValue(); } else if (type.equals(int.class) || type.equals(Integer.class)) { if(((BigDecimal)value).scale() >0 ){ throw new RuntimeException("有小数位,不能转化为:"+ type.getName()); } return ((Number) value).intValue(); } else if (type.equals(long.class) || type.equals(Long.class)) { if(((BigDecimal)value).scale() >0 ){ throw new RuntimeException("有小数位,不能转化为:"+ type.getName()); } return ((Number) value).longValue(); } else if (type.equals(float.class) || type.equals(Float.class)) { return ((Number) value).floatValue(); } else if (type.equals(double.class) || type.equals(Double.class)) { return ((Number) value).doubleValue(); }else{ throw new RuntimeException("没有处理的数据类型:" + type.getName()); } } }
/** * 比较数值 * @param op1 * @param op2 * @return */ public static int compareNumber(Number op1, Number op2){ int type1 = OperatorOfNumber.getSeq(op1.getClass()); int type2 = OperatorOfNumber.getSeq(op2.getClass()); int type = type1 > type2 ? type1:type2; if(type == 1) { byte o1 = ((Number)op1).byteValue(); byte o2 = ((Number)op2).byteValue(); if(o1 == o2) return 0; if(o1 < o2) return -1; return 1; } if(type == 2) { short o1 = ((Number)op1).shortValue(); short o2 = ((Number)op2).shortValue(); if(o1 == o2) return 0; if(o1 < o2) return -1; return 1; } if(type == 3) { int o1 = ((Number)op1).intValue(); int o2 = ((Number)op2).intValue(); if(o1 == o2) return 0; if(o1 < o2) return -1; return 1; } if(type == 4) { long o1 = ((Number)op1).longValue(); long o2 = ((Number)op2).longValue(); if(o1 == o2) return 0; if(o1 < o2) return -1; return 1; } if(type == 5) { float o1 = ((Number)op1).floatValue(); float o2 = ((Number)op2).floatValue(); if(o1 == o2) return 0; if(o1 < o2) return -1; return 1; } if(type == 6){ double o1 = ((Number)op1).doubleValue(); double o2 = ((Number)op2).doubleValue(); if(o1 == o2) return 0; if(o1 < o2) return -1; return 1; } if(type == 7){ BigDecimal o1 = new BigDecimal(op1.toString()); BigDecimal o2 = new BigDecimal(op2.toString()); return o1.compareTo(o2); } throw new RuntimeException("比较操作错误:op1=" + op1.toString() +",op2=" + op2.toString());
}
/** * 添加 * @param op1 * @param op2 * @param isPrecise * @return * @throws Exception */ public static Object add(Object op1, Object op2,boolean isPrecise) throws Exception { if(op1 == null){ op1 = "null"; } if(op2 == null){ op2 = "null"; } if (op1 instanceof String || op2 instanceof String) { return op1.toString() + op2.toString(); } if(isPrecise==true){ return PreciseNumberOperator.addPrecise((Number)op1,(Number)op2); }else{ return NormalNumberOperator.addNormal((Number)op1,(Number)op2); } }
/** * 截取 * @param op1 * @param op2 * @param isPrecise * @return * @throws Exception */ public static Number subtract(Object op1, Object op2,boolean isPrecise) throws Exception { if(isPrecise==true){ return PreciseNumberOperator.subtractPrecise((Number)op1,(Number)op2); }else{ return NormalNumberOperator.subtractNormal((Number)op1,(Number)op2); } }
/** * 乘法 * @param op1 * @param op2 * @param isPrecise * @return * @throws Exception */ public static Number multiply(Object op1, Object op2,boolean isPrecise) throws Exception { if(isPrecise==true){ return PreciseNumberOperator.multiplyPrecise((Number)op1,(Number)op2); }else{ return NormalNumberOperator.multiplyNormal((Number)op1,(Number)op2); } }
/** * 减法 * @param op1 * @param op2 * @param isPrecise * @return * @throws Exception */ public static Number divide(Object op1, Object op2,boolean isPrecise) throws Exception { if(isPrecise==true){ return PreciseNumberOperator.dividePrecise((Number)op1,(Number)op2); }else{ return NormalNumberOperator.divideNormal((Number)op1,(Number)op2); } } public static Object modulo(Object op1,Object op2) throws Exception{ return NormalNumberOperator.moduloNormal((Number)op1,(Number)op2); }}
/** * 正常的数值操作 */class NormalNumberOperator {
/** * 普通的加法运算 * @param op1 * @param op2 * @return * @throws Exception */ public static Number addNormal(Number op1, Number op2) throws Exception { int type1 = OperatorOfNumber.getSeq(op1.getClass()); int type2 = OperatorOfNumber.getSeq(op2.getClass()); int type = type1 > type2 ? type1:type2; if(type == NumberType.NUMBER_TYPE_BYTE) return op1.byteValue() + op2.byteValue(); if(type == NumberType.NUMBER_TYPE_SHORT) return op1.shortValue() + op2.shortValue(); if(type == NumberType.NUMBER_TYPE_INT) return op1.intValue() + op2.intValue(); if(type == NumberType.NUMBER_TYPE_LONG) return op1.longValue() + op2.longValue(); if(type == NumberType.NUMBER_TYPE_FLOAT) return op1.floatValue() + op2.floatValue(); if(type == NumberType.NUMBER_TYPE_DOUBLE) return op1.doubleValue() + op2.doubleValue(); if(type == NumberType.NUMBER_TYPE_BIGDECIMAL) return new BigDecimal(op1.toString()).add(new BigDecimal(op2.toString())); throw new QLException("不支持的对象执行了\"+\"操作"); }

/** * 普通的减法操作 * @param op1 * @param op2 * @return * @throws Exception */ public static Number subtractNormal(Number op1,Number op2) throws Exception{ int type1 = OperatorOfNumber.getSeq(op1.getClass()); int type2 = OperatorOfNumber.getSeq(op2.getClass()); int type = type1 > type2 ? type1:type2; if(type == NumberType.NUMBER_TYPE_BYTE) return op1.byteValue() - op2.byteValue(); if(type == NumberType.NUMBER_TYPE_SHORT) return op1.shortValue() - op2.shortValue(); if(type == NumberType.NUMBER_TYPE_INT) return op1.intValue() - op2.intValue(); if(type == NumberType.NUMBER_TYPE_LONG) return op1.longValue() - op2.longValue(); if(type == NumberType.NUMBER_TYPE_FLOAT) return op1.floatValue() - op2.floatValue(); if(type == NumberType.NUMBER_TYPE_DOUBLE) return op1.doubleValue() - op2.doubleValue(); if(type == NumberType.NUMBER_TYPE_BIGDECIMAL) return new BigDecimal(op1.toString()).subtract(new BigDecimal(op2.toString())); throw new QLException("不支持的对象执行了\"-\"操作"); }
/** * 普通的乘法操作 * @param op1 * @param op2 * @return * @throws Exception */ public static Number multiplyNormal(Number op1,Number op2) throws Exception { int type1 = OperatorOfNumber.getSeq(op1.getClass()); int type2 = OperatorOfNumber.getSeq(op2.getClass()); int type = type1 > type2 ? type1:type2; if(type == NumberType.NUMBER_TYPE_BYTE) return op1.byteValue() * op2.byteValue(); if(type == NumberType.NUMBER_TYPE_SHORT) return op1.shortValue() * op2.shortValue(); if(type == NumberType.NUMBER_TYPE_INT) return op1.intValue() * op2.intValue(); if(type == NumberType.NUMBER_TYPE_LONG) return op1.longValue() * op2.longValue(); if(type == NumberType.NUMBER_TYPE_FLOAT) return op1.floatValue() * op2.floatValue(); if(type == NumberType.NUMBER_TYPE_DOUBLE) return op1.doubleValue() * op2.doubleValue(); if(type == NumberType.NUMBER_TYPE_BIGDECIMAL) return new BigDecimal(op1.toString()).multiply(new BigDecimal(op2.toString())); throw new QLException("不支持的对象执行了\"*\"操作"); }
/** * 普通的除法操作 * @param op1 * @param op2 * @return * @throws Exception */ public static Number divideNormal(Number op1,Number op2) throws Exception{ int type1 = OperatorOfNumber.getSeq(op1.getClass()); int type2 = OperatorOfNumber.getSeq(op2.getClass()); int type = type1 > type2 ? type1:type2; if(type == NumberType.NUMBER_TYPE_BYTE) return op1.byteValue() / op2.byteValue(); if(type == NumberType.NUMBER_TYPE_SHORT) return op1.shortValue() / op2.shortValue(); if(type == NumberType.NUMBER_TYPE_INT) return op1.intValue() / op2.intValue(); if(type == NumberType.NUMBER_TYPE_LONG) return op1.longValue() / op2.longValue(); if(type == NumberType.NUMBER_TYPE_FLOAT) return op1.floatValue() / op2.floatValue(); if(type == NumberType.NUMBER_TYPE_DOUBLE) return op1.doubleValue() / op2.doubleValue(); if(type == NumberType.NUMBER_TYPE_BIGDECIMAL) return new BigDecimal(op1.toString()).divide(new BigDecimal(op2.toString()), BigDecimal.ROUND_HALF_UP); throw new QLException("不支持的对象执行了\"/\"操作"); }
/** * 普通的取模运算 * @param op1 * @param op2 * @return * @throws Exception */ public static Number moduloNormal(Number op1,Number op2) throws Exception{ int type1 = OperatorOfNumber.getSeq(op1.getClass()); int type2 = OperatorOfNumber.getSeq(op2.getClass()); int type = type1 > type2 ? type1:type2; if(type == NumberType.NUMBER_TYPE_BYTE) return op1.byteValue() % op2.byteValue(); if(type == NumberType.NUMBER_TYPE_SHORT) return op1.shortValue() % op2.shortValue(); if(type == NumberType.NUMBER_TYPE_INT) return op1.intValue() % op2.intValue(); if(type == NumberType.NUMBER_TYPE_LONG) return op1.longValue() % op2.longValue(); throw new QLException("不支持的对象执行了\"mod\"操作"); }}
/** * 高精度计算 * @author xuannan */class PreciseNumberOperator { public static int DIVIDE_PRECISION = 10;
/** * 添加高精度 * @param op1 * @param op2 * @return * @throws Exception */ public static Number addPrecise(Number op1, Number op2) throws Exception { BigDecimal result = null; if(op1 instanceof BigDecimal){ if(op2 instanceof BigDecimal){ result = ((BigDecimal)op1).add((BigDecimal)op2); }else{ result = ((BigDecimal)op1).add(new BigDecimal(op2.toString())); } }else{ if(op2 instanceof BigDecimal){ result = new BigDecimal(op1.toString()).add((BigDecimal)op2); }else{ result = new BigDecimal(op1.toString()).add(new BigDecimal(op2.toString())); } } if(result.scale() ==0){ long tempLong = result.longValue(); if(tempLong <= Integer.MAX_VALUE && tempLong >= Integer.MIN_VALUE){ return (int)tempLong; }else{ return tempLong; } }else{ return result; } }
/** * 减法高精度 * @param op1 * @param op2 * @return * @throws Exception */ public static Number subtractPrecise(Number op1, Number op2) throws Exception { BigDecimal result = null; if(op1 instanceof BigDecimal){ if(op2 instanceof BigDecimal){ result = ((BigDecimal)op1).subtract((BigDecimal)op2); }else{ result = ((BigDecimal)op1).subtract(new BigDecimal(op2.toString())); } }else{ if(op2 instanceof BigDecimal){ result = new BigDecimal(op1.toString()).subtract((BigDecimal)op2); }else{ result = new BigDecimal(op1.toString()).subtract(new BigDecimal(op2.toString())); } } if(result.scale() ==0){ long tempLong = result.longValue(); if(tempLong <= Integer.MAX_VALUE && tempLong >= Integer.MIN_VALUE){ return (int)tempLong; }else{ return tempLong; } }else{ return result; } }
/** * 乘法高精度 * @param op1 * @param op2 * @return * @throws Exception */ public static Number multiplyPrecise(Number op1, Number op2) throws Exception { BigDecimal result = null; if(op1 instanceof BigDecimal){ if(op2 instanceof BigDecimal){ result = ((BigDecimal)op1).multiply((BigDecimal)op2); }else{ result = ((BigDecimal)op1).multiply(new BigDecimal(op2.toString())); } }else{ if(op2 instanceof BigDecimal){ result = new BigDecimal(op1.toString()).multiply((BigDecimal)op2); }else{ result = new BigDecimal(op1.toString()).multiply(new BigDecimal(op2.toString())); } } if(result.scale() ==0){ long tempLong = result.longValue(); if(tempLong <= Integer.MAX_VALUE && tempLong >= Integer.MIN_VALUE){ return (int)tempLong; }else{ return tempLong; } }else{ return result; } }
/** * 除法高精度 * @param op1 * @param op2 * @return * @throws Exception */ public static Number dividePrecise(Number op1, Number op2) throws Exception { BigDecimal result = null; if(op1 instanceof BigDecimal){ if(op2 instanceof BigDecimal){ result = ((BigDecimal)op1).divide((BigDecimal)op2, DIVIDE_PRECISION, BigDecimal.ROUND_HALF_UP); }else{ result = ((BigDecimal)op1).divide(new BigDecimal(op2.toString()), DIVIDE_PRECISION, BigDecimal.ROUND_HALF_UP); } }else{ if(op2 instanceof BigDecimal){ result = new BigDecimal(op1.toString()).divide((BigDecimal)op2, DIVIDE_PRECISION, BigDecimal.ROUND_HALF_UP); }else{ result = new BigDecimal(op1.toString()).divide(new BigDecimal(op2.toString()), DIVIDE_PRECISION, BigDecimal.ROUND_HALF_UP); } } if(result.scale() ==0){ long tempLong = result.longValue(); if(tempLong <= Integer.MAX_VALUE && tempLong >= Integer.MIN_VALUE){ return (int)tempLong; }else{ return tempLong; } }else{ return result; } }}

复制代码

9.22、RunEnvironment(运行环境)

package com.ql.util.express;

import com.ql.util.express.exception.QLException;
/** * 运行环境 * @author xiaochengxinyizhan */public final class RunEnvironment { private static int INIT_DATA_LENTH = 15; private boolean isTrace = false; private int point = -1; protected int programPoint = 0; private OperateData[] dataContainer; private ArraySwap arraySwap = new ArraySwap(); private boolean isExit = false; private Object returnValue = null; private InstructionSet instructionSet; private InstructionSetContext context; public RunEnvironment(InstructionSet aInstructionSet,InstructionSetContext aContext,boolean aIsTrace){ dataContainer = new OperateData[INIT_DATA_LENTH]; this.instructionSet = aInstructionSet; this.context = aContext; this.isTrace = aIsTrace; } public void initial(InstructionSet aInstructionSet,InstructionSetContext aContext,boolean aIsTrace){ this.instructionSet = aInstructionSet; this.context = aContext; this.isTrace = aIsTrace; } public void clear(){ isTrace = false; point = -1; programPoint = 0; isExit = false; returnValue = null; instructionSet = null; context = null; } public InstructionSet getInstructionSet() { return instructionSet; }

public InstructionSetContext getContext(){ return this.context; } public void setContext(InstructionSetContext aContext){ this.context = aContext; }
public boolean isExit() { return isExit; } public Object getReturnValue() { return returnValue; } public void setReturnValue(Object value){ this.returnValue = value; } public void quitExpress(Object aReturnValue){ this.isExit = true; this.returnValue = aReturnValue; } public void quitExpress(){ this.isExit = true; this.returnValue = null; } public boolean isTrace(){ return this.isTrace; } public int getProgramPoint() { return programPoint; } public void programPointAddOne() { programPoint ++ ; } public void gotoLastWhenReturn(){ programPoint = this.instructionSet.getInstructionLength(); } public int getDataStackSize(){ return this.point + 1; } public void push(OperateData data){ this.point++; if(this.point >= this.dataContainer.length){ ensureCapacity(this.point + 1); } this.dataContainer[point] = data; } public OperateData peek(){ if(point <0){ throw new RuntimeException("系统异常,堆栈指针错误"); } return this.dataContainer[point]; } public OperateData pop(){ if(point <0) throw new RuntimeException("系统异常,堆栈指针错误"); OperateData result = this.dataContainer[point]; this.point--; return result; } public void clearDataStack(){ this.point = -1; } public void gotoWithOffset(int aOffset ){ this.programPoint = this.programPoint + aOffset; } /** * 此方法是调用最频繁的,因此尽量精简代码,提高效率 * @param context * @param len * @return * @throws Exception */ public ArraySwap popArray(InstructionSetContext context,int len) throws Exception { int start = point - len + 1; this.arraySwap.swap(this.dataContainer,start,len); point = point - len; return this.arraySwap; } public OperateData[] popArrayOld(InstructionSetContext context,int len) throws Exception { int start = point - len + 1; OperateData[] result = new OperateData[len]; System.arraycopy(this.dataContainer,start, result,0, len); point = point - len; return result; } public OperateData[] popArrayBackUp(InstructionSetContext context,int len) throws Exception { int start = point - len + 1; if(start <0){ throw new QLException("堆栈溢出,请检查表达式是否错误"); } OperateData[] result = new OperateData[len]; for (int i = 0 ; i < len; i++) { result[i] = this.dataContainer[start + i]; if(void.class.equals(result[i].getType(context))){ throw new QLException("void 不能参与任何操作运算,请检查使用在表达式中使用了没有返回值的函数,或者分支不完整的if语句"); } } point = point - len; return result; }
public void ensureCapacity(int minCapacity) { int oldCapacity = this.dataContainer.length; if (minCapacity > oldCapacity) { int newCapacity = (oldCapacity * 3) / 2 + 1; if (newCapacity < minCapacity){ newCapacity = minCapacity; } OperateData[] tempList = new OperateData[newCapacity]; System.arraycopy(this.dataContainer,0,tempList,0,oldCapacity); this.dataContainer = tempList; } } }

复制代码

十、小结


借鉴的学习内容是在充分掌握 Java 基础上进行了一些简单的运算和语法的封装。模拟 java 的编译器形成自己的一套语法规则,值得学习。做的不好的地方,其实是基于老项目的维护,有些魔法数字以及无注释,代码不规整等内容


  • 1、线程安全,引擎运算过程中的产生的临时变量都是 threadlocal 类型。

  • 2、高效执行,比较耗时的脚本编译过程可以缓存在本地机器,运行时的临时变量创建采用了缓冲池的技术,和 groovy 性能相当。


发布于: 2021 年 01 月 18 日阅读数: 49
用户头像

小胜靠智,大胜靠德 2019.06.27 加入

历经创业、京东、腾讯、滴滴公司,希望能够有些东西一起分享。公众号:小诚信驿站,微信/CSDN搜索:wolf_love666

评论

发布
暂无评论
案例研究之聊聊 QLExpress 源码 (九)