<html xmlns="http://www.w3.org/TR/xhtml1/transitional"><head xmlns="">
      <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
   <title>3.6.&nbsp;Advanced Conditional Elements</title><link rel="stylesheet" href="../shared/css/html.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets Vsnapshot_6797"><link rel="start" href="title.html" title="Drools"><link rel="up" href="ch03.html" title="Chapter&nbsp;3.&nbsp;The Rule Language"><link rel="prev" href="ch03s05.html" title="3.5.&nbsp;Rule"><link rel="next" href="ch03s07.html" title="3.7.&nbsp;Query"><base xmlns="http://www.w3.org/TR/xhtml1/transitional" target="body"></base></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div xmlns="" class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">3.6.&nbsp;Advanced Conditional Elements</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ch03s05.html">Prev</a>&nbsp;</td><th width="60%" align="center">Chapter&nbsp;3.&nbsp;The Rule Language</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="ch03s07.html">Next</a></td></tr></table><hr></div><div xmlns="" class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e2677"></a>3.6.&nbsp;Advanced Conditional Elements</h2></div></div></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p><em class="replaceable"><code>(updated to Drools 4.0)</code></em></p></div><p>Drools 4.0 introduces a whole new set of conditional elements in order
  to support full First Order Logic expressiveness, as well as some facilities
  for handling collections of facts. This section will detail the following
  new Conditional Elements:</p><div class="itemizedlist"><ul type="disc"><li><p>from</p></li><li><p>collect</p></li><li><p>accumulate</p></li><li><p>forall</p></li></ul></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2699"></a>3.6.1.&nbsp;From</h3></div></div></div><p>The <span class="bold"><strong>from</strong></span> Conditional Element allows
    users to specify a source for patterns to reason over. This allows the
    engine to reason over data not in the Working Memory. This could be a
    sub-field on a bound variable or the results of a method call. It is a
    powerful construction that allows out of the box integration with other
    application components and frameworks. One common example is the
    integration with data retrieved on-demand from databases using hibernate
    named queries.</p><p>The expression used to define the object source is any expression
    that follows regular MVEL syntax. I.e., it allows you to easily use object
    property navigation, execute method calls and access maps and collections
    elements.</p><p>Here is a simple example of reasoning and binding on another pattern
    sub-field:</p><pre class="programlisting">rule "validate zipcode"
when
    Person( $personAddress : address ) 
    Address( zipcode == "23920W") from $personAddress 
then
    # zip code is ok
end
</pre><p>With all the flexibility from the new expressiveness in the Drools
    engine you can slice and dice this problem many ways. This is the same but
    shows how you can use a graph notation with the 'from':</p><pre class="programlisting">rule "validate zipcode"
when
    $p : Person( ) 
    $a : Address( zipcode == "23920W") from $p.address 
then
    # zip code is ok
end
</pre><p>Previous examples were reasoning over a single pattern. The
    <span class="bold"><strong>from</strong></span> CE also support object sources that
    return a collection of objects. In that case, <span class="bold"><strong>from</strong></span> will iterate over all objects in the
    collection and try to match each of them individually. For instance, if we
    want a rule that applies 10% discount to each item in an order, we could
    do:</p><pre class="programlisting">rule "apply 10% discount to all items over US$ 100,00 in an order"
when
    $order : Order()
    $item  : OrderItem( value &gt; 100 ) from $order.items
then
    # apply discount to $item
end
</pre><p>The above example will cause the rule to fire once for each item
    whose value is greater than 100 for each given order.</p><p>The next example shows how we can reason over the results of a
    hibernate query. The Restaurant pattern will reason over and bind with
    each result in turn:</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2733"></a>3.6.2.&nbsp;Collect</h3></div></div></div><p>The <span class="bold"><strong>collect</strong></span> Conditional Element
    allows rules to reason over collection of objects collected from the given
    source or from the working memory. A simple example:</p><pre class="programlisting">import java.util.ArrayList

rule "Raise priority if system has more than 3 pending alarms"
when
    $system : System()
    $alarms : ArrayList( size &gt;= 3 )
              from collect( Alarm( system == $system, status == 'pending' ) )
then
    # Raise priority, because system $system has
    # 3 or more alarms pending. The pending alarms
    # are $alarms.
