Reputation: 777
Consider the following scenario, where rules defined by ID need to satisfy all conditions .
RULES ID Attribute1 Operator1 Value1 Attribute2 Operator2 Value1 ... And so on ------------------------------------------------------------------- 1 x = 10 a IN 5,10 2 x = 20 a IN 10,15 3 x = 20 a IN 25,20
The above means if(x=10) & if(a = 5 or a = 10} & ..., then ID = 1
In case of an incoming feed for the format [x, a, ...]
10, 5, ... 10, 10, ... 20, 20, ...
then IDs should be
1 1 3
I wish to check if there is a more easy and elegant way than the below solution and which data structure to be used.
What are the cons of the data structures & approach used in the below solution? (sure there could be)
Assumptions:
My solution:
The rule set is organized as Map<String, List<Criterion>>
, where key is ID and Criterion contains attribute, operator and value as fields.
The data is organized as List<Map<String, String>>
, where key is the attribute (could be x or a etc.) and value as the actual value in the feed.
For each entry in List<Map<String, String>
, do below to find the ID
Loop through each of the entries in Map<String, List<Criterion>>
and invoke the below method. In case true
is returned, I log the ID, which is the key and break the rule loop & proceeed to next data item.
public boolean executeRules(List<Criterion> list,
Map<String, String> dataItem) {
boolean fullMatch = true;
if(CollectionUtils.isNotEmpty(list)){
for(Criterion rule : list) {
switch (rule.getOperator()) {
case EQUAL_TO: //Similar to EQUAL TO
if(!rule.getValue().equals(dataItem.get(rule.getOperand()))){
fullMatch = false;
}
break;
case IN://Similar to IN
List<String> inCriteria = null;
if(rule.getValue() != null) {
inCriteria = Arrays.asList(((String) rule.getValue()).split("\\s*,\\s*"));
if(!inCriteria.contains(dataItem.get(rule.getOperand()))){
fullMatch = false;
}
} else {
fullMatch = false;
}
break;
default:
LOG.error("Invalid Operator: " + rule.getOperator());
fullMatch = false;
break;
}
if(!fullMatch) {
return false;
}
}
} else {
LOG.error("No Rules found");
return false;
}
return true;
}
PS: Not a homework; just some research.
Upvotes: 0
Views: 1425
Reputation: 14149
I think that you could make use of SmartParam library (http://smartparam.org/). It is designed for such evaluations and is very generic, so you can use if even with properties file as well as with database
Upvotes: 3