我特别喜欢JAVA和Drools的初学者,所以不要问为什么我这样做:D任务是实施一个简单的系统来计算2项(不同颜色)的关税和价格。我用吸气剂和二传手制作了一个简单的课程:
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;
}
}
我还有2个单独的DRL文件,用于每种颜色。根据规则的计算,我需要打印出2个额外的属性,简单的乘法(subTotal)。每个文件都有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
此外,还有一个类,我调用整个方法来启动过程:
public class App {
public static void main(String[] args) {
CSVReader csvReader = new CSVReader();
csvReader.CSVToJava();
}
}
所有内容都是packageExplorer
我的主要问题是打印输出看起来像这样 - &gt;
Red Pen,6,3.5,21.0
Blue Pen,12,0.0,0.0
每行应包含4个字段,前两个字段在while循环中的CSVReader类中计算,而后两个字段(在案例中为3.5和21.0或Red Pen)使用Drools计算。正如你所看到的,蓝笔的规则根本没有解决,我无法解决问题......如果有人可以提供帮助,我会非常感激:)
编辑:解决了这个问题之后,我用另外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 fire没有规则触发,其中总量乘以0.85(total
是在Pen
类中声明的静态变量,所以我可以从每种颜色收集suTotal
s的添加,尽管显着性最低 - &gt;应该最后开火,正确的数量应该是140 * 0.85 = 119。
看起来像这样:
Red Pen,30,3.0,90.0
Blue Pen,20,2.5,50.0
140
也许有人可以解决这个问题,到目前为止,你们的建议很棒!)
答案 0 :(得分:2)
两个文件都有规则
rule "less or equal to 10"
rule "more than 10"
你无法做到这一点。规则按名称标识;与另一个规则同名的规则将以静默方式覆盖第一个规则。未定义来自不同DRL文件的加载顺序。
在Drools 5.x期间,是否以及如何使用这个问题进行了长时间的讨论,但现在这就是桥下的水,你必须坚持下去。 (我不确定Drools 6.x是否允许这样做。请参阅文档。)
感谢@Wis确认Drools 6.x在编译中存在具有相同名称的规则时引发编译错误,无论是在相同的DRL文件中还是在不同的文件中。
答案 1 :(得分:1)
我不是专家,但我建议切换RED PEN和BLUE PEN以查看它是否在第一次规则后没有触发规则。或者它可能是CSV文件读取的问题。 THX
答案 2 :(得分:1)
规则条件中的字符串比较不应使用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中乘以一个整数和一个整数会得到一个double值,这个值已经是你的关税和subTotal成员的类型。