Lession2
Relating facts and attributes to each other in a rule
Adding callback initialization and more
为了能够看一下在规则引擎里面发生了什么事情,我们需要添加一些方法到KnowledgeSessionHelper
public static KieSessiongetStatefulKnowledgeSessionWithCallback(
KieContainer kieContainer, String sessionName) {
KieSessionsession = getStatefulKnowledgeSession(kieContainer, sessionName);
session.addEventListener(new RuleRuntimeEventListener() {
publicvoid objectInserted(ObjectInsertedEvent event) {
System.out.println("Objectinserted \n"
+ event.getObject().toString());
}
publicvoid objectUpdated(ObjectUpdatedEvent event) {
System.out.println("Object was updated \n"
+ "new Content \n"+ event.getObject().toString());
}
publicvoid objectDeleted(ObjectDeletedEvent event) {
System.out.println("Object retracted \n"
+ event.getOldObject().toString());
}
});
session.addEventListener(new AgendaEventListener() {
publicvoid matchCreated(MatchCreatedEvent event) {
System.out.println("The rule "
+ event.getMatch().getRule().getName()
+ " can be fired in agenda");
}
publicvoid matchCancelled(MatchCancelledEvent event) {
System.out.println("The rule "
+ event.getMatch().getRule().getName()
+ " cannot b in agenda");
}
publicvoid beforeMatchFired(BeforeMatchFiredEvent event) {
System.out.println("The rule "
+ event.getMatch().getRule().getName()
+ " will befired");
}
publicvoid afterMatchFired(AfterMatchFiredEvent event) {
System.out.println("The rule "
+ event.getMatch().getRule().getName()
+ " has be fired");
}
publicvoid agendaGroupPopped(AgendaGroupPoppedEvent event) {
}
publicvoid agendaGroupPushed(AgendaGroupPushedEvent event) {
}
publicvoid beforeRuleFlowGroupActivated(RuleFlowGroupActivatedEvent event) {
}
publicvoid afterRuleFlowGroupActivated(RuleFlowGroupActivatedEvent event) {
}
publicvoid beforeRuleFlowGroupDeactivated(RuleFlowGroupDeactivatedEvent event) {
}
publicvoid afterRuleFlowGroupDeactivated(RuleFlowGroupDeactivatedEvent event) {
}
});
以上代码就是在session里面把所有的事件都打印出来。来观察规则引擎
在CashFlow 修改toString方法
public static int CREDIT = 1;
public staticint DEBIT = 2;
@Override
public StringtoString() {
// TODOAuto-generated method stub
StringBuffer buff = new StringBuffer();
buff.append("-----CashFlow-----)\n");
buff.append("Account no=" + this.accountNo + "\n");
if(this.mvtDate != null) {
buff.append("Mouvement Date= "
+ DateFormat.getDateInstance().format(this.mvtDate)
+ "\n");
} else {
buff.append("No Mouvement date was set\n");
}
buff.append("Mouvement Amount=" + this.amount +"\n");
buff.append("-----CashFlow end--)");
returnbuff.toString();
}
在util包,我们创建一个DateHelper 如下:
package util;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateHelper {
publicstatic String sFormat = "yyyy-MM-dd";
public staticDate getDate(String sDate) throws Exception {
SimpleDateFormat sdf = new SimpleDateFormat(sFormat);
returnsdf.parse(sDate);
}
public staticDate getDate(String sDate, String anotherFormat)
throwsException {
SimpleDateFormat sdf = new SimpleDateFormat(anotherFormat);
returnsdf.parse(sDate);
}
}
在kmodule.xml ,如下修改
<?xml version="1.0" encoding="UTF-8"?>
<kmodulexmlns="http://jboss.org/kie/6.0.0/kmodule">
<kbasename="rules" packages="lesson1">
<ksession name="ksession-rules"/>
</kbase>
<kbasename="rules2" packages="lesson2">
<ksession name="ksession-lesson2"/>
</kbase>
</kmodule>
然后在src/test/rules 添加一个lesson2,添加一个lesson2.drl文件如下
package droolscours
//list any import classes here.
import droolscours.AccountingPeriod;
import droolscours.CashFlow;
import droolscours.Account;
import util.OutputDisplay;
global OutputDisplay showResults;
rule "Your First Rule revisited again"
when
Account( )
then
showResults.showText("The account exists");
end
添加一个TestLesson2 测试单元,代码如下
package droolscours;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.kie.api.event.rule.ObjectDeletedEvent;
import org.kie.api.event.rule.ObjectInsertedEvent;
import org.kie.api.event.rule.ObjectUpdatedEvent;
import org.kie.api.event.rule.RuleRuntimeEventListener;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.StatelessKieSession;
import org.kie.api.runtime.rule.FactHandle;
import util.KnowledgeSessionHelper;
@SuppressWarnings("restriction")
public class TestLesson2 {
staticKieContainer kieContainer;
StatelessKieSession sessionStateless = null;
KieSession sessionStatefull = null;
@BeforeClass
public staticvoid beforeClass(){
kieContainer=KnowledgeSessionHelper.createRuleBase();
}
@Before
public voidsetUp() throws Exception{
System.out.println("------------Before------------");
}
@After
public voidtearDown() throws Exception{
System.out.println("------------After------------");
}
@Test
public voidtestdeuxFait1() {
sessionStatefull = KnowledgeSessionHelper
.getStatefulKnowledgeSessionWithCallback(kieContainer,"ksession-lesson2");
OutputDisplay display = new OutputDisplay();
sessionStatefull.setGlobal("showResults", display);
Account a =new Account();
sessionStatefull.insert(a);
AccountingPeriod period = new AccountingPeriod();
sessionStatefull.insert(period);
sessionStatefull.fireAllRules();
}
}
执行后结果如下
------------Before------------
Object inserted
Account [accountno=0, balance=0.0]
Object inserted
AccountingPeriod [startDate=null,endDate=null]
The rule Your First Rule revisitedagain can be fired in agenda
The rule Your First Rule revisitedagain will be fired
time:1490946504145-The accountexists
The rule Your First Rule revisitedagain has be fired
------------After------------
所以现在我们知道了所有工作我们可以继续教程
Test Case
我们准备实现一个测试例子使用下面的数据
1) Account accountno=1
2) 一个Accountingperiod 从January first 2016 到 march 31th 2016
3) 三个Cash Flow动作,credit 1000$ January 15th 2016,debit 500$ February15th 2016和
a credit movement April 15th 2016 of 1000$.
那个期间的平衡:500$ f
Fact binding(事实绑定)
我们想去更新一个account balance对于每一次CashFlow。我们首先放入CashFlow 并且查询所有CashFlow 的类型。为了这样做,我们添加一个约束在CashFlow 类
然后我们添加第二个Account 的类型。问题是现在怎样更新balacne?
规则如下:
package droolscours
//list any import classes here.
import droolscours.AccountingPeriod;
import droolscours.CashFlow;
import droolscours.Account;
import util.OutputDisplay;
global OutputDisplay showResults;
rule "Credit rule"
when
$cash:CashFlow(type == CashFlow.CREDIT )
$acc :Account( )
then
$acc.setBalance($acc.getBalance()+$cash.getAmount());
showResults.showText("Account no"+$acc.getAccountNo()+ " has now a balance of"+$acc.getBalance());
end
在事实前,我们定义变量 $cash 和$acc像上面展示的并且这些变量可以作为一般的java变量使用。就像我们可以更新balance
然后TestLesson2 修改如下:
public class TestLesson2 {
staticKieContainer kieContainer;
StatelessKieSession sessionStateless = null;
KieSession sessionStatefull = null;
@BeforeClass
public staticvoid beforeClass(){
kieContainer=KnowledgeSessionHelper.createRuleBase();
}
@Before
public void setUp()throws Exception{
System.out.println("------------Before------------");
}
@After
public voidtearDown() throws Exception{
System.out.println("------------After------------");
}
@Test
public voidtestTwoFacts() {
sessionStatefull = KnowledgeSessionHelper
.getStatefulKnowledgeSessionWithCallback(kieContainer,"ksession-lesson2");
OutputDisplay display = new OutputDisplay();
sessionStatefull.setGlobal("showResults", display);
Accounta = new Account();
a.setAccountNo(1);
a.setBalance(0);
sessionStatefull.insert(a);
CashFlow cash1 = new CashFlow();
cash1.setAccountNo(1);
cash1.setAmount(1000);
cash1.setType(CashFlow.CREDIT);
sessionStatefull.insert(cash1);
sessionStatefull.fireAllRules();
Assert.assertEquals(a.getBalance(), 1000,0);
}
}
在TestTwoFacts 测试我们插入插入了一个Account对象和一个credit类型的CashFlow。最后,平衡应该是1000$。在控制台看到下面如果执行test
------------Before------------
Object inserted
Account [accountNo=1, balance=0.0]
Object inserted
-----CashFlow-----)
Account no=1
No Mouvement date was set
Mouvement Amount=1000.0
-----CashFlow end--)
The rule Credit rule can be fired inagenda
The rule Credit rule will be fired
time:1490948268070-Account no 1 hasnow a balance of 1000.0
The rule Credit rule has be fired
------------After------------
Attribute binding
修改下TestLesson2
@Test
public voidtestTwofactsTwocashFlowMovement() throws Exception {
sessionStatefull = KnowledgeSessionHelper
.getStatefulKnowledgeSessionWithCallback(kieContainer,"ksession-lesson2");
OutputDisplay display = new OutputDisplay();
sessionStatefull.setGlobal("showResults", display);
Account a =new Account();
a.setAccountNo(1);
a.setBalance(0);
sessionStatefull.insert(a);
CashFlowcash1 = new CashFlow();
cash1.setAccountNo(1);
cash1.setAmount(1000);
cash1.setMvtDate(DateHelper.getDate("2010-01-15"));
cash1.setType(CashFlow.CREDIT);
sessionStatefull.insert(cash1);
CashFlowcash2 = new CashFlow();
cash2.setAccountNo(2);
cash2.setAmount(1000);
cash2.setMvtDate(DateHelper.getDate("2010-01-15"));
cash2.setType(CashFlow.CREDIT);
sessionStatefull.insert(cash2);
sessionStatefull.fireAllRules();
Assert.assertEquals(a.getBalance(), 1000,0);
}
When we run the test case, the test fails : 我们看到控制台,"Credit rule" 规则执行了两次
------------Before------------
Object inserted
Account [accountNo=1, balance=0.0]
Object inserted
-----CashFlow-----)
Account no=1
No Mouvement date was set
Mouvement Amount=1000.0
-----CashFlow end--)
The rule Credit rule can be fired inagenda
The rule Credit rule will be fired
time:1490948544556-Account no 1 hasnow a balance of 1000.0
The rule Credit rule has be fired
------------After------------
------------Before------------
Object inserted
Account [accountNo=1, balance=0.0]
Object inserted
-----CashFlow-----)
Account no=1
Mouvement Date= 2010-1-15
Mouvement Amount=1000.0
-----CashFlow end--)
Object inserted
-----CashFlow-----)
Account no=2
Mouvement Date= 2010-1-15
Mouvement Amount=1000.0
-----CashFlow end--)
The rule Credit rule can be fired inagenda
The rule Credit rule can be fired inagenda
The rule Credit rule will be fired
time:1490948544635-Account no 1 hasnow a balance of 1000.0
The rule Credit rule has be fired
The rule Credit rule will be fired
time:1490948544635-Account no 1 hasnow a balance of 2000.0
The rule Credit rule has be fired
------------After------------
这个规则执行了两次因为这里有2连接。第一个CashFlow动作关注account number =1 和第二个账号account number=2.我们需要找到一个方法去连接两个事实。我应该修改规则如下
$cash :CashFlow($accno : accountNo ,type ==CashFlow.CREDIT )
$acc : Account( accountNo ==$accno )
这个规则使用了绑定变量。我们创建了一个属性变量叫做$accno 在 属性accountNo。我们可以定义一个绑定在Account事实的accountNo
------------Before------------
Object inserted
Account [accountNo=1, balance=0.0]
Object inserted
-----CashFlow-----)
Account no=1
Mouvement Date= 2010-1-15
Mouvement Amount=1000.0
-----CashFlow end--)
Object inserted
-----CashFlow-----)
Account no=2
Mouvement Date= 2010-1-15
Mouvement Amount=1000.0
-----CashFlow end--)
The rule Credit rule can be fired inagenda
The rule Credit rule will be fired
time:1490949118883-Account no 1 hasnow a balance of 1000.0
The rule Credit rule has be fired
------------After------------
现在这个规则就执行了一次,平衡就正确了
Calculating balance
现在我们知道怎样连接一个事实并且使用属性变量通过绑定属性去使用他们作为条件。我们修改一下credit rule 和创建一个debit rule :
package cours
import droolscours.Account;
import droolscours.AccountingPeriod;
import droolscours.CashFlow;
import droolscours.util.OutputDisplay;
global OutputDisplay showResult;
rule "Credit rule"
when
$cash:CashFlow( $aDate : mvtDate, $no : accountNo ,type == CashFlow.CREDIT )
$acc :Account(accountNo ==$no )
$period: AccountingPeriod( startDate <=$aDate && endDate >= $aDate)
then
$acc.setBalance($acc.getBalance()+$cash.getAmount());
showResults.showText("Account no "+$acc.getAccountNo()+ "has now a balance of "+$acc.getBalance());
end
rule "Debit rule"
when
$cash:CashFlow( $aDate : mvtDate, $no : accountNo ,type == CashFlow.DEBIT )
$acc :Account(accountNo ==$no )
$period :AccountingPeriod( startDate <= $aDate&& endDate >= $aDate)
then
$acc.setBalance($acc.getBalance()-$cash.getAmount());
showResults.showText("Account no "+$acc.getAccountNo()
+" has now a balance of "+$acc.getBalance());
end
在上面的规则,我们添加了一个条件所以在CashFlow的mvtDate 在AccountinPeriod的startDate和endDate 之间
添加测试:
@Test
public voidtestcalculateBalance() throws Exception {
sessionStatefull = KnowledgeSessionHelper
.getStatefulKnowledgeSessionWithCallback(kieContainer,"ksession-lesson2");
OutputDisplay display = new OutputDisplay();
sessionStatefull.setGlobal("showResults", display);
Account a =new Account();
a.setAccountNo(1);
a.setBalance(0);
sessionStatefull.insert(a);
CashFlowcash1 = new CashFlow();
cash1.setAccountNo(1);
cash1.setAmount(1000);
cash1.setMvtDate(DateHelper.getDate("2016-01-15"));
cash1.setType(CashFlow.CREDIT);
sessionStatefull.insert(cash1);
CashFlowcash2 = new CashFlow();
cash2.setAccountNo(1);
cash2.setAmount(500);
cash2.setMvtDate(DateHelper.getDate("2016-02-15"));
cash2.setType(CashFlow.DEBIT);
sessionStatefull.insert(cash2);
CashFlowcash3 = new CashFlow();
cash3.setAccountNo(1);
cash3.setAmount(1000);
cash3.setMvtDate(DateHelper.getDate("2016-04-15"));
cash3.setType(CashFlow.CREDIT);
sessionStatefull.insert(cash3);
AccountingPeriod period = new AccountingPeriod();
period.setStartDate(DateHelper.getDate("2016-01-01"));
period.setEndDate(DateHelper.getDate("2016-03-31"));
sessionStatefull.insert(period);
sessionStatefull.fireAllRules();
Assert.assertTrue(a.getBalance()==500);
}
测试结果如下:
------------Before------------
Object inserted
Account [accountNo=1, balance=0.0]
Object inserted
-----CashFlow-----)
Account no=1
Mouvement Date= 2016-1-15
Mouvement Amount=1000.0
-----CashFlow end--)
Object inserted
-----CashFlow-----)
Account no=1
Mouvement Date= 2016-2-15
Mouvement Amount=500.0
-----CashFlow end--)
Object inserted
-----CashFlow-----)
Account no=1
Mouvement Date= 2016-4-15
Mouvement Amount=1000.0
-----CashFlow end--)
Object inserted
AccountingPeriod [startDate=Fri Jan01 00:00:00 CST 2016, endDate=Thu Mar 31 00:00:00 CST 2016]
The rule Credit rule can be fired inagenda
The rule Credit rule will be fired
time:1490949616170-Account no 1 hasnow a balance of 1000.0
The rule Credit rule has be fired
The rule Debit rule can be fired inagenda
The rule Debit rule will be fired
time:1490949616170-Account no 1 hasnow a balance of 500.0
The rule Debit rule has be fired
------------After------------
作为解释,Credit Rule执行一次和"DebitRule"也是执行一次。CashFlow 在April 15 2016被忽略,不满足条件
Summary
在lesson 1,我们学校到动态的规则引擎。怎样和什么时间规则可以调用在本教程,我们开始连接条件一起在事实和怎样关联其他事实在规则里。
lession3
Adding more constraints in facts
我们集中在规则引擎怎样执行在第一节课。在第二节课,我们介绍了怎样去表达事实之间的联系。在这个章节,我们集中精力在所有的drools语言关联更加复杂的事实条件用力。用户需要创建一个TestLesson3 的包在src/test/rules ,并且在kmodule.xml 添加新的定义
<kbase name="rules3"packages="lesson3">
<ksession name="ksession-lesson3"/>
</kbase>
当我绑定例子,你可以看到跟多规则执行。drools是一个函数式语言,当条件被满足,规则就会执行
Some more classes
为了看到更加先进的特性,我们需要添加两个新的类,在src/main/java 添加
Customer :
package droolscours;
public class Customer {
private Stringname;
private Stringsurname;
private Stringcountry;
publicCustomer(String name, String surname, String country) {
super();
this.name =name;
this.surname = surname;
this.country= country;
}
publicCustomer() {
super();
// TODOAuto-generated constructor stub
}
public StringgetCountry() {
returncountry;
}
public voidsetCountry(String country) {
this.country = country;
}
public StringgetName() {
returnname;
}
public voidsetName(String name) {
this.name =name;
}
public StringgetSurname() {
returnsurname;
}
public voidsetSurname(String surname) {
this.surname = surname;
}
@Override
public StringtoString() {
StringBuffer buff = new StringBuffer();
buff.append("-----Customer-----)\n");
buff.append("Name=" + this.name + "\n");
buff.append("Surname Name=" + this.surname + "\n");
buff.append("Country=" + this.country + "\n");
buff.append("-----Customer end-)");
returnbuff.toString();
}
}
PrivateAccount如下:
package droolscours;
public class PrivateAccount extends Account {
privateCustomer owner;
public CustomergetOwner() {
returnowner;
}
public voidsetOwner(Customer owner) {
this.owner= owner;
}
@Override
public StringtoString() {
StringBuffer buff = new StringBuffer();
buff.append("-----Private Account-)");
buff.append(super.toString());
if(this.owner != null) {
buff.append(this.owner.toString());
}
buff.append("-----Private Account end-)");
return buff.toString();
}
}
In Constraint
这就允许去验证一个属性在值列表,规则如下
package cours
//#list any import classes here.
import droolscours.CashFlow;
import util.OutputDisplay;
//#declare any global variables here
global OutputDisplay showResult;
rule "The cashFlow can be a credit or a debit"
when
$cash:CashFlow(type in ( CashFlow.DEBIT,CashFlow.CREDIT) )
then
showResult.showText("The cashFlow is a credit or a debit");
end
测试单元如下:
@Test
public voidtestInConstrait() throws Exception {
sessionStatefull = KnowledgeSessionHelper
.getStatefulKnowledgeSessionWithCallback(kieContainer,"ksession-lesson3");
OutputDisplay display = new OutputDisplay();
sessionStatefull.setGlobal("showResult", display);
CashFlowcashFlow = new CashFlow();
cashFlow.setType(CashFlow.CREDIT);
sessionStatefull.insert(cashFlow);
sessionStatefull.fireAllRules();
} }
运行后结果如下:
------------Before------------
Object inserted
-----CashFlow-----)
Account no=0
No Mouvement date was set
Mouvement Amount=0.0
-----CashFlow end--)
The rule The cashFlow can be a credit or a debit can be fired in agenda
The rule The cashFlow can be a credit or a debit will be fired
time:1490951651843-The cashFlow is acredit or a debit
The rule The cashFlow can be a credit or a debit has be fired
------------After------------
Nested Accessor
嵌套访问
这就允许对一个类的属性添加条件,需要添加到另一个对象的属性
规则添加如下:
rule "Accessor"
when
$cash :PrivateAccount(owner.name =="Héron" )
then
showResult.showText("Account is owned by Héron");
end
测试单元添加方法:
@Test
public voidtestNestedAccessor() throws Exception {
sessionStatefull = KnowledgeSessionHelper
.getStatefulKnowledgeSessionWithCallback(kieContainer,"ksession-lesson3");
OutputDisplay display = new OutputDisplay();
sessionStatefull.setGlobal("showResult", display);
Customercustomer = new Customer();
customer.setName("Héron");
customer.setSurname("Nicolas");
PrivateAccount pAccount = new PrivateAccount();
pAccount.setOwner(customer);
sessionStatefull.insert(pAccount);
sessionStatefull.fireAllRules();
}
我们没有添加customer 到drools的session里面
结果如下:
------------Before------------
Object inserted
-----Private Account-)Account[accountNo=0, balance=0.0]-----Customer-----)
Name=Héron
Surname Name=Nicolas
Country=null
-----Customer end-)-----PrivateAccount end-)
The rule Accessor can be fired inagenda
The rule Accessor will be fired
time:1490951969709-Account is ownedby Héron
The rule Accessor has be fired
------------After------------
这个规则的被执行的
And/or
有可能做一些想java的限制
规则如下:
rule "infixAnd"
when
( $c1 :Customer ( country=="GB") and PrivateAccount( owner==$c1))
or
( $c1 :Customer (country=="US") and PrivateAccount( owner==$c1))
then
showResult.showText("Person lives in GB or US");
end
测试单元如下:
@Test
public void testInOrFact()throws Exception {
sessionStatefull = KnowledgeSessionHelper
.getStatefulKnowledgeSessionWithCallback(kieContainer,"ksession-lesson3");
OutputDisplay display = new OutputDisplay();
sessionStatefull.setGlobal("showResult", display);
Customercustomer = new Customer();
customer.setCountry("GB");
sessionStatefull.insert(customer);
PrivateAccount pAccount = new PrivateAccount();
pAccount.setOwner(customer);
sessionStatefull.insert(pAccount);
sessionStatefull.fireAllRules();
}
运行结果如下:
------------Before------------
Object inserted
-----Customer-----)
Name=null
Surname Name=null
Country=GB
-----Customer end-)
Object inserted
-----Private Account-)Account[accountNo=0, balance=0.0]-----Customer-----)
Name=null
Surname Name=null
Country=GB
-----Customer end-)-----PrivateAccount end-)
The rule infixAnd can be fired inagenda
The rule infixAnd will be fired
time:1490952168060-Person lives inGB or US
The rule infixAnd has be fired
------------After------------
not
测试如果在这个session没有这种类型的事实
规则如下:
rule "no customer"
when
notCustomer( )
then
showResult.showText("No customer");
end
测试如下:
@Test
public voidtestNotCondition() throws Exception {
sessionStatefull = KnowledgeSessionHelper
.getStatefulKnowledgeSessionWithCallback(kieContainer,"ksession-lesson3");
OutputDisplay display = new OutputDisplay();
sessionStatefull.setGlobal("showResult", display);
sessionStatefull.fireAllRules();
}
结果:
------------Before------------
The rule no customer can be fired inagenda
The rule no customer will be fired
time:1490952300065-No customer
The rule no customer has be fired
------------After------------
exist
跟上面的相反,至少一个事实在session
rule "Exists"
when
existsAccount( )
then
showResult.showText("Account exists");
end
测试单元如下:
@Test
public voidtestExistsCondition() throws Exception {
sessionStatefull= KnowledgeSessionHelper
.getStatefulKnowledgeSessionWithCallback(kieContainer,"ksession-lesson3");
OutputDisplay display = new OutputDisplay();
sessionStatefull.setGlobal("showResult", display);
AccountpAccount = new Account();
sessionStatefull.insert(pAccount);
Customer c= new Customer();
sessionStatefull.insert(c);
sessionStatefull.fireAllRules();
}
结果:
------------Before------------
Object inserted
Account [accountNo=0, balance=0.0]
Object inserted
-----Customer-----)
Name=null
Surname Name=null
Country=null
-----Customer end-)
The rule Exists can be fired inagenda
The rule Exists will be fired
time:1490952445635-Account exists
The rule Exists has be fired
------------After------------
ForAll
我们可以确认每一个Account 对应的 CashFlow
rule "ForAll"
when
forall( Account( $no : accountNo )
CashFlow( accountNo == $no)
)
then
showResult.showText("All cashflows are related to an Account");
end
在这个规则,在forall 条件下,我们连接CashFLow实例到Account实例。我们对所有的对象关联测试
@Test
public voidtestForALl() throws Exception {
sessionStatefull = KnowledgeSessionHelper
.getStatefulKnowledgeSessionWithCallback(kieContainer,"ksession-lesson3");
OutputDisplay display = new OutputDisplay();
sessionStatefull.setGlobal("showResult", display);
Account a =new Account();
a.setAccountNo(1);
a.setBalance(0);
sessionStatefull.insert(a);
CashFlowcash1 = new CashFlow();
cash1.setAccountNo(1);
sessionStatefull.insert(cash1);
CashFlowcash2 = new CashFlow();
cash2.setAccountNo(1);
sessionStatefull.insert(cash2);
Account a2= new Account();
a2.setAccountNo(2);
a2.setBalance(0);
sessionStatefull.insert(a2);
CashFlowcash3 = new CashFlow();
cash3.setAccountNo(2);
sessionStatefull.insert(cash3);
sessionStatefull.fireAllRules();
}
执行结果如下:
The rule ForAll can be fired inagenda
The rule ForAll will be fired
time:1490952839763-All cashflows are relatedto an Account
From
有些时候需要访问一些外部数据。因为不可能插入所有的对象到一个session里面,我们可以使用在指令部分
首先 让我创建一个 CustomerService 类在Droolscours.sercice包下
package droolscours.service;
import droolscours.Customer;
import java.util.ArrayList;
import java.util.List;
public class CustomerService {
publicList<Customer> getListCustomer() {
List<Customer>result = new ArrayList<Customer>();
result.add(new Customer("Héron", "Nicolas","Fr"));
result.add(new Customer("Héron", "James","GB"));
result.add(new Customer("Héron", "Nicolas","GB"));
returnresult;
}
}
然后我们可以创建一个规则使用from
规则如下:
rule "FromCondition"
when
$c :Customer()
$cc :Customer(name ==$c.name,surname==$c.surname,country !=$c.country) fromserviceCustomer.getListCustomer();
then
showResult.showText("Found same customer in 2 countries");
end
测试单元如下:
@Test
public voidtestFromLHS() throws Exception {
sessionStatefull =KnowledgeSessionHelper.getStatefulKnowledgeSessionWithCallback(kieContainer,
"ksession-lesson3");
OutputDisplay display = new OutputDisplay();
sessionStatefull.setGlobal("showResult", display);
sessionStatefull.setGlobal("serviceCustomer", newCustomerService());
Customer c= new Customer("Héron", "Nicolas", "A");
sessionStatefull.insert(c);
sessionStatefull.fireAllRules();
}
结果如下:
The rule FromCondition can be firedin agenda
The rule FromCondition can be firedin agenda
The rule FromCondition will be fired
time:1490953326562-Found samecustomer in 2 countries:-----Customer-----)
Name=Héron
Surname Name=Nicolas
Country=A
-----Customer end-)
The rule FromCondition has be fired
The rule FromCondition will be fired
time:1490953326563-Found samecustomer in 2 countries:-----Customer-----)
Name=Héron
Surname Name=Nicolas
Country=A
-----Customer end-)
The rule FromCondition has be fired
------------After------------
规则会被执行两次在一个service有相同的名字,不同的城市的
Collecting
为了收集一组事实对像目的和约束是真实的。让我们看看下面的例子在"More then 2 CashFlow Line".规则。在这个规则里面,我们想收集所有CashFlow,in一个当前的时间的期间和一个好的帐务数值。"from collect" 语法返回一个列表。可能添加一个条件在第一个规则我们添加一个约束就是至少2项在第二个规则。
规则如下:
rule "More then 2 CashFlow Line"
when
$c :Account( $acc : accountno )
$p :AccountingPeriod ($sDate : startDate ,$eDate : endDate )
$number :ArrayList(size >= 2 )
fromcollect( CashFlow( mvtDate >= $sDate && mvtDate <= $eDate,accountNo == $acc ) )
then
showResult.showText("Found more than 2 CashFlow Lines");
showResult.showText("<<<<<<<<<<");
for (Objectff : $number){
showResult.showText(ff.toString());
}
showResult.showText(">>>>>>>>>>>>>>>>");
end
rule "Numbers of CashFlow Line"
when
$c :Account( $acc : accountno )
$p :AccountingPeriod ($sDate : startDate ,$eDate : endDate )
$number :ArrayList( )
fromcollect( CashFlow( mvtDate >= $sDate && mvtDate <= $eDate,accountNo == $acc ) )
then
showResult.showText("Found "+$number+" more than 2CashFlow Lines");
end
修改一下类:
public AccountingPeriod() {
}
publicAccountingPeriod(Date startDate, Date endDate) {
super();
this.startDate = startDate;
this.endDate = endDate;
}
public CashFlow(){
super();
}
public CashFlow(DatemvtDate, double amount, int type, long accountNo) {
super();
this.mvtDate = mvtDate;
this.amount= amount;
this.type =type;
this.accountNo = accountNo;
}
测试单元如下:
@Test
public voidtestCollecting() throws Exception {
sessionStatefull =KnowledgeSessionHelper.getStatefulKnowledgeSessionWithCallback(kieContainer,
"lesson34-session");
OutputDisplay display = new OutputDisplay();
sessionStatefull.setGlobal("showResult", display);
Account a =new Account();
a.setAccountNo(1);
a.setBalance(0);
sessionStatefull.insert(a);
sessionStatefull.insert(newCashFlow(DateHelper.getDate("2010-01-15"), 1000, CashFlow.CREDIT,1));
sessionStatefull.insert(newCashFlow(DateHelper.getDate("2010-02-15"), 500, CashFlow.DEBIT, 1));
sessionStatefull.insert(newCashFlow(DateHelper.getDate("2010-04-15"), 1000, CashFlow.CREDIT,1));
sessionStatefull
.insert(new AccountingPeriod(DateHelper.getDate("2010-01-01"),DateHelper.getDate("2010-31-31")));
sessionStatefull.fireAllRules();
}
结果很长不打印了``````
Accumulating
累积
rule "Credit and Debit Rule"
when
$c :Account( $acc : accountno )
$p :AccountingPeriod ($sDate : startDate ,$eDate : endDate )
$totalCredit : Number( doubleValue > 100 )
fromaccumulate( CashFlow( type ==CashFlow.CREDIT,$value : amount, mvtDate >=$sDate && mvtDate <=$eDate,accountNo == $acc ),
init( doubletotal = 0; ),
action( total +=$value; ),
reverse( total -=$value; ),
result( total ) )
$totalDebit: Number( doubleValue > 100 )
fromaccumulate( CashFlow( type ==CashFlow.DEBIT,$value : amount, mvtDate >=$sDate && mvtDate <=$eDate,accountNo == $acc ),
init( doubletotal = 0; ),
action( total +=$value; ),
reverse( total -=$value; ),
result( total ) )
then
showResult.showText(" Found "+$totalCredit+" as acredit");
showResult.showText(" Found "+$totalDebit+" as adebit");
end
测试单元:
@Test
public voidtestAccumulate() throws Exception {
sessionStatefull =KnowledgeSessionHelper.getStatefulKnowledgeSessionWithCallback(kieContainer,"ksession-lesson3");
OutputDisplay display = new OutputDisplay();
sessionStatefull.setGlobal("showResult", display);
sessionStatefull.insert(new Account(1,0));
FactHandlefa = sessionStatefull.insert(newCashFlow(DateHelper.getDate("2010-01-15"), 1000, CashFlow.CREDIT,1));
sessionStatefull.insert(newCashFlow(DateHelper.getDate("2010-02-15"),500,CashFlow.DEBIT,1));
sessionStatefull.insert(newCashFlow(DateHelper.getDate("2010-04-15"),1000,CashFlow.CREDIT,1));
sessionStatefull.insert(new AccountingPeriod(DateHelper.getDate("2010-01-01"),DateHelper.getDate("2010-12-31")));
sessionStatefull.fireAllRules();
sessionStatefull.delete(fa);
sessionStatefull.fireAllRules();
}
Summary