end
</pre><p>In the above example, the rule will look for all pending alarms in
    the working memory for each given system and group them in ArrayLists. If
    3 or more alarms are found for a given system, the rule will fire.</p><p>The <span class="bold"><strong>collect</strong></span> CE result pattern can
    be any concrete class that implements tha java.util.Collection interface
    and provides a default no-arg public constructor. I.e., you can use
    default java collections like ArrayList, LinkedList, HashSet, etc, or your
    own class, as long as it implements the java.util.Collection interface and
    provide a default no-arg public constructor.</p><p>Both source and result patterns can be constrained as any other
    pattern.</p><p>Variables bound before the <span class="bold"><strong>collect</strong></span>
    CE are in the scope of both source and result patterns and as so, you can
    use them to constrain both your source and result patterns. Although, the
    <span class="emphasis"><em>collect( ... )</em></span> is a scope delimiter for bindings,
    meaning that any binding made inside of it, is not available for use
    outside of it.</p><p>Collect accepts nested <span class="bold"><strong>from</strong></span>
    elements, so the following example is a valid use of <span class="bold"><strong>collect</strong></span>:</p><pre class="programlisting">import java.util.LinkedList;

rule "Send a message to all mothers"
when
    $town : Town( name == 'Paris' )
    $mothers : LinkedList() 
               from collect( Person( gender == 'F', children &gt; 0 ) 
                             from $town.getPeople() 
                           )
then
    # send a message to all mothers
end
</pre></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2770"></a>3.6.3.&nbsp;Accumulate</h3></div></div></div><p>The <span class="bold"><strong>accumulate</strong></span> Conditional Element
    is a more flexible and powerful form of <span class="bold"><strong>collect</strong></span> Conditional Element, in the sense that it
    can be used to do what <span class="bold"><strong>collect</strong></span> CE does
    and also do things that <span class="bold"><strong>collect</strong></span> CE is not
    capable to do. Basically what it does is it allows a rule to iterate over
    a collection of objects, executing custom actions for each of the
    elements, and at the end return a result object.</p><p>The general syntax of the <span class="bold"><strong>accumulate</strong></span> CE is:</p><pre class="programlisting"><em class="replaceable"><code>&lt;result pattern&gt;</code></em> from accumulate( <em class="replaceable"><code>&lt;source pattern&gt;</code></em>,
                                  init( <em class="replaceable"><code>&lt;init code&gt;</code></em> ),
                                  action( <em class="replaceable"><code>&lt;action code&gt;</code></em> ),
                                  reverse( <em class="replaceable"><code>&lt;reverse code&gt;</code></em> ),
                                  result( <em class="replaceable"><code>&lt;result expression&gt;</code></em> ) )
</pre><p>The meaning of each of the elements is the following:</p><div class="itemizedlist"><ul type="disc"><li><p><span class="bold"><strong>&lt;source pattern&gt;</strong></span>: the
        source pattern is a regular pattern that the engine will try to match
        against each of the source objects.</p></li><li><p><span class="bold"><strong>&lt;init code&gt;</strong></span>: this is a
        semantic block of code in the selected dialect that will be executed
        once for each tuple, before iterating over the source objects.</p></li><li><p><span class="bold"><strong>&lt;action code&gt;</strong></span>: this is a
        semantic block of code in the selected dialect that will be executed
        for each of the source objects.</p></li><li><p><span class="bold"><strong>&lt;reverse code&gt;</strong></span>: this is
        an optional semantic block of code in the selected dialect that if
        present will be executed for each source object that no longer matches
        the source pattern. The objective of this code block is to "undo" any
        calculation done in the &lt;action code&gt; block, so that the engine
        can do decremental calculation when a source object is modified or
        retracted, hugely improving performance of these operations.</p></li><li><p><span class="bold"><strong>&lt;result expression&gt;</strong></span>: this
        is a semantic expression in the selected dialect that is executed
        after all source objects are iterated.</p></li><li><p><span class="bold"><strong>&lt;result pattern&gt;</strong></span>: this is
        a regular pattern that the engine tries to match against the object
        returned from the &lt;result expression&gt;. If it matches, the
        <span class="bold"><strong>accumulate</strong></span> conditional element
        evaluates to <span class="bold"><strong>true</strong></span> and the engine
        proceeds with the evaluation of the next CE in the rule. If it does
        not matches, the <span class="bold"><strong>accumulate</strong></span> CE
        evaluates to <span class="bold"><strong>false</strong></span> and the engine
        stops evaluating CEs for that rule.</p></li></ul></div><p>It is easier to understand if we look at an example:</p><pre class="programlisting">rule "Apply 10% discount to orders over US$ 100,00"
when
    $order : Order()
    $total : Number( doubleValue &gt; 100 ) 
             from accumulate( OrderItem( order == $order, $value : value ),
                              init( double total = 0; ),
                              action( total += $value; ),
                              reverse( total -= $value; ),
                              result( total ) )
then
    # apply discount to $order
