Drools--用户指南(drools训练第二课)

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

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值