ram
ram

Reputation: 777

What would be the ideal data structures for implementing rules like scenario?

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:

  1. The list of attributes is fixed for now but may change.
  2. The incoming feed format is fixed.
  3. Not on the lines of Java rules implementation.
  4. Algorithmic answer is accepted, Java 7 implementation is preferred.

My solution:

  1. The rule set is organized as Map<String, List<Criterion>>, where key is ID and Criterion contains attribute, operator and value as fields.

  2. 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.

  3. For each entry in List<Map<String, String>, do below to find the ID

  4. 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

Answers (1)

Jakub Kubrynski
Jakub Kubrynski

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

Related Questions