droolsbusiness-rules

Drools JBOSS rule Nested IF's


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.


Solution

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