继续回顾QLExpress,深入了解里面的一些设计。
操作数据的抽象
/**
* 数据类型定义
*
* @author [email protected]
*/
public class OperateData {
protected Object dataObject;
protected Class<?> type;
public OperateData(Object obj, Class<?> type) {
this.type = type;
this.dataObject = obj;
}
/**
* 给对象缓存接口使用
*
* @param obj
* @param type
*/
public void initial(Object obj, Class<?> type) {
this.type = type;
this.dataObject = obj;
}
public void clear() {
this.dataObject = null;
this.type = null;
}
public Class<?> getDefineType() {
throw new RuntimeException(this.getClass().getName() + "必须实现方法:getDefineType");
}
public Class<?> getOriginalType() {
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)) {
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
+ "\")";
}
result = result + "," + type.getName() + ".class";
result = result + ")";
return result;
}
@Override
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);
} else {
builder.append("null");
}
}
}
- 属性就是:数据类型和数据
后续的各种数据类型基于此,包括:类、字符类型、类域类型、代数数据类型、类型联合和数据库类型
OperateData的数组结构:
public final class ArraySwap {
private OperateData[] operateDataArray;
private int start;
public int length;
public void swap(OperateData[] operateDataArray, int start, int length) {
this.operateDataArray = operateDataArray;
this.start = start;
this.length = length;
}
public OperateData get(int i) {
return this.operateDataArray[i + start];
}
}
操作符抽象
对于规则引擎到最底层就是 a,b 像个对象执行某种操作符,判断ture or false。即规则条件左、右变量,以及左右变量执行的操作,返回一个结果。
/**
* 操作符的基类
*
* @author xuannan
*/
public abstract class Operator extends OperatorBase {
@Override
public OperateData executeInner(InstructionSetContext parent, 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(parent);
}
}
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;
最重要的就是executeInner
方法,对传入的操作参数执行并返回结果。
也可以学到如何比较两个对象是否相等,大小关系
/**
* 进行对象是否相等的比较
*
* @param op1
* @param op2
* @return
*/
public static boolean objectEquals(Object op1, Object op2) {
if (op1 == null && op2 == null) {
return true;
}
if (op1 == null || op2 == null) {
return false;
}
//Character的值比较
if (op1 instanceof Character || op2 instanceof Character) {
int compareResult;
if (op1 instanceof Character && op2 instanceof Character) {
return op1.equals(op2);
} else if (op1 instanceof Number) {
compareResult = OperatorOfNumber.compareNumber((Number)op1, (int)(Character)op2);
return compareResult == 0;
} else if (op2 instanceof Number) {
compareResult = OperatorOfNumber.compareNumber((int)(Character)op1, (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;
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);
} else if (op2 instanceof Number) {
compareResult = OperatorOfNumber.compareNumber((int)(Character)op1, (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;
}
在OperatorBase中则包括基本的操作符属性
/**
* 操作符号定义
*
* @author [email protected]
*/
public abstract class OperatorBase {
protected String name;
protected String aliasName;
protected String errorInfo;
/**
* 是否需要高精度计算
*/
protected boolean isPrecise = false;
/**
* 操作数描述
*/
protected String[] operateDataDesc;
/**
* 操作数的其它定义
*/
protected String[] operateDataAnnotation;
具体操作符 OperatorIn
public class OperatorIn extends Operator {
public OperatorIn(String name) {
this.name = name;
}
public OperatorIn(String aliasName, String name, String errorInfo) {
this.name = name;
this.aliasName = aliasName;
this.errorInfo = errorInfo;
}
@Override
public Object executeInner(Object[] list) throws Exception {
Object obj = list[0];
if (obj == null) {
if (QLExpressRunStrategy.isAvoidNullPointer()) {
//避免空指针策略异常则返回false
return false;
}
// 对象为空,不能执行方法
String msg = "对象为空,不能执行方法:";
throw new QLException(msg + this.name);
} else if (!((obj instanceof Number) || (obj instanceof String))) {
String msg = "对象类型不匹配,只有数字和字符串类型才才能执行 in 操作,当前数据类型是:";
throw new QLException(msg + obj.getClass().getName());
} else if (list.length == 2 && (list[1].getClass().isArray() || list[1] instanceof List)) {
if (list[1].getClass().isArray()) {
int len = Array.getLength(list[1]);
for (int i = 0; i < len; i++) {
boolean f = OperatorEqualsLessMore.executeInner("==", obj, Array.get(list[1], i));
if (f) {
return Boolean.TRUE;
}
}
} else if (list[1] instanceof List) {
@SuppressWarnings("unchecked")
List<Object> array = (List<Object>)list[1];
for (Object o : array) {
boolean f = OperatorEqualsLessMore.executeInner("==", obj, o);
if (f) {
return Boolean.TRUE;
}
}
}
return false;
} else {
for (int i = 1; i < list.length; i++) {
boolean f = OperatorEqualsLessMore.executeInner("==", obj, list[i]);
if (f) {
return Boolean.TRUE;
}
}
return Boolean.FALSE;
}
}
}
重新executeInner方法,进行数据判断和执行in方法
OperatorAdd
public class OperatorAdd extends Operator {
public OperatorAdd(String name) {
this.name = name;
}
public OperatorAdd(String aliasName, String name, String errorInfo) {
this.name = name;
this.aliasName = aliasName;
this.errorInfo = errorInfo;
}
@Override
public Object executeInner(Object[] list) throws Exception {
return OperatorOfNumber.add(list[0], list[1], this.isPrecise);
}
}
字符串或数字类型进行加法,高精度数字则进行BigDecimal化的加法
回顾表达式的执行
对于表达式"2 in b" 解析为的语法树
1: STAT_BLOCK:STAT_BLOCK STAT_BLOCK
2: STAT_SEMICOLON:STAT_SEMICOLON STAT_SEMICOLON
3: in:in in
4: 2:CONST_INTEGER CONST
4: b:ID ID
任何表达式都能表达成如上的语法树,然后执行过程中每一步都有操作符的执行,和结果的更新。最后就得到最后结果