[rules-users] Re: How check if all the values in a collection match a criteria

Edson Tirelli tirelli at post.com
Mon May 19 09:32:51 EDT 2008


   Alessandro,

   I'm not sure what the problem in your case is, but the syntax I showed
you is the correct syntax for forall, since a forall is nothing more than
not( A() and not( B() ... ) ).
   I created a JUnit 3 test case (since people was asking for junit
examples) to reproduce the scenario and it works just fine:

================
    public void testExpenses() throws Exception {
        Reader source = new InputStreamReader(
getClass().getResourceAsStream( "/expenses.drl" ) );
        PackageBuilder builder = new PackageBuilder();
        builder.addPackageFromDrl( source );

        RuleBase ruleBase = RuleBaseFactory.newRuleBase();
        ruleBase.addPackage( builder.getPackage() );

        StatefulSession session = ruleBase.newStatefulSession();
        ArrayList<ExpenseReport> results = new ArrayList<ExpenseReport>();
        session.setGlobal( "results", results );

        // CASE 1: empty expense report, should fire
        ExpenseReport report1 = new ExpenseReport(new
ArrayList<ExpenseDetail>());
        session.insert( report1 );
        session.fireAllRules();

        assertEquals( 1, results.size() );
        assertEquals( report1, results.get( 0 ));

        // CASE 2: non-empty expense report, with mixed details, should NOT
fire
        ExpenseDetail[] details2 = new ExpenseDetail[] { new
ExpenseDetail(ExpenseType.TAX), new ExpenseDetail( ExpenseType.MEAL ) };
        ExpenseReport report2 = new ExpenseReport(Arrays.asList( details2
));
        session.insert( report2 );
        session.fireAllRules();

        assertEquals( 1, results.size() );

        // CASE 3: non-empty expense report, with TAX-only details, should
fire
        ExpenseDetail[] details3 = new ExpenseDetail[] { new
ExpenseDetail(ExpenseType.TAX), new ExpenseDetail( ExpenseType.TAX ) };
        ExpenseReport report3 = new ExpenseReport(Arrays.asList( details3
));
        session.insert( report3 );
        session.fireAllRules();

        assertEquals( 2, results.size() );
        assertEquals( report3, results.get( 1 ));
    }

==========
package com.sample

global java.util.List results;

rule "Check all expenses"
when
    $report: ExpenseReport($expenseDetails: expenseDetails)
    not ( $ed : ExpenseDetail() from $expenseDetails and
          not ( ExpenseDetail( this == $ed, type == ExpenseType.TAX ) from
$expenseDetails )
    )
then
    results.add( $report );
end
===========

    If you can make this test break showing your problem, I may be able to
help you out.

    Thanks for opening the JIRA.

    []s
    Edson


2008/5/19 Alessandro Di Bella <aldibella at gmail.com>:

> Hi,
>
> thanks for your help, I created the JIRA as requested (
> http://jira.jboss.org/jira/browse/JBRULES-1611).
>
> The workaround you suggest works only partially, if any of the
> ExpenseDetails is of type ExpenseType.TAX it will fire the rule.
>
> What I would like to do is to fire the rule only if all ExpenseDetails in
> the same report are of type ExpenseType.TAX.
>
> Any help is more than welcome.
>
> Thanks
>
> Alessandro
>
> Edson Tirelli wrote:
>
>>
>>   Hmm, now that you mentioned, I see that our parser is limiting the
>> forall() CE, not allowing nested "from" CEs. This is something we should
>> fix, since the limitation is purely a parser limitation.
>>
>>   Anyway, for your case, the workaround is simply to use the "raw"
>> forall-equivalence: not( A() and not( B() ) ). So try this:
>>
>> rule "Do Not Process TAX"                        when
>>               $report: ExpenseReport($expenseDetails: expenseDetails)
>>               not ( $ed : ExpenseDetails() from $expenseDetails and
>>                     not ( ExpenseDetails( this == $ed, expenseType ==
>> ExpenseType.TAX ) from $expenseDetails )
>>               )
>>  then
>>               System.out.println("################ It works
>> ##################");
>>               insertLogical("Bypass Process");
>> end
>>
>>   This is just more verbose than the forall, but it is exactly the same.
>> Once the parser is fixed, you will be able to simply write:
>>
>> rule "Do Not Process TAX"                        when
>>               $report: ExpenseReport($expenseDetails: expenseDetails)
>>               forall ( ExpenseDetails( expenseType == ExpenseType.TAX )
>> from $expenseDetails )
>>  then
>>               System.out.println("################ It works
>> ##################");
>>               insertLogical("Bypass Process");
>> end
>>
>>    BTW, may I ask you please to open a JIRA so we don't forget to fix this
>> for 5.0?
>>
>>    Thanks,
>>         Edson
>>
>>
>>
>> 2008/5/18 Alessandro Di Bella <aldibella at gmail.com <mailto:
>> aldibella at gmail.com>>:
>>
>>    Hi,
>>
>>    I have these two classes:
>>
>>    ExpenseReport{
>>     Collection<ExpenseDetails> expenseDetails
>>    }
>>    ExpenseDetails{    ExpenseReport document
>>     ExpenseType expenseType
>>    }
>>
>>    I am trying to create a rule that fires when all the ExpenseDetails in
>> a
>>    ExpenseReport  are of the same type:
>>
>>    rule "Do Not Process TAX"                        when
>>                   $report: ExpenseReport($expenseDetails: expenseDetails)
>>                   forall (
>>   ExpenseDetails(document==$report, expenseType
>>    == ExpenseType.TAX)
>>                   )          then
>>                   System.out.println("################ It works
>>    ##################");
>>                   insertLogical("Bypass Process");
>>    end
>>
>>    For some reasons, it fires regardless that value of
>>    ExpenseDetails.expenseType.
>>
>>    I just started with drools and any help i more than welcome.
>>
>>    Thanks
>>
>>    _______________________________________________
>>    rules-users mailing list
>>    rules-users at lists.jboss.org <mailto:rules-users at lists.jboss.org>
>>    https://lists.jboss.org/mailman/listinfo/rules-users
>>
>>
>>
>>
>> --
>> Edson Tirelli
>> JBoss Drools Core Development
>> Office: +55 11 3529-6000
>> Mobile: +55 11 9287-5646
>> JBoss, a division of Red Hat @ www.jboss.com <http://www.jboss.com>
>>
>>
>> ------------------------------------------------------------------------
>>
>> _______________________________________________
>> rules-users mailing list
>> rules-users at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/rules-users
>>
>
> _______________________________________________
> rules-users mailing list
> rules-users at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/rules-users
>



-- 
Edson Tirelli
JBoss Drools Core Development
Office: +55 11 3529-6000
Mobile: +55 11 9287-5646
JBoss, a division of Red Hat @ www.jboss.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/rules-users/attachments/20080519/31ab2bc7/attachment.html 


More information about the rules-users mailing list