Drools JBOSS rule Nested IF's

12,356

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.

Share:
12,356
Pankaj Chaswal
Author by

Pankaj Chaswal

Updated on June 04, 2022

Comments

  • Pankaj Chaswal
    Pankaj Chaswal about 2 years

    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.