Движок правил 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
,