Easy-Rules规则引擎,不能同时触发多个事实

问题描述 投票:0回答:2

我正在尝试扩展Shop Tutorial以便于在多个shop上运行简单规则(facts)。在规则中写条件时,我们使用“事实名称”调用函数,如下所示,

condition: "people.isAdult() == false"

因为,people只是facts中ONE对象实例的名称,所以定义上面的条件并不好。如何定义条件,使其迭代多个facts

我想要实现的是在规则引擎的一次火灾中评估多个事实的规则。

当具有相同事实名称的事实数组被提供给规则引擎时,仅评估提供的最后一个事实。但是,当为每个事实分配不同的名称时,我不能为每个名称分配相同的条件。

您可以在下面看到代码。假设Person类具有所有成员的基本get / set函数。

Rules.yml:

---
name: "regex"
description: "Check if regex pattern matches"
priority: 1
condition: "people.getPayload().matches(\".*12.*34$\") == true"
actions:
 - "System.out.println(\"There is a match\");"
---
name: "age"
description: "Check if person's age is > 18 and marks the person as adult"
priority: 2
condition: "people.age > 18"
actions:
  - "people.setAdult(true);"
---
name: "alkol"
description: "children are not allowed to buy alcohol"
priority: 3
condition: "people.isAdult() == false"
actions:
  - "System.out.println(\"Shop: Sorry, you are not allowed to buy portakal\");"

主要:

//create a person instance (fact)   
            Person [] PeopleArray = new Person [100];
            Person [] KidsArray = new Person [300];

        // initialize arrays
            for(int i = 0; i < PeopleArray.length ; i++)
            {
               PeopleArray[i] = new Person("TOM"+i,23);
               PeopleArray[i].setPayload(dummystring);
            }
            for(int i = 0; i < KidsArray.length ; i++)
            {
                KidsArray[i] = new Person("EMRE"+i,13);
                KidsArray[i].setPayload(dummystring);
            }


        Facts facts = new Facts();

        // create a rule set
        Rules rules = MVELRuleFactory.createRulesFrom(new FileReader("rules.yml"));

        RulesEngine rulesEngine = new DefaultRulesEngine();

        System.out.println("Tom: Hi! can I have some Vodka please?");

      //put the facts
        for(int i = 0; i < PeopleArray.length ; i++)
            facts.put("people", PeopleArray[i]);
        long start = System.currentTimeMillis();
        for(int i = 0; i < KidsArray.length ; i++)
            facts.put("people", KidsArray[i]);

        rulesEngine.fire(rules, facts);
java rule-engine mvel
2个回答
2
投票

Facts对象本质上是一个hashmap。因此,通过设计,您不能使用相同的密钥放置两个事实。

我在你的例子中看到people事实是一个数组。现在,如何在mvel表达式中处理数组是另一回事。说实话,我能给出的最佳答案是查看MVEL文档:https://github.com/imona/tutorial/wiki/MVEL-Guide#arrays

我想要实现的是在规则引擎的一次火灾中评估多个事实的规则。

我不确定这可以通过简单的规则来实现。我想你可以:

  • 要么平面映射你的事实
  • 或者在不同的事实上多次致电fire

希望这可以帮助。


1
投票

Fact实际上只是一个Map

Map<String, Object> facts = new HashMap<>()       // from source code

如果您需要添加多个事实,然后使用它们立即触发规则,您可以使用List来完成。一个人可以创建一个List<Object>并将此List添加到Facts

规则类:

@Rule(name = "Hello World rule", description = "Always say hello world")
public class HelloWorldRule {

    @Condition
    public boolean when() {
        return true;
    }

    @Action
    public void then(@Fact("facts") List<Object> arr) throws Exception {
        for (Object i : arr) {
            System.out.print(i + ", ");
        }
    }

}

发射器类:

public class Launcher {

    public static void main(String[] args) {

        // create facts
        Facts facts = new Facts();
        List<Object> arr = new ArrayList<>();
        arr.add("hello");
        arr.add(5);
        facts.put("facts", arr);

        // create rules
        Rules rules = new Rules();
        rules.register(new HelloWorldRule());

        // create a rules engine and fire rules on known facts
        RulesEngine rulesEngine = new DefaultRulesEngine();
        rulesEngine.fire(rules, facts);

    }
}

请记住,如果不是Object而是你拥有相同类型的所有对象,就像在这种情况下Person一样,这真的很有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.