Reputation: 449
I need to implement a simple rules engine with hierarchical fallback support. I have already looked into the DROOLS library but I am not sure if it supports my use case.
The use case is rather simple which makes me thinking whether I need a rules engine at all? Nevertheless, here is the use case -
I have a modal with bunch of fields
Public Class Entity {
public int val0;
public int val1;
public int val2;
public int val3;
.....
}
Now, I want to create rules against these fields as follow
RULE1 --- IF val0 == 1 && val1 == 1 && val2 == 1 && val3 == 1 --- (1,1,1,1) THEN DO this
RULE2 --- IF val0 == 1 && val1 == 1 && val2 == 1 && val3 == 2, --- (1,1,1,2) THEN DO this
RULE3 --- IF val0 == 1 && val1 == 1 && val2 == 1 && val3 == *, --- (1,1,1,*) THEN DO this
RULE4 --- IF val0 == 1 && val1 == 1 && val2 == * && val3 == *, --- (1,1,*,*) THEN DO this
The problem is with RULE3
and RULE4
where val2 and val3 can match any value.
e.g.
val0=1, val1=1, val2=1, val3=1 -- should execute RULE1 - specific match
val0=1, val1=1, val2=1, val3=3 -- should execute RULE3 - generic match as there's no specific match for val3
val0=1, val1=1, val2=10, val3=5 -- should execute RULE4 - generic match as there's no specific match for val2 and val3
So depending on the query, either I will find the matching rule or I will have to fallback to the more generic rules. Is there any existing rules engine library that provides this functionality or rather do I even need a rules engine library to implement this functionality?
Upvotes: 2
Views: 562
Reputation: 1707
At first I thought you might want to consider using bitwise logic, but with some of the fields taking non-binary values this probably doesn't really work for you.
However, the solution needn't be that complicated. Just create a class that acts as a matcher for the values of Entity
and use a chain of if-else statements to find the match.
class EntityMatcher {
private Integer val0, val1, val2, val3;
/** Constructor used to match all the parameters */
EntityMatcher(int val0, int val1, int val2, int val3) {
// set fields 0-3
}
/** Constructor used when you don't care about val2 & val3 */
EntityMatcher(int val0, int val1) {
// set fields 0 & 1, leaving val2 and val3 as null
}
boolean matches(Entity toMatchAgainst) {
return (this.val0 == null || this.val0 == toMatchAgainst.val0)
&& (this.val1 == null || this.val1 == toMatchAgainst.val1)
...
&& (this.valN == null || this.valN == toMatchAgainst.valN);
}
}
Then your rules engine could look something like this:
if (new EntityMatcher(1, 1, 1, 1).matches(entity))
// Rule 1
else if (new EntityMatcher(1, 1, 1, 2).matches(entity))
// Rule 2
...
else if (new EntityMatcher(1, 1).matches(entity))
// Rule 4
...
else
// no match
This is essentially the same idea as case classes in Scala.
Upvotes: 2