[jboss-svn-commits] JBL Code SVN: r13727 - labs/jbossrules/trunk/documentation/manual/en/Chapter-Rule_Language.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Mon Jul 23 10:49:39 EDT 2007
Author: tirelli
Date: 2007-07-23 10:49:39 -0400 (Mon, 23 Jul 2007)
New Revision: 13727
Modified:
labs/jbossrules/trunk/documentation/manual/en/Chapter-Rule_Language/Section-Rule.xml
Log:
Updating rule section docs
Modified: labs/jbossrules/trunk/documentation/manual/en/Chapter-Rule_Language/Section-Rule.xml
===================================================================
--- labs/jbossrules/trunk/documentation/manual/en/Chapter-Rule_Language/Section-Rule.xml 2007-07-23 14:47:35 UTC (rev 13726)
+++ labs/jbossrules/trunk/documentation/manual/en/Chapter-Rule_Language/Section-Rule.xml 2007-07-23 14:49:39 UTC (rev 13727)
@@ -167,6 +167,8 @@
<para>type : String</para>
+ <para>possible values: "java" or "mvel"</para>
+
<para>The dialect species the language to be used for any code
expressions in the LHS or the RHS code block. Currently two dialects are
available, Java and MVEL. While the dialect can be specified at the
@@ -260,9 +262,9 @@
end</programlisting>
</example>
- <para>Conditional elements work on one or more Columns (which were
- described above). The most common one is "and" which is implicit when you
- have multiple Columns in the LHS of a rule that are not connected in
+ <para>Conditional elements work on one or more Patterns (which are
+ described bellow). The most common one is "and" which is implicit when you
+ have multiple Patterns in the LHS of a rule that are not connected in
anyway. Note that an 'and' cannot have a leading declaration binding like
'or' - this is obvious when you think about it. A declaration can only
reference a single Fact, when the 'and' is satisfied it matches more than
@@ -294,7 +296,7 @@
</figure>
<para>At the top of the ER diagram you can see that the pattern consists
- of zero or more constriants and has an optional pattern binding. The
+ of zero or more constraints and has an optional pattern binding. The
rail road diagram below shows the syntax for this.</para>
<figure>
@@ -387,35 +389,80 @@
</mediaobject>
</figure>
- <para>',' and '&&' when used without '||' are equivalent;. ','
- is provided as a less verbose '&&' connective for more simple
- field constraints.</para>
+ <para>The ',' (comma) character is used to separate constraint groups.
+ It has an implicit 'and' connective semantics.<example>
+ <title>Constraint Group connective ','</title>
- <example>
- <title>Equivalent connectives</title>
+ <programlisting># Cheese type is stilton and price < 10 and age is mature.
+Cheese( type == "stilton", price < 10, age == "mature" )</programlisting>
+ </example>The above example has 3 constraint groups, each with a
+ single constraint:</para>
- <programlisting>Cheese( type == "stilton", price < 10 ) // valid
-Cheese( type == "stilton" && price < 10 ) valid</programlisting>
- </example>
+ <itemizedlist>
+ <listitem>
+ <para>group 1: type is stilton -> type == "stilton"</para>
+ </listitem>
- <para>However only '&&' can be used with '||'.</para>
+ <listitem>
+ <para>group 2: price is less than 10 -> price < 10</para>
+ </listitem>
+ <listitem>
+ <para>group 3: age is mature -> age == "mature"</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>The '&&' (and) and '||' (or) constraint connectives allow
+ constraint groups to have multiple constraints. Example:</para>
+
<example>
- <title>Not Equivalent connectives</title>
+ <title>&& and || Constraint Connectives</title>
- <programlisting>Cheese( type == "stilton", price < 10 || age == "mature" ) // invalid
-Cheese( type == "stilton" && price < 10 || age == "mature") // valid</programlisting>
+ <programlisting>Cheese( type == "stilton" && price < 10, age == "mature" ) // Cheese type is "stilton" and price < 10, and age is mature
+Cheese( type == "stilton" || price < 10, age == "mature" ) // Cheese type is "stilton" or price < 10, and age is mature</programlisting>
</example>
- <para>Constraints can be grouped using parenthesis; notice from the
- railroad and the ER diagram that this provides a recursive nature to the
- use of constraints in a Pattern.</para>
+ <para>The above example has two constraint groups. The first has 2
+ constraints and the second has one constraint.</para>
+ <para>The connectives are evaluated in the following order, from first
+ to last:</para>
+
+ <orderedlist>
+ <listitem>
+ <para>&&</para>
+ </listitem>
+
+ <listitem>
+ <para>||</para>
+ </listitem>
+
+ <listitem>
+ <para>,</para>
+ </listitem>
+ </orderedlist>
+
+ <para>It is possible to change the evaluation priority by using
+ parenthesis, as in any logic or mathematical expression. Example:</para>
+
+ <para><example>
+ <title>Using parenthesis to change evaluation priority</title>
+
+ <programlisting># Cheese type is stilton and ( price is less than 20 or age is mature ).
+Cheese( type == "stilton" && ( price < 20 || age == "mature" ) ) </programlisting>
+ </example>In the above example, the use of parenthesis makes the ||
+ connective be evaluated before the && connective.</para>
+
+ <para>Also, it is important to note that besides having the same
+ semantics, the connectives '&&' and ',' are resolved with
+ different priorities and ',' cannot be embedded in a composite
+ constraint expression. </para>
+
<example>
- <title>Grouping with Parenthesis</title>
+ <title>Not Equivalent connectives</title>
- <programlisting>Cheese( type == "stilton", ( price < 10 || age == "mature" ) ) // valid
-Cheese( type == "stilton" && ( price < 10 || age == "mature" ) ) // valid</programlisting>
+ <programlisting>Cheese( ( type == "stilton", price < 10 ) || age == "mature" ) // invalid as ',' cannot be embedded in an expression
+Cheese( ( type == "stilton" && price < 10 ) || age == "mature") // valid as '&&' can be embedded in an expression</programlisting>
</example>
<section>
@@ -441,7 +488,7 @@
</figure>
<para>There are three types of restrictions; Single Value Restriction,
- Compount Value Restriction and Multi Restrictoin.</para>
+ Compound Value Restriction and Multi Restriction.</para>
<figure>
<title>restriction</title>
@@ -459,23 +506,6 @@
</mediaobject>
</figure>
- <para>A field is an accessible method on the object. If your model
- objects follow the java bean pattern, then fields are exposed using
- "getXXX" or "isXXX" methods (these are methods that take no arguments,
- and return something). You can access fields either by using the
- bean-name convention (so "getType" can be accessed as "type").</para>
-
- <para>For example, refering to our Cheese class, the following :
- Cheese(type == ...) uses the getType() method on the a cheese
- instance. You can also access non getter methods, like "toString()" on
- the Object for instance (in which case, you do Cheese(toString == ..)
- - you use the full name of the method with correct capitalisation, but
- not brackets). Do please make sure that you are accessing methods that
- take no parameters, and are in-fact "accessors" (as in, they don't
- change the state of the object in a way that may effect the rules -
- remember that the rule engine effectively caches the results of its
- matching inbetween invocations to make it faster).</para>
-
<section>
<title>JavaBeans as facts</title>
@@ -634,12 +664,15 @@
<primary>regular expression</primary>
</indexterm>Regular Expression. Typically that regexp is a
String, but variables that resolve to a valid regexp are also
- allowed.</para>
+ allowed. It is important to note that <emphasis>different from
+ java</emphasis>, if you write a String regexp directly on the
+ source file, <emphasis>you don't need to escape '\'</emphasis>.
+ Example:</para>
<example>
<title>Regular Expression Constraint</title>
- <programlisting>Cheese( type matches "(Buffulo)?\\S*Mozerella" )</programlisting>
+ <programlisting>Cheese( type matches "(Buffalo)?\S*Mozerella" )</programlisting>
</example>
</simplesect>
@@ -651,12 +684,15 @@
</indexterm>Regular Expression can be used to match String
fields. Returns true when the match is false. Typically that
regexp is a String, but variables that resolve to a valid regexp
- are also allowed.</para>
+ are also allowed.It is important to note that
+ <emphasis>different from java</emphasis>, if you write a String
+ regexp directly on the source file, <emphasis>you don't need to
+ escape '\'</emphasis>. Example:</para>
<example>
<title>Regular Expression Constraint</title>
- <programlisting>Cheese( type not matches "(Buffulo)?\\S*Mozerella" )</programlisting>
+ <programlisting>Cheese( type not matches "(Buffulo)?\S*Mozerella" )</programlisting>
</example>
</simplesect>
@@ -666,13 +702,14 @@
<para><literal>'contains'</literal> is used to check if a
field's <indexterm>
<primary>Collection</primary>
- </indexterm>Collection contains the specified value.</para>
+ </indexterm>Collection or array contains the specified
+ value.</para>
<example>
<title>Contains with Collections</title>
- <programlisting>CheeseCounter( cheeses contains "stilton" ) //contains with a String literal
-CheeseCounter( cheeses contains $var ) //contains with a variable</programlisting>
+ <programlisting>CheeseCounter( cheeses contains "stilton" ) // contains with a String literal
+CheeseCounter( cheeses contains $var ) // contains with a variable</programlisting>
</example>
</simplesect>
@@ -682,13 +719,22 @@
<para><literal>'not contains'</literal> is used to check if a
field's <indexterm>
<primary>Collection</primary>
- </indexterm>Collection does not contains an object.</para>
+ </indexterm>Collection or array does not contains an
+ object.</para>
<example>
<title>Literal Constraints with Collections</title>
- <programlisting>CheeseCounter( cheeses not contains "cheddar" ) //contains with a String literal
-CheeseCounter( cheeses not contains $var ) //contains with a variable</programlisting>
+ <programlisting>CheeseCounter( cheeses not contains "cheddar" ) // not contains with a String literal
+CheeseCounter( cheeses not contains $var ) // not contains with a variable</programlisting>
+
+ <blockquote>
+ <para><emphasis role="bold">NOTE: </emphasis>for backward
+ compatibility, the '<emphasis
+ role="bold">excludes</emphasis>' operator is supported as a
+ synonym for '<emphasis role="bold">not
+ contains</emphasis>'.</para>
+ </blockquote>
</example>
</simplesect>
@@ -696,7 +742,7 @@
<title>memberof</title>
<para><literal>'memberof' is used to check if a field is a
- member of a collection; that collection must be be a
+ member of a collection or array; that collection must be be a
variable.</literal></para>
<example>
@@ -710,7 +756,7 @@
<title>not memberof</title>
<para><literal>'not memberof' is used to check if a field is not
- a member of a collection; that collection must be be a
+ a member of a collection or array; that collection must be be a
variable.</literal></para>
<example>
@@ -724,9 +770,9 @@
<section>
<title>Literal Restrictions</title>
- <para>Literal restrrictions are the simplest for of restrictions
+ <para>Literal restrictions are the simplest form of restrictions
and evaluate a field against a specified literal; numeric, date,
- string and boolean.</para>
+ string or boolean.</para>
<figure>
<title>literalRestriction</title>
@@ -766,7 +812,7 @@
<para>The date format "dd-mmm-yyyy" is supported by default. You
can customise this by providing an alternative date format mask
as a System property ("drools.dateformat" is the name of the
- property). If more control is required, use the predicate
+ property). If more control is required, use the inline-eval
constraint.</para>
<example>
@@ -792,7 +838,7 @@
<title>Boolean</title>
<para>only true or false can be used. 0 and 1 are not
- recognised, nor is <literal>Cheese ( smelly )</literal> is not
+ recognised, nor is <literal>Cheese ( smelly )</literal> is
allowed</para>
<example>
@@ -894,12 +940,10 @@
<primary>Return Value</primary>
</indexterm>Return Value restrriction can use any valid Java
primitive or object. Avoid using any Drools keywords as
- Declaration identifiers. Functions used in a Return v</para>
+ Declaration identifiers. Functions used in a Return Value
+ Restriction must return time constant results. Previously bound
+ declarations can be used in the expression.</para>
- <para>Value Restriction must return time constant results.
- Previously bound declarations can be used in the
- expression.</para>
-
<example>
<title>Return Value Restriction</title>
@@ -916,7 +960,7 @@
<para>The compound value restriction is used where there is more
than one possible value, currently only the 'in' and 'not in'
evaluators support this. The operator takes a parenthesis enclosed
- comma seperated list of values, which can be a variable, literla,
+ comma seperated list of values, which can be a variable, literal,
return value or qualified identifier.The 'in' and 'not in'
evaluators are actually sugar and are rewriten as a multi
restriction list of != and == restrictions.</para>
@@ -953,10 +997,10 @@
<section>
<title>Multi Restriction</title>
- <para>Multi restriction allows you to place more than restriction on
- a field using the '&&' or '||' restriction connectives,
- grouping via parenthesis is also allowed; which adds a recursive
- nature to this restriction.</para>
+ <para>Multi restriction allows you to place more than one
+ restriction on a field using the '&&' or '||' restriction
+ connectives. Grouping via parenthesis is also allowed; which adds a
+ recursive nature to this restriction.</para>
<figure>
<title>multiRestriction</title>
@@ -996,7 +1040,7 @@
<title>Multi Restriction</title>
<programlisting>Person( age > 30 && < 40 ) // simple multi restriction using a single &&
-Person( age ( (> 30 && < 40) || (> 20 && < 20) ) ) // more complex multi restriction using groupings of multi restrictions
+Person( age ( (> 30 && < 40) || (> 20 && < 25) ) ) // more complex multi restriction using groupings of multi restrictions
Person( age > 30 && < 40 || location == "london" ) // mixing muti restrictions with constraint connectives</programlisting>
</example>
</section>
@@ -1024,18 +1068,18 @@
<para>A <indexterm>
<primary>Predicate</primary>
</indexterm>inline-eval constraint can use any valid dialect
- expression as long as it evaluated to a primitive boolean - avoid
+ expression as long as it is evaluated to a primitive boolean - avoid
using any Drools keywords as Declaration identifiers. the expression
must be time constant. Any previous bound variable, from the current
or previous pattern, can be used; autovivification is also used to
auto create field binding variables. When an identifier is found that
is not a current variable the builder looks to see if the identifier
- is a field on the current object type, if it is the field is auto
+ is a field on the current object type, if it is, the field is auto
created as a variable of the same name; this is autovivification of
field varables inside of inline evals.</para>
<para>This example will find all pairs of male/femal people where the
- male is 2 years older than the female; the girlAge variable is auto
+ male is 2 years older than the female; the boyAge variable is auto
created as part of the autovivification process.</para>
<example>
@@ -1059,7 +1103,7 @@
of their parent references are inserted into the Working Memory. If
you wish to modify a nested value you should remove he parent objects
first and re-assert afterwards. If you only have a single parent at
- the root of the graph you, when in the MVEL dialect, you can use the
+ the root of the graph, when in the MVEL dialect, you can use the
'modify' keyword and its block setters to write the nested accessor
assingments while retracting and inserting the the root parent object
as required. Nested accessors can be used either side of the operator
@@ -1076,6 +1120,9 @@
<programlisting>$p : Person( )
Pet( owner == $p, eval( age > $p.children[0].age ) ) // Find a pet who is older than their owners first born child</programlisting>
</example>
+
+ <remark>NOTE: nested accessors have a much greater performance cost
+ than direct field access, so use them carefully.</remark>
</section>
</section>
@@ -1235,8 +1282,8 @@
pensioner : Person( sex == "m", age > 65 ) )</programlisting>
</example>
- <para>The 'or' conditional element results in multipe rule generation,
- called sub rules, for each possible logically outcome. the example above
+ <para>The 'or' conditional element results in multiple rule generation,
+ called sub rules, for each possible logically outcome. The example above
would result in the internal generation of two rules. These two rules
work independently within the Working Memory, which means both can
match, activate and fire - there is no shortcutting.</para>
@@ -1265,20 +1312,20 @@
</figure>
<para>Eval is essentially a catch all which allows any semantic code
- (that returns a primitive primitive boolean) to be executed. This can
- refer to variables that were bound in the LHS of the rule, and functions
- in the rule package. Over use of eval reduces the declarativess of your
- rules and can result in a poor performing engine. While 'evals' can be
- used anywhere in the Pattern the best practice is to add it as the last
- conditional element in the LHS of a rule. </para>
+ (that returns a primitive boolean) to be executed. This can refer to
+ variables that were bound in the LHS of the rule, and functions in the
+ rule package. Over use of eval reduces the declarativess of your rules
+ and can result in a poor performing engine. While 'evals' can be used
+ anywhere in the Pattern the best practice is to add it as the last
+ conditional element in the LHS of a rule.</para>
<para>Evals cannot be indexed and thus are not as optimal as using Field
Constraints. However this makes them ideal for being used when functions
return values that change over time, which is not allowed within Field
- Constraints. </para>
+ Constraints.</para>
<para>For folks who are familiar with Drools 2.x lineage, the old Drools
- paramater and condition tags are equivalent to binding a variable to an
+ parameter and condition tags are equivalent to binding a variable to an
appropriate type, and then using it in an eval node.</para>
<example>
@@ -1308,8 +1355,8 @@
</mediaobject>
</figure>
- <para>'not' is first order logic's Existential Quantifier and checks for
- the non existence of something in the Working Memory. Brackets are
+ <para>'not' is first order logic's Non-Existential Quantifier and checks
+ for the non existence of something in the Working Memory. Brackets are
optional. Think of 'not' as meaning "there must be none of...".</para>
<example>
@@ -1363,7 +1410,7 @@
<programlisting>exists Bus(color == "red")
exists ( Bus(color == "red", number == 42) ) //brackets are optional
-exists ( Bus(color == "red") and Bus(color == "blue")) // not with nested 'and' infix used here as ony two patterns</programlisting>
+exists ( Bus(color == "red") and Bus(color == "blue")) // exists with nested 'and' infix used here as ony two patterns</programlisting>
</example>
</section>
@@ -1384,16 +1431,11 @@
</mediaobject>
</figure>
- <para><emphasis role="bold">Forall</emphasis> is the Conditional Element
- that completes the First Order Logic support in Drools. The syntax is
- very simple:</para>
-
- <programlisting>forall( <replaceable><select pattern></replaceable> <replaceable><constraint patterns></replaceable> )</programlisting>
-
<para>The <emphasis role="bold">forall</emphasis> Conditional Element
- will evaluate to true when all facts that match the
- <replaceable><select pattern></replaceable> match all the
- <replaceable><constraint patterns></replaceable>. Example:</para>
+ completes the First Order Logic support in Drools. The <emphasis
+ role="bold">forall</emphasis> Conditional Element will evaluate to true
+ when all facts that match the first pattern match all the remaining
+ patterns. Example:</para>
<programlisting>rule "All english buses are red"
when
@@ -1407,10 +1449,29 @@
<para>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:</para>
+ true. </para>
- <programlisting>rule "all employees have health and dental care programs"
+ <para>To state that all facts of a given type in the working memory must
+ match a set of constraints, forall can be written with a single pattern
+ for simplicity. Example</para>
+
+ <para><example>
+ <title>Single Pattern Forall</title>
+
+ <programlisting>rule "All Buses are Red"
when
+ forall( Bus( color == 'red' ) )
+then
+ # all asserted Bus facts are red
+end
+</programlisting>
+ </example> The above is exactly the same as writing:</para>
+
+ <para>Another example of multi-pattern forall:<example>
+ <title>Multi-Pattern Forall</title>
+
+ <programlisting>rule "all employees have health and dental care programs"
+when
forall( $emp : Employee()
HealthCare( employee == $emp )
DentalCare( employee == $emp )
@@ -1419,12 +1480,14 @@
# all employees have health and dental care
end
</programlisting>
+ </example></para>
<para>Forall can be nested inside other CEs for complete expressiveness.
For instance, <emphasis role="bold">forall</emphasis> can be used inside
- a <emphasis role="bold">not</emphasis> CE:</para>
+ a <emphasis role="bold">not</emphasis> CE:<example>
+ <title>Combining Forall with Not CE</title>
- <programlisting>rule "not all employees have health and dental care"
+ <programlisting>rule "not all employees have health and dental care"
when
not forall( $emp : Employee()
HealthCare( employee == $emp )
@@ -1434,11 +1497,12 @@
# not all employees have health and dental care
end
</programlisting>
+ </example></para>
<para>As a side note, forall Conditional Element is equivalent to
writing:</para>
- <programlisting>not( <replaceable><select pattern></replaceable> and not ( and <replaceable><constraint patterns></replaceable> ) )</programlisting>
+ <programlisting>not( <replaceable><first pattern></replaceable> and not ( and <replaceable><remaining patterns></replaceable> ) )</programlisting>
<para>Also, it is important to note that <emphasis role="bold">forall is
a scope delimiter</emphasis>, so it can use any previously bound
More information about the jboss-svn-commits
mailing list