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(a)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(a)gmail.com <mailto:
> aldibella(a)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(a)lists.jboss.org <mailto:rules-users@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(a)lists.jboss.org
>
https://lists.jboss.org/mailman/listinfo/rules-users
>
_______________________________________________
rules-users mailing list
rules-users(a)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