end
</pre><p>In the above example, for each Order() in the working memory, the
    engine will execute the <span class="bold"><strong>init code</strong></span>
    initializing the total variable to zero. Then it will iterate over all
    OrderItem() objects for that order, executing the <span class="bold"><strong>action</strong></span> for each one (in the example, it will sum
    the value of all items into the total variable). After iterating over all
    OrderItem, it will return the value corresponding to the <span class="bold"><strong>result expression</strong></span> (in the above example, the value
    of the total variable). Finally, the engine will try to match the result
    with the Number() pattern and if the double value is greater than 100, the
    rule will fire.</p><p>The example used java as the semantic dialect, and as such, note
    that the usage of ';' is mandatory in the init, action and reverse code
    blocks. The result is an expression and as such, it does not admit ';'. If
    the user uses any other dialect, he must comply to that dialect specific
    syntax.</p><p>As mentioned before, the <span class="bold"><strong>reverse
    code</strong></span> is optional, but it is strongly recommended that the user
    writes it in order to benefit from the <span class="emphasis"><em>improved performance on
    update and retracts</em></span>.</p><p>The <span class="bold"><strong>accumulate</strong></span> CE can be used to
    execute any action on source objects. The following example instantiates
    and populates a custom object:</p><pre class="programlisting">rule "Accumulate using custom objects"
when
    $person   : Person( $likes : likes )
    $cheesery : Cheesery( totalAmount &gt; 100 )
                from accumulate( $cheese : Cheese( type == $likes ),
                                 init( Cheesery cheesery = new Cheesery(); ),
                                 action( cheesery.addCheese( $cheese ); ),
                                 reverse( cheesery.removeCheese( $cheese ); ),
                                 result( cheesery ) );
then
    // do something
end</pre><div class="section" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="d0e2888"></a>3.6.3.1.&nbsp;Accumulate Functions</h4></div></div></div><p>The accumulate CE is a very powerful CE, but it gets real
      declarative and easy to use when using predefined functions that are
      known as Accumulate Functions. They work exactly like accumulate, but
      instead of explicitly writing custom code in every accumulate CE, the
      user can use predefined code for common operations.</p><p>For instance, the rule to apply discount on orders written in the
      previous section, could be written in the following way, using
      Accumulate Functions:</p><pre class="programlisting">rule "Apply 10% discount to orders over US$ 100,00"
when
    $order : Order()
    $total : Number( doubleValue &gt; 100 ) 
             from accumulate( OrderItem( order == $order, $value : value ),
                              sum( $value ) )
then
    # apply discount to $order
end
</pre><p>In the above example, sum is an AccumulateFunction and will sum
      the $value of all OrderItems and return the result.</p><p>Drools 4.0 ships with the following built in accumulate
      functions:</p><div class="itemizedlist"><ul type="disc"><li><p>average</p></li><li><p>min</p></li><li><p>max</p></li><li><p>count</p></li><li><p>sum</p></li></ul></div><p>These common functions accept any expression as input. For
      instance, if someone wants to calculate the average profit on all items
      of an order, a rule could be written using the average function:</p><pre class="programlisting">rule "Average profit"
when
    $order : Order()
    $profit : Number() 
              from accumulate( OrderItem( order == $order, $cost : cost, $price : price )
                               average( 1 - $cost / $price ) )
then
    # average profit for $order is $profit
end
</pre><p>Accumulate Functions are all pluggable. That means that if needed,
      custom, domain specific functions can easily be added to the engine and
      rules can start to use them without any restrictions. To implement a new
      Accumulate Functions all one needs to do is to create a java class that
      implements the org.drools.base.acumulators.AccumulateFunction interface
      and add a line to the configuration file or set a system property to let
      the engine know about the new function. As an example of an Accumulate
      Function implementation, the following is the implementation of the
      "average" function:</p><pre class="programlisting">/*
 * Copyright 2007 JBoss Inc
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Created on Jun 21, 2007
 */
package org.drools.base.accumulators;


/**
 * An implementation of an accumulator capable of calculating average values
 * 
 * @author etirelli
 *
 */
public class AverageAccumulateFunction implements AccumulateFunction {

    protected static class AverageData {
        public int    count = 0;
        public double total = 0;
    }

    /* (non-Javadoc)
     * @see org.drools.base.accumulators.AccumulateFunction#createContext()
     */
    public Object createContext() {
        return new AverageData();
    }

    /* (non-Javadoc)
     * @see org.drools.base.accumulators.AccumulateFunction#init(java.lang.Object)
     */
    public void init(Object context) throws Exception {
        AverageData data = (AverageData) context;
        data.count = 0;
        data.total = 0;
    }

