Движок правил Easy-Rules, не может срабатывать сразу по нескольким фактам

Я пытаюсь расширить Учебное пособие по магазинам для простых правил ( магазин) для работы на нескольких 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\");"

Главный:

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

1 ответ

Решение

Facts Объект по сути является хэш-картой. Таким образом, вы не можете поместить два факта с одним и тем же ключом.

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

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

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

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

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

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,

Другие вопросы по тегам