两条规则中的一条未触发
One out of two rules not firing
我是 JAVA 的新手,尤其是 Drools,所以不要问我为什么这样做 :D 任务是实现一个简单的系统来计算 2 的关税和价格项目(不同颜色)。我用 getter 和 setter 做了一个简单的 class :
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(写入尚未实现)。 Class 处理输入并调用会话如下:
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;
}
}
我还有 2 个单独的 DRL 文件,用于每种项目颜色。根据规则的计算,我需要打印出 2 个附加属性,简单乘法(小计)。每个文件有 2 条规则:
import com.sample.Pen; //FIRST ONE
rule "less or equal to 10"
when
item : Pen(item.getColor().equalsIgnoreCase("BLUE PEN"), (item.getQuantity()) <= 10.0)
then
item.setTariff(3.0);
item.setSubTotal(3.0 * ((double) item.getQuantity()));
end
rule "more than 10"
when
item : Pen(item.getColor().equalsIgnoreCase("BLUE PEN"), (item.getQuantity()) > 10.0)
then
item.setTariff(2.5);
item.setSubTotal(2.5 * ((double) item.getQuantity()));
end
import com.sample.Pen; //SECOND ONE
rule "less or equal to 10"
when
item : Pen(item.getColor().equalsIgnoreCase("RED PEN"), (item.getQuantity()) <= 10.0)
then
item.setTariff(3.5);
item.setSubTotal(3.5 * ((double) item.getQuantity()));
end
rule "more than 10"
when
item : Pen(item.getColor().equalsIgnoreCase("RED PEN"), (item.getQuantity()) > 10.0)
then
item.setTariff(3.0);
item.setSubTotal(3.0 * ((double) item.getQuantity()));
end
此外,还有一个 class,我在其中调用启动流程的整个方法:
public class App {
public static void main(String[] args) {
CSVReader csvReader = new CSVReader();
csvReader.CSVToJava();
}
}
一切看起来像这样packageExplorer
我的主要问题是打印输出看起来像这样 -->
Red Pen,6,3.5,21.0
Blue Pen,12,0.0,0.0
每行应包含 4 个字段,前两个字段是在 while 循环中通过 CSVReader class 计算得出的,而后两个字段(本例中的 3.5 和 21.0 或 Red Pen)是使用 Drools 计算的。如您所见,蓝笔的规则根本没有触发,我无法解决问题...如果有人可以提供帮助,我将不胜感激:)
编辑:解决这个问题后,我用分布在 2 个 DRL 文件中的另外 3 条规则编辑了代码:
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
我还在我的会话中添加了文件 classpaths,以便可以触发。调用 fireAll 方法时,没有规则触发第二次 drl 火灾,其中总量乘以 0.85(total
是在 Pen
class 中声明的静态变量,所以我可以从每种颜色中收集 suTotal
s 的加法),尽管显着性是最低的 --> 应该最后触发并且正确的数量应该是 140*0.85 = 119.
看起来像这样:
Red Pen,30,3.0,90.0
Blue Pen,20,2.5,50.0
140
也许有人也能解决这个问题,到目前为止你们的建议都很好 :)
我不是专家,但我建议将RED PEN和BLUE PEN切换一下,看看它是否在第一个规则后不触发规则。或者它可能是 CSV 文件读取的问题。谢谢
规则条件中的字符串比较不应使用Java equals 方法。 Drools 使用自己的 rule language。 (但请注意 - 5.x 语法比参考文档中显示的语法更受限制。而且它在次要版本 5.2/3/... [laune] 之间也有所不同)
查看示例 4.4(我更正了示例中缺失的 "
):
1: rule simple_rule
2: when
3: Student( name == "Andy" )
4: then
5: end
您应该为您的规则尝试这种语法(还要注意您的数量是整数而不是浮点数):
when
item : Pen(color == "BLUE PEN", quantity > 10)
附带说明一下,您在规则的动作部分中的 (double)
转换不是强制性的。 Java 中的双精度和整数相乘最终得到双精度值,这已经是您的 tariff 和 subTotal 成员的类型。
两个文件都有规则
rule "less or equal to 10"
rule "more than 10"
你不能这样。规则由名称标识;与另一个规则同名的规则将默默地覆盖第一个规则。来自不同 DRL 文件的加载顺序未定义。
在 Drools 5.x 期间就是否应该以及如何工作进行了长时间的讨论,但现在这是桥下的水,你必须坚持下去。 (我不确定 Drools 6.x 是否允许这样做。请查阅文档。)
感谢@Wis 确认 Drools 6.x 在编译中存在具有相同名称的规则时引发编译错误,无论是在同一 DRL 文件中还是在不同文件中。
我是 JAVA 的新手,尤其是 Drools,所以不要问我为什么这样做 :D 任务是实现一个简单的系统来计算 2 的关税和价格项目(不同颜色)。我用 getter 和 setter 做了一个简单的 class :
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(写入尚未实现)。 Class 处理输入并调用会话如下:
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;
}
}
我还有 2 个单独的 DRL 文件,用于每种项目颜色。根据规则的计算,我需要打印出 2 个附加属性,简单乘法(小计)。每个文件有 2 条规则:
import com.sample.Pen; //FIRST ONE
rule "less or equal to 10"
when
item : Pen(item.getColor().equalsIgnoreCase("BLUE PEN"), (item.getQuantity()) <= 10.0)
then
item.setTariff(3.0);
item.setSubTotal(3.0 * ((double) item.getQuantity()));
end
rule "more than 10"
when
item : Pen(item.getColor().equalsIgnoreCase("BLUE PEN"), (item.getQuantity()) > 10.0)
then
item.setTariff(2.5);
item.setSubTotal(2.5 * ((double) item.getQuantity()));
end
import com.sample.Pen; //SECOND ONE
rule "less or equal to 10"
when
item : Pen(item.getColor().equalsIgnoreCase("RED PEN"), (item.getQuantity()) <= 10.0)
then
item.setTariff(3.5);
item.setSubTotal(3.5 * ((double) item.getQuantity()));
end
rule "more than 10"
when
item : Pen(item.getColor().equalsIgnoreCase("RED PEN"), (item.getQuantity()) > 10.0)
then
item.setTariff(3.0);
item.setSubTotal(3.0 * ((double) item.getQuantity()));
end
此外,还有一个 class,我在其中调用启动流程的整个方法:
public class App {
public static void main(String[] args) {
CSVReader csvReader = new CSVReader();
csvReader.CSVToJava();
}
}
一切看起来像这样packageExplorer
我的主要问题是打印输出看起来像这样 -->
Red Pen,6,3.5,21.0
Blue Pen,12,0.0,0.0
每行应包含 4 个字段,前两个字段是在 while 循环中通过 CSVReader class 计算得出的,而后两个字段(本例中的 3.5 和 21.0 或 Red Pen)是使用 Drools 计算的。如您所见,蓝笔的规则根本没有触发,我无法解决问题...如果有人可以提供帮助,我将不胜感激:)
编辑:解决这个问题后,我用分布在 2 个 DRL 文件中的另外 3 条规则编辑了代码:
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
我还在我的会话中添加了文件 classpaths,以便可以触发。调用 fireAll 方法时,没有规则触发第二次 drl 火灾,其中总量乘以 0.85(total
是在 Pen
class 中声明的静态变量,所以我可以从每种颜色中收集 suTotal
s 的加法),尽管显着性是最低的 --> 应该最后触发并且正确的数量应该是 140*0.85 = 119.
看起来像这样:
Red Pen,30,3.0,90.0
Blue Pen,20,2.5,50.0
140
也许有人也能解决这个问题,到目前为止你们的建议都很好 :)
我不是专家,但我建议将RED PEN和BLUE PEN切换一下,看看它是否在第一个规则后不触发规则。或者它可能是 CSV 文件读取的问题。谢谢
规则条件中的字符串比较不应使用Java equals 方法。 Drools 使用自己的 rule language。 (但请注意 - 5.x 语法比参考文档中显示的语法更受限制。而且它在次要版本 5.2/3/... [laune] 之间也有所不同)
查看示例 4.4(我更正了示例中缺失的 "
):
1: rule simple_rule
2: when
3: Student( name == "Andy" )
4: then
5: end
您应该为您的规则尝试这种语法(还要注意您的数量是整数而不是浮点数):
when
item : Pen(color == "BLUE PEN", quantity > 10)
附带说明一下,您在规则的动作部分中的 (double)
转换不是强制性的。 Java 中的双精度和整数相乘最终得到双精度值,这已经是您的 tariff 和 subTotal 成员的类型。
两个文件都有规则
rule "less or equal to 10"
rule "more than 10"
你不能这样。规则由名称标识;与另一个规则同名的规则将默默地覆盖第一个规则。来自不同 DRL 文件的加载顺序未定义。
在 Drools 5.x 期间就是否应该以及如何工作进行了长时间的讨论,但现在这是桥下的水,你必须坚持下去。 (我不确定 Drools 6.x 是否允许这样做。请查阅文档。)
感谢@Wis 确认 Drools 6.x 在编译中存在具有相同名称的规则时引发编译错误,无论是在同一 DRL 文件中还是在不同文件中。