【Drools学习笔记】07-exists与insertLogical

我们先看个例子,然后在说明两个函数的作用。

kmodule.xml

<kbase name="FireKB" packages="org.drools.examples.fire.simple">
    <ksession name="FireKS"/>
</kbase>

<kbase name="FireLogicalKB" packages="org.drools.examples.fire.logical">
    <ksession name="FireLogicalKS"/>
</kbase>

Fire.drl在org.drools.examples.fire.simple下

package org.drools.examples.fire.simple;

import org.drools.examples.fire.Fire;
import org.drools.examples.fire.Alarm;
import org.drools.examples.fire.Room;
import org.drools.examples.fire.Sprinkler;

rule RaiseAlarm when
     exists Fire()
then
    insert( new Alarm( "house1" ) );
    System.out.println( "Raise the Alarm");
end

rule CancelAlarm when
    not Fire()
    a : Alarm()
then
    delete( a );
    System.out.println( "Cancel the Alarm");
end

rule ThereIsAnAlarm when
     Alarm()
then
    System.out.println( "there is an Alarm " );
end

rule ThereIsNoAlarm when
     not Alarm()
then
    System.out.println( "there is no Alarm " );
end

rule TurnSprinklerOn when
    s : Sprinkler( on == false )
    f : Fire( room == s.room )
then
    modify( s ) { setOn( true ) }
    System.out.println( "Turn on the sprinkler for room " + f.getRoom().getName() );
end

rule TurnSprinklerOff when
    s : Sprinkler( on == true )
    not Fire( room == s.room )
then
    modify( s ) { setOn( false ) }
    System.out.println( "Turn off the sprinkler for room " + s.getRoom().getName() );
end

rule OK when
    not Alarm()
    not Sprinkler( on == true )
then
    System.out.println( "Everything is ok" );
end

FireLogical.drl在org.drools.examples.fire.logical下

package org.drools.examples.fire.logical;

import org.drools.examples.fire.Fire;
import org.drools.examples.fire.Alarm;
import org.drools.examples.fire.Room;
import org.drools.examples.fire.Sprinkler;

rule RaiseAlarm when
     Fire()
then
    insertLogical( new Alarm( "house1" ) );
    System.out.println( "Raise the Alarm");
end

rule ThereIsAnAlarm when
     Alarm()
then
    System.out.println( "there is an Alarm " );
end

rule ThereIsNoAlarm when
     not Alarm()
then
    System.out.println( "there is no Alarm " );
end

rule TurnSprinklerOn when
    s : Sprinkler( on == false )
    f : Fire( room == s.room )
then
    modify( s ) { setOn( true ) }
    System.out.println( "Turn on the sprinkler for room " + f.getRoom().getName() );
end

rule TurnSprinklerOff when
    s : Sprinkler( on == true )
    not Fire( room == s.room )
then
    modify( s ) { setOn( false ) }
    System.out.println( "Turn off the sprinkler for room " + s.getRoom().getName() );
end

rule OK when
    not Alarm()
    not Sprinkler( on == true )
then
    System.out.println( "Everything is ok" );
end

下面是模型类。

package org.drools.examples.fire;

public class Alarm {
    private String name;

    public Alarm(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Alarm{" +
               "name='" + name + '\'' +
               '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) { return true; }
        if (o == null || getClass() != o.getClass()) { return false; }

        Alarm alarm = (Alarm) o;

        if (!name.equals(alarm.name)) { return false; }

        return true;
    }

    @Override
    public int hashCode() {
        return name.hashCode();
    }
}
package org.drools.examples.fire;

public class Fire {
    private Room room;

    public Fire(Room room) {
        this.room = room;
    }

    public Room getRoom() {
        return room;
    }

    public void setRoom(Room room) {
        this.room = room;
    }

    @Override
    public String toString() {
        return "Fire{" +
               "room=" + room +
               '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) { return true; }
        if (o == null || getClass() != o.getClass()) { return false; }

        Fire fire = (Fire) o;

        if (!room.equals(fire.room)) { return false; }

        return true;
    }

    @Override
    public int hashCode() {
        return room.hashCode();
    }
}
package org.drools.examples.fire;

public class Room {
    private String name;

    public Room(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Room{" +
               "name='" + name + '\'' +
               '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) { return true; }
        if (o == null || getClass() != o.getClass()) { return false; }

        Room room = (Room) o;

        if (!name.equals(room.name)) { return false; }

        return true;
    }

    @Override
    public int hashCode() {
        return name.hashCode();
    }
}
package org.drools.examples.fire;

public class Sprinkler {
    private Room room;
    private boolean on;

    public Sprinkler(Room room) {
        this.room = room;
    }

    public Sprinkler(Room room, boolean on) {
        this.room = room;
        this.on = on;
    }

    public Room getRoom() {
        return room;
    }

    public void setRoom(Room room) {
        this.room = room;
    }

    public boolean isOn() {
        return on;
    }

    public void setOn(boolean on) {
        this.on = on;
    }

