<br>   Yap, Wolfgang has the picture right. Just 2 clarifications:<br><br>* A single pattern forall in Drools is a syntax sugar to a multi-pattern forall in the following way:<br><br>forall( Pattern( &lt;constraints&gt; ) ) <br>
=&gt; <br>forall( $p : Pattern() <br>         Pattern( this == $p, &lt;constraints&gt; )<br><br>   In other words, drools uses the fact type to define the domain and apply the constraints to all objects in that domain.<br>
<br>* &quot;not&quot; is the quantifier CE that means &quot;not exists&quot;. If you explicitly write &quot;not( exists ( ) )&quot;, the &quot;exists&quot; is redundant, but not eliminated automatically by Drools yet. So, you are wasting quite a lot of performance, since that forces drools to create a subnetwork in Rete. For Drools 5.1 and forward I will automatically eliminate the exists during the logical transformation step, but up to 5.0.x, you need to do it manually.<br>
<br>    Edson<br><br><br><div class="gmail_quote">2009/11/7 Wolfgang Laun <span dir="ltr">&lt;<a href="mailto:wolfgang.laun@gmail.com">wolfgang.laun@gmail.com</a>&gt;</span><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Here&#39;s the explanation why Tom&#39;s version does not work. The first
pattern of a &quot;forall&quot; defines the domain, which is: all CreditReport
facts; for each object in this domain, the remaining patterns must
match; since the FICO pattern merely ascertains the existence of a
single FICO chained to a parent CreditReport with validScoreIndicator
false, it fires as soon as there is one for each of the existing
CreditReports.<br><br>
Jared&#39;s solution has the CreditReport CE in front of the forall,
unadorned with any quantifier, and the innate behavior of Drools makes
sure that the hole thing will be tried, once, for any existing CreditReport
anyway. Then, the forall domain is now FICOs with that CR&#39;s id and valid == false - but what is the CE? I guess that Drool&#39;s behavior is somewhat off the definition, using just FICO() - i.e., all existing FICO objects - as the domain. (However, I think that Edson changed this recently for 5.1.0.) Thus, Jared&#39;s rule indeed fires only when all FICOs are linked to the CreditReport are false, but it fails to do so as soon as there is at least one other FICO with either a different parent, or valid.<br>


<br>Therefore, to be on the safe side with multiple CreditReport facts and assorted FICO&#39;s being in WM at the same time, I propose this rule:<br><br>rule &quot;somerule2&quot;<div class="im"><br>when<br>    report: CreditReport( $parentCreditReport_1_Id : myId)<br>
</div>
    forall ( $f : FICO( parentId == $parentCreditReport_1_Id )<br>             FICO( this == $f, validScoreIndicator == false) )<br>then<br>    System.out.println(&quot;somerule2 fired on &quot; + $parentCreditReport_1_Id );<br>

end<br><br>Here, the domain is explicitly given as all FICOs of the current CR; and for all of them valid must be false.<br><br>Still, this solution is not perfect: It would also fire in the absence of any FICO for some CR. To fix this, add a guard against there being no FICOs for the current CR:<div class="im">
<br>
<br>report: CreditReport( $parentCreditReport_1_Id : myId)<br></div>            exists FICO( parentId == $parentCreditReport_1_Id )<br>forall ( $f : FICO( parentId == $parentCreditReport_1_Id )<br>
             FICO( this == $f, validScoreIndicator == false) )<br><br>To complete the picture, one might equally well use the negation of forall, which would have to be propagated into the predicate (read &#39;|&#39; as &quot;so that&quot;):<br>

    forall x in D | P(x) =&gt; not existst x in D | not P(x)<br><br>Now the condition delimiting the domain and the negated predicate can be merged again into one CE:<br><br>rule &quot;somerule3&quot;<div class="im"><br>
when<br>    report: CreditReport( $parentCreditReport_1_Id : myId)<br></div>
    exists FiCo( parentId == $parentCreditReport_1_Id )<br>    not ( exists FiCo( parentId == $parentCreditReport_1_Id, validScore == true) )<br>then<br>    System.out.println(&quot;somerule3 fired on &quot; + $parentCreditReport_1_Id );<br>

end<br><font color="#888888"><br>-W</font><div><div></div><div class="h5"><br><br><div class="gmail_quote">On Fri, Nov 6, 2009 at 9:45 PM, Jared Davis <span dir="ltr">&lt;<a href="mailto:sunray@davisprogramming.com" target="_blank">sunray@davisprogramming.com</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
I think this usage may work for your case.<br>
<br>
rule &quot;somerule&quot;<br>
  when<br>
    report: CreditReport( $parentCreditReport_1_Id : myId)<br>
    forall (<br>
<div>      FICO( parentId == $parentCreditReport_1_Id, validScoreIndicator == false)<br>
    )<br>
  then<br>
</div>    System.out.print(&quot;Fired on &quot; + $parentCreditReport_1_Id );<br>
end<br>
<br>
<br>
<br>
_______________________________________________<br>
rules-users mailing list<br>
<a href="mailto:rules-users@lists.jboss.org" target="_blank">rules-users@lists.jboss.org</a><br>
<a href="https://lists.jboss.org/mailman/listinfo/rules-users" target="_blank">https://lists.jboss.org/mailman/listinfo/rules-users</a><br>
</blockquote></div><br>
</div></div></blockquote></div><br><br clear="all"><br>-- <br>  Edson Tirelli<br>  JBoss Drools Core Development<br>  JBoss by Red Hat @ <a href="http://www.jboss.com">www.jboss.com</a><br>