Java 8 rules engine
Rule: An object composed of a name, priority, predicate, and output function.
Match: When the predicate condition of a Rule is met (returns true)
RuleSet: An iterable collection of Rule objects
RuleMap: Maps a group name to a RuleSet
Evaluator: Uses a Rule/RuleSet to Evaluate an input and produce an output
When a rule is evaluated, its predicate is tested against the input. If the result is true, then it is considered a Match. After a Match the output function is applied to the input and (optionally) returns a result. For a multi match call, this result (if it exists) is then added to a collection of outputs, which is passed to the caller upon completion of the Evaluation. Otherwise, for a single evaluation, the rule's function is applied and the output ignored. Only the output of the final Matched rule is returned as the result.
- _Rule<I,O> extends Comparable<Rule<I,O>>
- Methods
- getName(): String
- getGroupName(): String
- getNextGroupName(): String
- getPriority(): int
- getMatchCondition(): Predicate
- testMatchCondition(): boolean
- getOnMatchHandler(): Function<I,O>
- applyOnMatchHandler(): void
- Methods
- _RuleSet<I,O> extends Iterable<Rule<I,O>>
- Methods
- size(): int
- stream(): Stream<_Rule<I,O>>
- iterator(): Iterator<_Rule<I,O>>
- add(_Rule<I,O> rule): boolean
- contains(_Rule<I,O> rule): boolean
- remove(_Rule<I,O> rule): boolean
- Methods
- _RuleMap<I,O>
- Methods
- getRuleGroup(String groupName): _RuleSet<I,O>
- getGroupNames(): Set
- getNumberOfGroups: int
- Methods
- _Evaluator<I,O>
- Methods
- evaluate(I input, O output) : EvaluationResult<I,O>
- Methods
At minimum a rule requires only 2 inputs: A name and a predicate. The name used as a unique identifier within a set. The predicate is the expression evaluated to determine if this rule is to be applied for the given input I. Optional members are a function or consumer, a priority, a group name, and a next group name. If they are not defined, they will be set to the default values shown below.
Default: (i) -> Optional.empty()
When a rule is matched, the result is the invocation of the onMatchHandler defined. A function will return an output of type Optional<O>, while a consumer will perform some or no operations on the input and return an Optional.empty().
Default: 0
Priority defines the order rules are evaluated within their group. Highest priority goes first. If two rules are tied for priority, they are evaluated alphabetically by their name.
Default: "DEFAULT"
Defines a group of rules to be evaluated as one RuleSet. Once a match is found in that group, evaluation either goes to next group, or halts if there is no next group. The group name "DEFAULT" will always be the first group evaluated.
Default: "HALT"
Defines a pointer to a group of rules to be evaluated next if the rule with this pointer is matched. A next group of "HALT" defines the end of an evaluation.
Rules are instantiated by use of a RuleBuilder. The constructor takes a String and a predicate, and contains methods for additional rule options
/*
A rule that evaluates if an integer is greater than or equal to 100, then adds 2 to it and adds it to the output.
*/
_Rule<Integer,List<Integer>> myRule = new Rule.RuleBuilder<Integer,List<Integer>>("myRule", i -> i >= 100)
.onMatchHandler((i,o) -> {
int result = i + 2;
o.add(result);
})
.build();
/*
A rule that evaluates if an integer is greater than or equal to 100, then prints a String.
This rule then points to another group called "Some other group" to be evaluated next.
*/
_Rule<Integer,List<Integer>> myRule = new Rule.RuleBuilder<Integer,List<Integer>>("myRule", i -> i >= 100)
.onMatchHandler((i,o) -> System.out.println(i + " is greater than or equals to 100"))
.nextGroupName("Some other group")
.build();
A collection of Rule objects unique on rule name.
Add a rule to the set, returns true if it is added successfully. Throws DuplicateRuleException if the rule is already contained in the set.
Return true if the given rule is contained within the set
Return true if the rule is in the set and successfully removed.
Returns the number of contained rules.
Returns a new Iterator of the contained rules.
Returns a new Stream of the contained rules.
_RuleSet<String, List<Integer>> ruleSet = new RuleSet<>();
ruleSet.add(someRule1); // true
ruleSet.add(someRule2); // true
ruleSet.size(); // 2
ruleSet.contains(someRule2); // true
ruleSet.contains(someRule3); // false
ruleSet.remove(someRule2); // true
ruleSet.contains(someRule2); // false
A map of rule group name to a _RuleSet. Initialized using a populated _RuleSet.
Get the _RuleSet mapped to the given group name
Get the names of the groups contained in the map (the key set)
Get the number of groups contained in the map (size)
_RuleSet<String, List<Integer>> ruleSet = new RuleSet<>();
ruleSet.add(someRule1);
ruleSet.add(someRule2);
_RuleMap<String, List<Integer>> ruleMap = new RuleMap<>(ruleSet);
ruleMap.getRuleGroup("Some Group Name");
ruleMap.getGroupNames();
ruleMap.getNumberOfGroups();
Instantiated using a _RuleSet, which is used to populate a _RuleMap.
Evaluates a given input (facts) against the contained rules and returns the relevant output (knowledge).
_RuleSet<String, List<Integer>> ruleSet = new RuleSet<>();
ruleSet.add(someRule1);
ruleSet.add(someRule2);
_RuleEvaluator<String, List<Integer>> evaluator = new RuleEvaluator<>(ruleSet);
String input = "Some input string";
List<Integer> output = new ArrayList<>();
EvaluationResult<String, List<Integer>> result = evaluator.evaluate(input, output);
result.getKnowledge().value(); // List<Integer>