规则引擎--QLExpress: 数据和操作符的抽象

继续回顾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

任何表达式都能表达成如上的语法树,然后执行过程中每一步都有操作符的执行,和结果的更新。最后就得到最后结果

猜你喜欢

转载自blog.csdn.net/qq_26437925/article/details/131335223