Java 两条规则中有一条不开火

Java 两条规则中有一条不开火,java,drools,priority-queue,rule-engine,Java,Drools,Priority Queue,Rule Engine,我是JAVA和Drools的初学者,所以不要问我为什么要这么做:D任务是实现一个简单的系统,可以计算两种商品(不同颜色)的关税和价格。我用getter和setter创建了一个简单的类: package com.sample; public class Pen { private String color; private int quantity; private double tariff; private double subTotal; pub

我是JAVA和Drools的初学者,所以不要问我为什么要这么做:D任务是实现一个简单的系统,可以计算两种商品(不同颜色)的关税和价格。我用getter和setter创建了一个简单的类:

package com.sample;

public class Pen {

    private String color;
    private int quantity;
    private double tariff;
    private double subTotal;

    public String getColor(){
        return color;
    }

    public void setColor(String color){
        this.color=color;
    }

    public int getQuantity(){
        return quantity;
    }

    public void setQuantity(int quantity){
        this.quantity=quantity;
    }

    public double getTariff(){
        return tariff;
    }

    public void setTariff(double tariff){
        this.tariff=tariff;
    }

    public double getSubTotal(){
        return subTotal;
    }

    public void setSubTotal(double subTotal){
        this.subTotal=subTotal;
    }

}
任务是从一个CSV文件中读取一些预定义的数据,并将其写入另一个CSV(尚未实现写入)。处理输入并调用会话的类如下所示:

public class CSVReader {
    public void CSVToJava() {
        String CSVFile = "csvExample.csv";
        BufferedReader buffer = null;
        String line = "";
        String delimiter = ",";
        List<Pen> penList = new ArrayList<Pen>();

        try {
            // load up the knowledge base
            KnowledgeBase kbase = readKnowledgeBase();
            StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
            buffer = new BufferedReader(new FileReader(CSVFile));
            while ((line = buffer.readLine()) != null) {
                String[] pens = line.split(delimiter);
                Pen redPen = new Pen();
                Pen bluePen = new Pen();
                if (pens[0].equalsIgnoreCase("Blue Pen")) {
                    bluePen.setColor(pens[0]);
                    bluePen.setQuantity(Integer.parseInt(pens[1].trim()));
                    penList.add(bluePen);
                    ksession.insert(bluePen);
                } else {
                    redPen.setColor(pens[0]);
                    redPen.setQuantity(Integer.parseInt(pens[1].trim()));
                    penList.add(redPen);
                    ksession.insert(redPen);
                }
            }
            ksession.fireAllRules();
            printPenList(penList);        
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Throwable t) {
            t.printStackTrace();
        } finally {
            if (buffer != null) {
                try {
                    buffer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void printPenList(List<Pen> penListToPrint) {
        for (int i = 0; i < penListToPrint.size(); i++) {
            System.out.println(penListToPrint.get(i).getColor() + "," + penListToPrint.get(i).getQuantity() + ","
                    + penListToPrint.get(i).getTariff() + "," + penListToPrint.get(i).getSubTotal());
        }

    }

    private static KnowledgeBase readKnowledgeBase() throws Exception {

        KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();

        kbuilder.add(ResourceFactory.newClassPathResource("com/Drools/BluePen.drl"), ResourceType.DRL);
        kbuilder.add(ResourceFactory.newClassPathResource("com/Drools/RedPen.drl"), ResourceType.DRL);

        KnowledgeBuilderErrors errors = kbuilder.getErrors();

        if (errors.size() > 0) {
            for (KnowledgeBuilderError error : errors) {
                System.err.println(error);
            }
            throw new IllegalArgumentException("Could not parse knowledge.");
        }

        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
        kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());

        return kbase;
    }

}
一切都是这样

我的主要问题是打印输出看起来像这样-->

每行应包含4个字段,前两个字段在while循环中的CSVReader类中计算,而最后两个字段(在本例中为3.5和21.0或红色笔)使用Drools计算。正如你所看到的,蓝笔的规则根本没有生效,我无法解决这个问题。。。如果有人能帮忙,我会非常感激:)

编辑:解决这个问题后,我用另外3条规则编辑了代码,这3条规则分布在2个DRL文件中:

package com.drools //First.drl

import com.sample.Pen;

rule "Subtotal for blue pen" salience 2

    when
        item : Pen(item.getColor().equalsIgnoreCase("BLUE PEN"))
    then
        item.setTotal(item.getTotal() + item.getSubTotal());    
end

rule "Subtotal for red pen" salience 2

    when
        item : Pen(item.getColor().equalsIgnoreCase("RED PEN"))
    then
        item.setTotal(item.getTotal() + item.getSubTotal());    
end


package com.drools //Second.drl

import com.sample.Pen;

rule "Discounted total price" salience 1

    when
        item : Pen((item.getTotal()) > 100.0)
    then
        item.setTotal(0.85 * item.getTotal());
end
我也在会话中添加了文件类路径,以便于启动。调用fireAll方法时,第二次drl激发没有规则激发,总数量乘以0.85(
total
是在
Pen
类中声明的静态变量,因此我可以从每种颜色收集添加的
suTotal
s),即使显著性最低-->应最后触发,正确的数量应为140*0.85=119

看起来像这样:

Red Pen,30,3.0,90.0
Blue Pen,20,2.5,50.0
140 

也许有人也能明白这一点,到目前为止,你们的建议都很好:)

我不是专家,但我建议在第一条规则之后切换红笔和蓝笔,看看它是否不会触发规则。或者可能是CSV文件读取的问题。规则条件中的字符串比较不应使用Java equals方法。Drools正在使用它自己的。(但请注意-5.x语法比参考文档中所示的要严格一些,并且在5.2/3/…[laune]的小版本之间也有所不同。)

看看示例4.4(我更正了示例中缺少的
):

您应该为您的规则尝试此语法(还要注意,您的数量是整数而不是浮点):

作为补充说明,规则的操作部分中的
(double)
强制转换不是必需的。在Java中,将double和整数相乘会得到一个double值,该值已经是关税和小计成员的类型。

两个文件都有规则

rule "less or equal to 10"
rule "more than 10"
您不能这样做。规则由名称标识;与另一个规则同名的规则将以静默方式覆盖第一个规则。未定义来自不同DRL文件的加载顺序

在Drools 5.x期间,这是否以及如何工作进行了长时间的讨论,但现在这是桥下的水,您必须坚持下去。(我不确定Drools 6.x是否允许这样做。请查阅文档。)


感谢@Wis确认Drools 6.x在编译中存在名称相同的规则时会引发编译错误,而不管这些规则是在同一DRL文件中还是在不同的文件中。

您仍然可以使用equals.和equalsIgnoreCase(如OP所述)是另一种方法。你是对的,equals确实有效。如果我没有弄错的话,在条件中只能使用Java的一小部分。我记得不能使用一些
Calendar
方法。但是有一点不同,drools==运算符是空安全的。我冒昧地补充了一句关于它们之间语法的警告6.x和5.x版本。原始问题没有指明drools borgmater使用的是哪个版本。然后在点击链接时要小心。你的编辑是相关的。这应该是一个评论,而不是答案。我同意,但我不允许用我目前的观点评论。做了一个测试以确保drools 6.x:它不允许d重复名称。它的结尾为:
java.lang.IllegalStateException:[4,0]:重复规则名称:小于或等于10[12,0]:重复的规则名称:超过10个。
。我将编辑您的帖子以确保完整性。@在编辑之前,请确保相同或不同文件中的规则没有差异。发生了另一个问题,也是由于触发了规则,我已编辑了包含详细信息的帖子。似乎salience工作不正常,或者我缺少了一些内容g:-/您缺少基本的东西。首先,阅读有关修改和更新的内容。其次,使用静态(类)变量是一种制造恶作剧的好方法。你有两个钢笔对象——总数通过两者都可见,因此对于总数为140的笔,规则会对红色的笔触发一次,然后对蓝色的笔触发一次,结果是140*0.85*0.85。第三,避免突出,除非你绝对确定你离不开它。@laune我测试过,可以确认非法状态在两种情况下都会出现重复规则名称的例外情况:在一个文件和两个不同的文件中有两个名称相同的规则(假设两个DRL文件在同一个编译中)。
package com.drools //First.drl

import com.sample.Pen;

rule "Subtotal for blue pen" salience 2

    when
        item : Pen(item.getColor().equalsIgnoreCase("BLUE PEN"))
    then
        item.setTotal(item.getTotal() + item.getSubTotal());    
end

rule "Subtotal for red pen" salience 2

    when
        item : Pen(item.getColor().equalsIgnoreCase("RED PEN"))
    then
        item.setTotal(item.getTotal() + item.getSubTotal());    
end


package com.drools //Second.drl

import com.sample.Pen;

rule "Discounted total price" salience 1

    when
        item : Pen((item.getTotal()) > 100.0)
    then
        item.setTotal(0.85 * item.getTotal());
end
Red Pen,30,3.0,90.0
Blue Pen,20,2.5,50.0
140 
1: rule simple_rule
2:   when
3:     Student( name == "Andy" )
4:   then
5: end
when
    item : Pen(color == "BLUE PEN", quantity > 10)
rule "less or equal to 10"
rule "more than 10"