    @Override
    public String toString() {
        return "Sprinkler{" +
               "room=" + room +
               ", on=" + on +
               '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) { return true; }
        if (o == null || getClass() != o.getClass()) { return false; }

        Sprinkler sprinkler = (Sprinkler) o;

        if (on != sprinkler.on) { return false; }
        if (!room.equals(sprinkler.room)) { return false; }

        return true;
    }

    @Override
    public int hashCode() {
        int result = room.hashCode();
        result = 31 * result + (on ? 1 : 0);
        return result;
    }
}

测试类。

package org.drools.examples.fire;

import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.rule.FactHandle;

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class FireExample {
    public static void main(final String[] args) {
        KieContainer kc = KieServices.Factory.get().getKieClasspathContainer();
        KieSession ksession = kc.newKieSession("FireKS");

        String[] names = new String[]{"kitchen", "bedroom", "office", "livingroom"};
        Map<String,Room> name2room = new HashMap<>(4);

        for( String name: names ){
            Room room = new Room( name );
            name2room.put( name, room );
            ksession.insert( room );
            Sprinkler sprinkler = new Sprinkler( room );
            ksession.insert( sprinkler );
        }

        ksession.fireAllRules();
        pause();

        Fire kitchenFire = new Fire( name2room.get( "kitchen" ) );
        Fire officeFire = new Fire( name2room.get( "office" ) );

        FactHandle kitchenFireHandle = ksession.insert( kitchenFire );
        FactHandle officeFireHandle = ksession.insert( officeFire );

        ksession.fireAllRules();
        pause();

        ksession.delete( kitchenFireHandle );
        ksession.delete(officeFireHandle);

        ksession.fireAllRules();

        ksession.dispose(); // Stateful rule session must always be disposed when finished
    }

    public static void pause() {
        System.out.println( "Pressure enter to contnue" );
        Scanner keyboard = new Scanner(System.in);
        keyboard.nextLine();
    }
}

运行结果

there is no Alarm 
Everything is ok
Pressure enter to contnue

Raise the Alarm
there is an Alarm 
Turn on the sprinkler for room kitchen
Turn on the sprinkler for room office
Pressure enter to contnue

Cancel the Alarm
there is no Alarm 
Turn off the sprinkler for room kitchen
Turn off the sprinkler for room office
Everything is ok

测试类

package org.drools.examples.fire;

import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.rule.FactHandle;

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class FireLogicalExample {
    public static void main(final String[] args) {
        KieContainer kc = KieServices.Factory.get().getKieClasspathContainer();
        KieSession ksession = kc.newKieSession("FireLogicalKS");

        String[] names = new String[]{"kitchen", "bedroom", "office", "livingroom"};
        Map<String,Room> name2room = new HashMap<>(4);

        for( String name: names ){
            Room room = new Room( name );
            name2room.put( name, room );
            ksession.insert( room );
            Sprinkler sprinkler = new Sprinkler( room );
            ksession.insert( sprinkler );
        }

        ksession.fireAllRules();
        pause();

        Fire kitchenFire = new Fire( name2room.get( "kitchen" ) );
        Fire officeFire = new Fire( name2room.get( "office" ) );

        FactHandle kitchenFireHandle = ksession.insert( kitchenFire );
        FactHandle officeFireHandle = ksession.insert( officeFire );

        ksession.fireAllRules();
        pause();

        ksession.delete( kitchenFireHandle );
        ksession.delete(officeFireHandle);

        ksession.fireAllRules();
        pause();

        ksession.dispose(); // Stateful rule session must always be disposed when finished
    }

    public static void pause() {
        System.out.println( "Pressure enter to contnue" );
        Scanner keyboard = new Scanner(System.in);
        keyboard.nextLine();
    }
}

运行结果

there is no Alarm 
Everything is ok
Pressure enter to contnue

Raise the Alarm
Raise the Alarm
there is an Alarm 
Turn on the sprinkler for room kitchen
Turn on the sprinkler for room office
Pressure enter to contnue

there is no Alarm 
Turn off the sprinkler for room kitchen
Turn off the sprinkler for room office
Everything is ok

对比两次运行结果发现:

  • 同样是插入了两个Fire对象,Fire.drl中规则RaiseAlarm只触发了一次,FireLogical.drl中规则RaiseAlarm触发了两次。
  • 在将Fire对象全部删除后,Fire.drl中会触发规则CancelAlarm->ThereIsNoAlarm->TurnSprinklerOff->OK,FireLogical.drl中并没有像Fire.drl一样在规则CancelAlarm中删除Alarm但依旧触发了规则ThereIsNoAlarm。

综上:

  • 对于exists Fire(),表示只在乎是否存在而不在乎存在几个,即使存在多个RHS只生效一次。对Fire(),存在几个RHS就会执行几次。
  • insertLogical当没有更多的fact支持当前激发规则的真值状态时,对象自动删除。 对于FireLogical.drl,使用insertLogical插入一个Alarm对象后,会触发事件ThereIsAnAlarm后不会再触发新的规则,这个Alarm就会自动删除了,也就不需要显示删除了。

猜你喜欢

转载自blog.csdn.net/shenchaohao12321/article/details/80913525