Add support to load rules with a ParserContext in MVELRuleFactory

Resolves 
pull/200/head
Mahmoud Ben Hassine
parent c83ff59da8
commit 3f6e87b202

@ -28,6 +28,7 @@ import org.jeasy.rules.api.Condition;
import org.jeasy.rules.api.Facts;
import org.jeasy.rules.api.Rule;
import org.jeasy.rules.core.BasicRule;
import org.mvel2.ParserContext;
import java.util.ArrayList;
import java.util.List;
@ -88,7 +89,17 @@ public class MVELRule extends BasicRule {
* @return this rule
*/
public MVELRule when(String condition) {
this.condition = new MVELCondition(condition);
return this.when(condition, new ParserContext());
}
/**
* Specify the rule's condition as MVEL expression.
* @param condition of the rule
* @param parserContext the MVEL parser context
* @return this rule
*/
public MVELRule when(String condition, ParserContext parserContext) {
this.condition = new MVELCondition(condition, parserContext);
return this;
}
@ -98,7 +109,17 @@ public class MVELRule extends BasicRule {
* @return this rule
*/
public MVELRule then(String action) {
this.actions.add(new MVELAction(action));
return this.then(action, new ParserContext());
}
/**
* Add an action specified as an MVEL expression to the rule.
* @param action to add to the rule
* @param parserContext the MVEL parser context
* @return this rule
*/
public MVELRule then(String action, ParserContext parserContext) {
this.actions.add(new MVELAction(action, parserContext));
return this;
}

@ -24,14 +24,8 @@
package org.jeasy.rules.mvel;
import org.jeasy.rules.api.Rule;
import org.jeasy.rules.api.Rules;
import org.jeasy.rules.support.ActivationRuleGroup;
import org.jeasy.rules.support.CompositeRule;
import org.jeasy.rules.support.ConditionalRuleGroup;
import org.jeasy.rules.support.UnitRuleGroup;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
class MVELRuleDefinition {
@ -40,12 +34,9 @@ class MVELRuleDefinition {
private String description = Rule.DEFAULT_DESCRIPTION;
private int priority = Rule.DEFAULT_PRIORITY;
private String condition;
private List<String> actions;
private Rules composingRules;
private List<String> actions = new ArrayList<>();
private List<MVELRuleDefinition> composingRules = new ArrayList<>();
private String compositeRuleType;
private List<String> allowedCompositeRuleTypes = new ArrayList<>(
Arrays.asList(UnitRuleGroup.class.getSimpleName(), ConditionalRuleGroup.class.getSimpleName(), ActivationRuleGroup.class.getSimpleName())
);
public String getName() {
return name;
@ -88,11 +79,7 @@ class MVELRuleDefinition {
}
void setComposingRules(List<MVELRuleDefinition> composingRuleDefinitions) {
composingRules = new Rules();
for (MVELRuleDefinition ruleDefinition : composingRuleDefinitions) {
Rule rule = ruleDefinition.create();
composingRules.register(rule);
}
this.composingRules = composingRuleDefinitions;
}
void setCompositeRuleType(String compositeRuleType) {
@ -103,56 +90,11 @@ class MVELRuleDefinition {
return compositeRuleType;
}
Rules getComposingRules() {
List<MVELRuleDefinition> getComposingRules() {
return composingRules;
}
Rule create() {
if (isCompositeRule()) {
return createCompositeRule();
} else {
return createSimpleRule();
}
}
private Rule createSimpleRule() {
MVELRule mvelRule = new MVELRule()
.name(name)
.description(description)
.priority(priority)
.when(condition);
for (String action : actions) {
mvelRule.then(action);
}
return mvelRule;
}
private Rule createCompositeRule() {
CompositeRule compositeRule;
switch (compositeRuleType) {
case "UnitRuleGroup":
compositeRule = new UnitRuleGroup(name);
break;
case "ActivationRuleGroup":
compositeRule = new ActivationRuleGroup(name);
break;
case "ConditionalRuleGroup":
compositeRule = new ConditionalRuleGroup(name);
break;
default:
throw new IllegalArgumentException("Invalid composite rule type, must be one of " + allowedCompositeRuleTypes);
}
compositeRule.setDescription(description);
compositeRule.setPriority(priority);
for (Rule rule : composingRules) {
compositeRule.addRule(rule);
}
return compositeRule;
}
private boolean isCompositeRule() {
return composingRules != null;
boolean isCompositeRule() {
return !composingRules.isEmpty();
}
}

@ -86,8 +86,8 @@ class MVELRuleDefinitionReader {
} else if (composingRules != null) {
List<MVELRuleDefinition> composingRuleDefinitions = new ArrayList<>();
for (Object rule : composingRules){
Map<String, Object> composingRulesMap = (Map<String, Object>) rule;
composingRuleDefinitions.add(createRuleDefinitionFrom(composingRulesMap));
Map<String, Object> composingRuleMap = (Map<String, Object>) rule;
composingRuleDefinitions.add(createRuleDefinitionFrom(composingRuleMap));
}
ruleDefinition.setComposingRules(composingRuleDefinitions);
ruleDefinition.setCompositeRuleType(compositeRuleType);

@ -25,8 +25,14 @@ package org.jeasy.rules.mvel;
import org.jeasy.rules.api.Rule;
import org.jeasy.rules.api.Rules;
import org.jeasy.rules.support.ActivationRuleGroup;
import org.jeasy.rules.support.CompositeRule;
import org.jeasy.rules.support.ConditionalRuleGroup;
import org.jeasy.rules.support.UnitRuleGroup;
import org.mvel2.ParserContext;
import java.io.Reader;
import java.util.Arrays;
import java.util.List;
/**
@ -36,7 +42,13 @@ import java.util.List;
*/
public class MVELRuleFactory {
private static MVELRuleDefinitionReader reader = new MVELRuleDefinitionReader();
private static final MVELRuleDefinitionReader READER = new MVELRuleDefinitionReader();
private static final List<String> ALLOWED_COMPOSITE_RULE_TYPES = Arrays.asList(
UnitRuleGroup.class.getSimpleName(),
ConditionalRuleGroup.class.getSimpleName(),
ActivationRuleGroup.class.getSimpleName()
);
/**
* Create a new {@link MVELRule} from a Reader.
@ -45,8 +57,19 @@ public class MVELRuleFactory {
* @return a new rule
*/
public static Rule createRuleFrom(Reader ruleDescriptor) {
MVELRuleDefinition ruleDefinition = reader.read(ruleDescriptor);
return ruleDefinition.create();
return createRuleFrom(ruleDescriptor, new ParserContext());
}
/**
* Create a new {@link MVELRule} from a Reader.
*
* @param ruleDescriptor as a Reader
* @param parserContext the MVEL parser context
* @return a new rule
*/
public static Rule createRuleFrom(Reader ruleDescriptor, ParserContext parserContext) {
MVELRuleDefinition ruleDefinition = READER.read(ruleDescriptor);
return createRule(ruleDefinition, parserContext);
}
/**
@ -56,11 +79,67 @@ public class MVELRuleFactory {
* @return a set of rules
*/
public static Rules createRulesFrom(Reader rulesDescriptor) {
return createRulesFrom(rulesDescriptor, new ParserContext());
}
/**
* Create a set of {@link MVELRule} from a Reader.
*
* @param rulesDescriptor as a Reader
* @return a set of rules
*/
public static Rules createRulesFrom(Reader rulesDescriptor, ParserContext parserContext) {
Rules rules = new Rules();
List<MVELRuleDefinition> ruleDefinition = reader.readAll(rulesDescriptor);
List<MVELRuleDefinition> ruleDefinition = READER.readAll(rulesDescriptor);
for (MVELRuleDefinition mvelRuleDefinition : ruleDefinition) {
rules.register(mvelRuleDefinition.create());
rules.register(createRule(mvelRuleDefinition, parserContext));
}
return rules;
}
private static Rule createRule(MVELRuleDefinition ruleDefinition, ParserContext context) {
if (ruleDefinition.isCompositeRule()) {
return createCompositeRule(ruleDefinition, context);
} else {
return createSimpleRule(ruleDefinition, context);
}
}
private static Rule createSimpleRule(MVELRuleDefinition ruleDefinition, ParserContext parserContext) {
MVELRule mvelRule = new MVELRule()
.name(ruleDefinition.getName())
.description(ruleDefinition.getDescription())
.priority(ruleDefinition.getPriority())
.when(ruleDefinition.getCondition(), parserContext);
for (String action : ruleDefinition.getActions()) {
mvelRule.then(action, parserContext);
}
return mvelRule;
}
private static Rule createCompositeRule(MVELRuleDefinition ruleDefinition, ParserContext parserContext) {
CompositeRule compositeRule;
String name = ruleDefinition.getName();
switch (ruleDefinition.getCompositeRuleType()) {
case "UnitRuleGroup":
compositeRule = new UnitRuleGroup(name);
break;
case "ActivationRuleGroup":
compositeRule = new ActivationRuleGroup(name);
break;
case "ConditionalRuleGroup":
compositeRule = new ConditionalRuleGroup(name);
break;
default:
throw new IllegalArgumentException("Invalid composite rule type, must be one of " + ALLOWED_COMPOSITE_RULE_TYPES);
}
compositeRule.setDescription(ruleDefinition.getDescription());
compositeRule.setPriority(ruleDefinition.getPriority());
for (MVELRuleDefinition composingRuleDefinition : ruleDefinition.getComposingRules()) {
compositeRule.addRule(createRule(composingRuleDefinition, parserContext));
}
return compositeRule;
}
}

@ -172,28 +172,28 @@ public class MVELRuleDefinitionReaderTest {
assertThat(ruleDefinition).isNotNull();
assertThat(ruleDefinition.getName()).isEqualTo("Movie id rule");
assertThat(ruleDefinition.getDescription()).isEqualTo("description");
assertThat(ruleDefinition.getPriority()).isEqualTo(1);
assertThat(ruleDefinition.getCompositeRuleType()).isEqualTo("UnitRuleGroup");
assertThat(ruleDefinition.getComposingRules()).isNotEmpty();
Rules subrules = ruleDefinition.getComposingRules();
List<MVELRuleDefinition> subrules = ruleDefinition.getComposingRules();
assertThat(subrules).hasSize(2);
Iterator<Rule> iterator = subrules.iterator();
Rule subrule = iterator.next();
assertThat(subrule.getName()).isEqualTo("Movie is rated R");
assertThat(subrule.getDescription()).isEqualTo("If the movie is rated R");
assertThat(subrule.getPriority()).isEqualTo(1);
subrule = iterator.next();
MVELRuleDefinition subrule = subrules.get(0);
assertThat(subrule.getName()).isEqualTo("Time is evening");
assertThat(subrule.getDescription()).isEqualTo("If it's later than 7pm");
assertThat(subrule.getPriority()).isEqualTo(1);
subrule = subrules.get(1);
assertThat(subrule.getName()).isEqualTo("Movie is rated R");
assertThat(subrule.getDescription()).isEqualTo("If the movie is rated R");
assertThat(subrule.getPriority()).isEqualTo(1);
ruleDefinition = ruleDefinitions.get(1);
assertThat(ruleDefinition).isNotNull();
assertThat(ruleDefinition.getName()).isEqualTo("weather rule");
assertThat(ruleDefinition.getDescription()).isEqualTo("when it rains, then take an umbrella");
assertThat(ruleDefinition.getComposingRules()).isNull();
assertThat(ruleDefinition.getComposingRules()).isEmpty();
assertThat(ruleDefinition.getCondition()).isEqualTo("rain == True");
assertThat(ruleDefinition.getActions()).isEqualTo(Collections.singletonList("System.out.println(\"It rains, take an umbrella!\");"));
}

Loading…
Cancel
Save