List Info

Thread: How check if all the values in a collection match a criteria




How check if all the values in a collection match a criteria
country flaguser name
Ireland
2008-05-18 12:04:10
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-userslists.jboss.org

https://lists.jboss.org/mailman/listinfo/rules-users

Re: How check if all the values in a collection match a criteria
user name
2008-05-18 14:30:34

 &nbsp; 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.

 &nbsp; Anyway, for your case, the workaround is simply to use the "raw&quot; forall-equivalence: not( A() and not( B() ) ). So try this:

rule "Do Not Process TAX"                        when
               $report: ExpenseReport($expenseDetails: expenseDetails)
             &nbsp; not ( $ed : ExpenseDetails() from $expenseDetails and
 &nbsp; &nbsp; &nbsp;   ; &nbsp; &nbsp; &nbsp; &nbsp;   ; not ( ExpenseDetails( this == $ed, expenseType == ExpenseType.TAX ) from $expenseDetails )
 &nbsp; &nbsp;   ; &nbsp; &nbsp; &nbsp;  )
 then
&nbsp;            &nbsp; System.out.println(&quot;################ It works ##################&quot;);
&nbsp;            &nbsp; insertLogical("Bypass Process&quot;);
end

&nbsp;  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)
             &nbsp; forall ( ExpenseDetails( expenseType == ExpenseType.TAX ) from $expenseDetails )
 then
 ;            &nbsp; System.out.println(&quot;################ It works ##################&quot;);
&nbsp;            &nbsp; insertLogical("Bypass Process&quot;);
end

&nbsp; &nbsp; BTW, may I ask you please to open a JIRA so we don't forget to fix this for 5.0?

&nbsp; &nbsp; Thanks,
&nbsp; &nbsp;   ; &nbsp; Edson



2008/5/18 Alessandro Di Bella < aldibellagmail.com">aldibellagmail.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 ##################&quot;);
               insertLogical(&quot;Bypass Process&quot;);
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-userslists.jboss.org" target="_blank">rules-userslists.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
Re: How check if all the values in a collection match a criteria
country flaguser name
Ireland
2008-05-19 03:50:20
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 <aldibellagmail.com

> <mailto:aldibellagmail.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-userslists.jboss.org <mailto:rules-userslists.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-userslists.jboss.org
> 
https://lists.jboss.org/mailman/listinfo/rules-users

_______________________________________________
rules-users mailing list
rules-userslists.jboss.org

https://lists.jboss.org/mailman/listinfo/rules-users

Re: Re: How check if all the values in a collection match a criteria
user name
2008-05-19 08:32:51

 &nbsp; Alessandro,

 &nbsp; 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() ... ) ).
 &nbsp; 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 {
 &nbsp; &nbsp;   ; Reader source = new InputStreamReader( getClass().getResourceAsStream( "/expenses.drl&quot; ) );
 &nbsp;   ; &nbsp; PackageBuilder builder = new PackageBuilder();
&nbsp;   ; &nbsp;  builder.addPackageFromDrl( source );
 &nbsp;   ; &nbsp;
 &nbsp; &nbsp; &nbsp;  RuleBase ruleBase = RuleBaseFactory.newRuleBase();
&nbsp;   ; &nbsp;  ruleBase.addPackage( builder.getPackage() );
 &nbsp;   ; &nbsp;
 &nbsp; &nbsp; &nbsp;  StatefulSession session = ruleBase.newStatefulSession();
 &nbsp; &nbsp; &nbsp;  ArrayList&lt;ExpenseReport> results = new ArrayList&lt;ExpenseReport>();
 &nbsp; &nbsp; &nbsp;  session.setGlobal( "results", results );
 &nbsp;   ; &nbsp;
 &nbsp; &nbsp; &nbsp;  // CASE 1: empty expense report, should fire
 ; &nbsp; &nbsp; &nbsp; ExpenseReport report1 = new ExpenseReport(new ArrayList&lt;ExpenseDetail>());
   ; &nbsp; &nbsp; session.insert( report1 );
 &nbsp;   ; &nbsp; session.fireAllRules();
 &nbsp; &nbsp;   ;
 &nbsp; &nbsp; &nbsp;  assertEquals( 1, results.size() );
 &nbsp;   ; &nbsp; assertEquals( report1, results.get( 0 ));
   ; &nbsp; &nbsp;
 &nbsp; &nbsp; &nbsp;  // CASE 2: non-empty expense report, with mixed details, should NOT fire
&nbsp; &nbsp; &nbsp;   ExpenseDetail[] details2 = new ExpenseDetail[] { new ExpenseDetail(ExpenseType.TAX), new ExpenseDetail( ExpenseType.MEAL ) };
 &nbsp;   ; &nbsp; ExpenseReport report2 = new ExpenseReport(Arrays.asList( details2 ));
   ; &nbsp; &nbsp; session.insert( report2 );
 ; &nbsp; &nbsp; &nbsp; session.fireAllRules();
 &nbsp; &nbsp;   ;
 &nbsp; &nbsp; &nbsp;  assertEquals( 1, results.size() );
 &nbsp;   ; &nbsp;
 &nbsp; &nbsp; &nbsp;  // CASE 3: non-empty expense report, with TAX-only details, should fire
 ; &nbsp; &nbsp; &nbsp; ExpenseDetail[] details3 = new ExpenseDetail[] { new ExpenseDetail(ExpenseType.TAX), new ExpenseDetail( ExpenseType.TAX ) };
 ; &nbsp; &nbsp; &nbsp; ExpenseReport report3 = new ExpenseReport(Arrays.asList( details3 ));
   ; &nbsp; &nbsp; session.insert( report3 );
 &nbsp;   ; &nbsp; session.fireAllRules();
 &nbsp; &nbsp;   ;
 &nbsp; &nbsp; &nbsp;  assertEquals( 2, results.size() );
 &nbsp;   ; &nbsp; assertEquals( report3, results.get( 1 ));
&nbsp; &nbsp; }

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

global java.util.List results;

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

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

&nbsp; &nbsp; Thanks for opening the JIRA.

&nbsp; &nbsp; []s
   ; Edson


2008/5/19 Alessandro Di Bella < aldibellagmail.com">aldibellagmail.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&quot; 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(&quot;################ It works ##################&quot;);
              insertLogical("Bypass Process&quot;);
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(&quot;################ It works ##################&quot;);
              insertLogical("Bypass Process&quot;);
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 < aldibellagmail.com" target="_blank">aldibellagmail.com <mailto: aldibellagmail.com" target="_blank">aldibellagmail.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(&quot;################ It works
   ##################");
                  insertLogical("Bypass Process&quot;);
   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-userslists.jboss.org" target="_blank">rules-userslists.jboss.org <mailto: rules-userslists.jboss.org" target="_blank">rules-userslists.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-userslists.jboss.org" target="_blank">rules-userslists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-users

_______________________________________________
rules-users mailing list
rules-userslists.jboss.org" target="_blank">rules-userslists.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
[1-4]

about | contact  Other archives ( Real Estate discussion Medical topics )