    /* (non-Javadoc)
     * @see org.drools.base.accumulators.AccumulateFunction#accumulate(java.lang.Object, java.lang.Object)
     */
    public void accumulate(Object context,
                           Object value) {
        AverageData data = (AverageData) context;
        data.count++;
        data.total += ((Number) value).doubleValue();
    }

    /* (non-Javadoc)
     * @see org.drools.base.accumulators.AccumulateFunction#reverse(java.lang.Object, java.lang.Object)
     */
    public void reverse(Object context,
                        Object value) throws Exception {
        AverageData data = (AverageData) context;
        data.count--;
        data.total -= ((Number) value).doubleValue();
    }

    /* (non-Javadoc)
     * @see org.drools.base.accumulators.AccumulateFunction#getResult(java.lang.Object)
     */
    public Object getResult(Object context) throws Exception {
        AverageData data = (AverageData) context;
        return new Double( data.count == 0 ? 0 : data.total / data.count );
    }

    /* (non-Javadoc)
     * @see org.drools.base.accumulators.AccumulateFunction#supportsReverse()
     */
    public boolean supportsReverse() {
        return true;
    }

}
</pre><p>The code for the function is very simple, as we could expect, as
      all the "dirty" integration work is done by the engine. Finally, to plug
      the function into the engine, we added it to the configuration
      file:</p><pre class="programlisting">drools.accumulate.function.average = org.drools.base.accumulators.AverageAccumulateFunction
</pre><p>Where "drools.accumulate.function." is a prefix that must always
      be used, "average" is how the function will be used in the rule file,
      and "org.drools.base.accumulators.AverageAccumulateFunction" is the
      fully qualified name of the class that implements the function
      behavior.</p></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="d0e2931"></a>3.6.4.&nbsp;Forall</h3></div></div></div><p><span class="bold"><strong>Forall</strong></span> is the Conditional Element
    that completes the First Order Logic support in Drools. The syntax is very
    simple: </p><pre class="programlisting">forall( <em class="replaceable"><code>&lt;select pattern&gt;</code></em> <em class="replaceable"><code>&lt;constraint patterns&gt;</code></em> )</pre><p>The <span class="bold"><strong>forall</strong></span> Conditional Element will
    evaluate to true when all facts that match the <em class="replaceable"><code>&lt;select
    pattern&gt;</code></em> match all the <em class="replaceable"><code>&lt;constraint
    patterns&gt;</code></em>. Example:</p><pre class="programlisting">rule "All english buses are red"
when
    forall( $bus : Bus( type == 'english') 
                   Bus( this == $bus, color = 'red' ) )
then
    # all english buses are red
end
</pre><p>In the above rule, we "select" all Bus object whose type is
    "english". Then, for each fact that matchs this pattern we evaluate the
    following patterns and if they match, the forall CE will evaluate to true.
    Another example:</p><pre class="programlisting">rule "all employees have health and dental care programs"
when
    forall( $emp : Employee()
            HealthCare( employee == $emp )
            DentalCare( employee == $emp )
          )
then
    # all employees have health and dental care
end
</pre><p>Forall can be nested inside other CEs for complete expressiveness.
    For instance, <span class="bold"><strong>forall</strong></span> can be used inside a
    <span class="bold"><strong>not</strong></span> CE:</p><pre class="programlisting">rule "not all employees have health and dental care"
when 
    not forall( $emp : Employee()
                HealthCare( employee == $emp )
                DentalCare( employee == $emp )
              )
then
    # not all employees have health and dental care
end
</pre><p>As a side note, forall Conditional Element is equivalent to
    writing:</p><pre class="programlisting">not( <em class="replaceable"><code>&lt;select pattern&gt;</code></em> and not ( and <em class="replaceable"><code>&lt;constraint patterns&gt;</code></em> ) )</pre><p>Also, it is important to note that <span class="bold"><strong>forall is a
    scope delimiter</strong></span>, so it can use any previously bound variable,
    but no variable bound inside it will be available to use outside of
    it.</p></div></div><div xmlns="" class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ch03s05.html">Prev</a>&nbsp;</td><td width="20%" align="center"><a accesskey="u" href="ch03.html">Up</a></td><td width="40%" align="right">&nbsp;<a accesskey="n" href="ch03s07.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">3.5.&nbsp;Rule&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="title.html">Home</a>&nbsp;|&nbsp;<a accesskey="t" href="bk01-toc.html">ToC</a></td><td width="40%" align="right" valign="top">&nbsp;3.7.&nbsp;Query</td></tr></table></div></body></html>