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

news/2024/6/19 0:40:39 标签: java, servlet, 数据库

继续回顾QLExpress,深入了解里面的一些设计。

操作数据的抽象

java">/**
 * 数据类型定义
 *
 * @author qhlhl2010@gmail.com
 */
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的数组结构:

java">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。即规则条件左、右变量,以及左右变量执行的操作,返回一个结果。

java">/**
 * 操作符的基类
 *
 * @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方法,对传入的操作参数执行并返回结果。

也可以学到如何比较两个对象是否相等大小关系

java">/**
 * 进行对象是否相等的比较
 *
 * @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);
}
java">/**
 * 进行对象比较
 *
 * @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中则包括基本的操作符属性

java">/**
 * 操作符号定义
 *
 * @author qhlhl2010@gmail.com
 */
public abstract class OperatorBase {
    protected String name;
    protected String aliasName;
    protected String errorInfo;

    /**
     * 是否需要高精度计算
     */
    protected boolean isPrecise = false;

    /**
     * 操作数描述
     */
    protected String[] operateDataDesc;

    /**
     * 操作数的其它定义
     */
    protected String[] operateDataAnnotation;


具体操作符 OperatorIn

java">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

java">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" 解析为的语法树

java">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

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


http://www.niftyadmin.cn/n/457460.html

相关文章

【初识C语言】字符串+转义字符+注释

文章目录 1. 字符串2. 转义字符转义字符表常见转义字符 3. 注释 1. 字符串 “hello world.\n” 上面这种由双引号引起的一串字符就被称为字符串&#xff1b; 字符串的存储 C 语言当中没有字符串类型&#xff0c;如果想要将字符串存储起来的话就需要用到字符串数组。 #include…

HTML5 的新特性

目录 1.0 HTML5 的新特性 1.1 HTML5 新增的语义化标签 1.2 HTML5 新增的多媒体标签 video视频 audio音频 1.2.1 video视频 1.2.2 audio音频 1.3 多媒体标签总结 2.0 HTML5 新增的input 类型 3.0 HTML5 新增的表单属性 1.0 HTML5 的新特性 HTML5的新增特性主要是针对于以前的不…

机器学习期末复习 集成学习

1.集成学习的一般结构&#xff1f; &#xff08;1&#xff09;产生一组个体学习器 &#xff08;2&#xff09;用某些策略将个体学习器结合 2.&#xff08;判断&#xff09;集成学习主要分为并行算法和串行算法。其中随机森林属于串行算法&#xff0c;即每一颗树的学习受其他树…

js blob 文件上传

js blob 文件上传 js中的文件处理和文件上传掌握得更扎实&#xff0c;有更深入的理解&#xff0c;底层原理 ps.项目中使用插件上传 filereadermime类型筛选单文件的2种处理方案多文件&文件上传进度管控 Ajax文件上传时&#xff1a;Formdata、File、Blob的关系-腾讯云开发者…

大数据就业路线

✨博文作者&#xff1a;烟雨孤舟 &#x1f496; 喜欢的可以 点赞 收藏 关注哦~~ ✍️ 作者简介: 一个热爱大数据的学习者 ✍️ 笔记简介&#xff1a;作为大数据爱好者&#xff0c;以下是个人总结的学习笔记&#xff0c;如有错误&#xff0c;请多多指教&#xff01; 数仓&#x…

【unity之UiI专题】GUI(IMGUI)详解

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;uni…

2023.6.22 c 考研单词例句默写

1. The drug is powerful.这个药物非常有效 2.The treaty was to the aggressors advantage.这个条款对侵略者有利 3.Children like candy.孩子们喜欢糖果 4.His body was deformed by leprosy.他的身体因为麻风病变形了 5.He was very mysterious in his manner. 他的行为…