Drools JBOSS rule Nested IF's

Pankaj Chaswal picture Pankaj Chaswal · Mar 19, 2012 · Viewed 11.8k times · Source

I am a newbie with Jboss Rule. I have gone through the documentation but I fail to find the approach to begin writing rule for following code sample.

For each User code in the list 
{
    If User code = ‘11’ 
    {
        If User code ‘17’ present in the group 
        {
            Add letter id 1
        }
        Else If User code ‘18’ present in the group 
        {
            Add letter id 2
        }
    }
    Else 
    {
        Add letter id 3 which is the letter need to be sent for code 11
    }
}

EDIT:

So far this is what i can develop for the user case discussed above.

  1. I am inserting (List of UserDetailVo) to the drools session.
  2. Object (UserDetailVo) contains (List of UserInfoVo). Every UserInfoVo contains a code.

Now I want to iterate over the (List of UserInfoVo) and update (letterId) to every (UserDetailVo) as i am trying to do below.

Case1 : when codeList has 110,121

rule "USER LETTER GROUPING 110,121" 
salience 300
no-loop true

    when
        userDetailVo : UserDetailVo ()
        UserInfoVo(code=="110") from userDetailVo.codeList
        UserInfoVo(code=="121") from userDetailVo.codeList
    then
        userDetailVo.addLetterId(1);
        //modify(trrDetailRequestVo)
end
    

Case2 : when codeList has 110,127

rule "USER LETTER GROUPING 110,127" 
        salience 300
        no-loop true
    
            when
                userDetailVo : UserDetailVo ()
                UserInfoVo(code=="110") from userDetailVo.codeList
                UserInfoVo(code=="127") from userDetailVo.codeList
            then
                userDetailVo.addLetterId(2);
                //modify(trrDetailRequestVo)
        end

Case3 : when codeList has only 110

rule "USER LETTER GROUPING 110" 
    salience 300
    no-loop true
    
        when
            userDetailVo : UserDetailVo (this.letterID.size() == 0) // Checking size of the list
            UserInfoVo(code=="110") from userDetailVo.codeList
        then
            userDetailVo.addLetterId(3);
            //modify(trrDetailRequestVo)
    end

Issues that I am facing is if I user modify/update at the end of rule. It goes into an infinite loop. If I remove modify/update, in case 3 though list size if greater than 0 still rule is fired.

Answer

mike9322 picture mike9322 · Mar 20, 2012

The concept of "else" doesn't really translate directly to a declarative language. Instead, you have to explicitly define what "else" truly means in terms of your data and write a rule (or rules) based on that condition. As an example, consider the following conditions:

If Order Total >= 1000
  Discount = 15%
Else If Order Total >= 500
  Discount = 10%
Else If Order Total >= 250
  Discount = 5%
Else
  Discount = 0%

The natural first attempt at rules for these conditions might be:

rule "15% discount"
  when
    $o : Order( total >= 1000 )
  then
    modify($o) { setDiscount(.15); }
end

rule "10% discount"
  when
    $o : Order( total >= 500 )
  then
    modify($o) { setDiscount(.10); }
end

etc...

The problem with this approach is that both the 10% and 15% rules will match for an Order whose total is 1200. This is because the "else" part of "else if" inherently includes the condition that the order total is not greater than 1000. So we write our rules like this instead:

rule "15% discount"
  when
    $o : Order( total >= 1000, discount == null )
  then
    modify($o) { setDiscount(.15); }
end

rule "10% discount"
  when
    $o : Order( total >= 500, total < 1000, discount == null )
  then
    modify($o) { setDiscount(.10); }
end

rule "5% discount"
  when
    $o : Order( total >= 250, total < 500, discount == null )
  then
    modify($o) { setDiscount(.05); }
end

rule "no discount"
  when
    $o : Order( total < 250, discount == null )
  then
    modify($o) { setDiscount(0); }
end

(You'll notice I also added a discount == null condition. This is to prevent the rule from reactivating when the Order fact is updated.)

I've been focusing on a simple example rather than your specific use case to demonstrate the concept of writing a condition to mimic an "else". I'm still not sure I completely understand your use case, but hopefully I've answered the key conceptual part of your question.