案例研究之聊聊 QLExpress 源码 (九)
发布于: 2021 年 01 月 18 日
九、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
版权声明: 本文为 InfoQ 作者【小诚信驿站】的原创文章。
原文链接:【http://xie.infoq.cn/article/15425ae652f33414c802f92c4】。文章转载请联系作者。
小诚信驿站
关注
小胜靠智,大胜靠德 2019.06.27 加入
历经创业、京东、腾讯、滴滴公司,希望能够有些东西一起分享。公众号:小诚信驿站,微信/CSDN搜索:wolf_love666
评论