Движок правил Easy-Rules, не может срабатывать сразу по нескольким фактам - PullRequest
0 голосов
/ 30 апреля 2018

Я пытаюсь расширить Учебное пособие по магазинам для простых правил ( shop ) для работы с несколькими facts. При написании условий в правиле мы вызываем функции, используя «имя факта», как показано ниже:

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

Поскольку people - это просто имя ОДНОГО экземпляра объекта в facts, определение условия, подобного приведенному выше, не годится. Как определить условие так, чтобы оно повторялось по нескольким 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\");"

Main:

//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);

Ответы [ 2 ]

0 голосов
/ 14 февраля 2019

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.

0 голосов
/ 08 мая 2018

A Facts объект по сути является hashmap. Таким образом, вы не можете поместить два факта с одним ключом.

В вашем примере я вижу, что факт people является массивом. Теперь о том, как обращаться с массивами в выражении mvel - это другая история. Если честно, лучший ответ, который я могу дать, это посмотреть документы MVEL: https://github.com/imona/tutorial/wiki/MVEL-Guide#arrays

Чего я хочу добиться, так это оценить правила по нескольким фактам в одном запуске механизма правил.

Я не уверен, что это возможно с простыми правилами. Я думаю, что вы можете:

  • Либо плоская карта ваших фактов
  • Или позвоните fire несколько раз по разным фактам

Надеюсь, это поможет.

...