5.5.2. Left Hand Side (when) Conditional Elements
The Left Hand Side (LHS) is a common name for the conditional part of the rule. It consists of zero or more Conditional Elements. If the LHS is left empty it is re-written as eval(true), which means the rule is always true, and will be activated with a new Working Memory session is created.

rule "no CEs"
when
then
<action>*
end
Is internally re-written as:
rule "no CEs"
when
eval( true )
then
<action>*
end
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 one fact - which fact would the declaration bind to?
The Pattern element is the most important Conditional Element. The entity relationship diagram below provides an overview of the various parts that make up the Pattern's constraints and how they work together; each is then covered in more detail with rail road diagrams and examples.

At the top of the ER diagram you can see that the pattern consists of zero or more constraints and has an optional pattern binding. The rail road diagram below shows the syntax for this.

At the simplest, with no constraints, it simply matches against a type, in the following case the type is "Cheese". This means the pattern will match against all Cheese objects in the Working Memory.
Cheese( )
To be able to refer to the matched object use a pattern binding variable such as '$c'. While this example variable is prefixed with a $ symbol, it is optional, but can be useful in complex rules as it helps to more easily differentiation between variables and fields.
$c : Cheese( )
Inside of the Pattern parenthesis is where all the action happens. A constraint can be either a Field Constraint, Inline Eval (called a predicate in 3.0) or a Constraint Group. Constraints can be separated by the following symbols ',', '&&' or '||'.



The ',' (comma) character is used to separate constraint groups. It has an implicit 'and' connective semantics.
# Cheese type is stilton and price < 10 and age is mature. Cheese( type == "stilton", price < 10, age == "mature" )
group 1: type is stilton -> type == "stilton"
group 2: price is less than 10 -> price < 10
group 3: age is mature -> age == "mature"
The '&&' (and) and '||' (or) constraint connectives allow constraint groups to have multiple constraints. Example:
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
The above example has two constraint groups. The first has 2 constraints and the second has one constraint.
The connectives are evaluated in the following order, from first to last:
&&
||
,
It is possible to change the evaluation priority by using parenthesis, as in any logic or mathematical expression. Example:
# Cheese type is stilton and ( price is less than 20 or age is mature ). Cheese( type == "stilton" && ( price < 20 || age == "mature" ) )
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.
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
A Field constraint specifies a restriction to be used on a field name; the field name can have an optional variable binding.

There are three types of restrictions; Single Value Restriction, Compound Value Restriction and Multi Restriction.

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") - we use the standard jdk Introspector class to do this mapping.
For example, referring to our Cheese class, the following : Cheese(type == ...) uses the getType() method on the a cheese instance. If a field name cannot be found it will resort to calling the name as a no argument method; "toString()" on the Object for instance can be used with Cheese(toString == ..) - you use the full name of the method with correct capitalization, 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 in between invocations to make it faster).
The field constraints can take a number of values; including literal, qualifiedIdentifier (enum), variable and returnValue.




You can do checks against fields that are or maybe null, using == and != as you would expect, and the literal "null" keyword, like: Cheese(type != null). If a field is null the evaluator will not throw an exception and will only return true if the value is a null check. Coercion is always attempted if the field and the value are of different types; exceptions will be thrown if bad coercions are attempted. i.e. if "ten" is provided as a string in a number evaluator, where as "10" would coerce to a numeric 10. Coercion is always in favor of the field type and not the value type.


Valid operators are dependent on the field type. Generally they are self explanatory based on the type of data: for instance, for date fields, "<" means "before" and so on. "Matches" is only applicable to string fields, "contains" and "not contains" is only applicable to Collection type fields. These operators can be used with any value and coercion to the correct value for the evaluator and filed will be attempted, as mention in the "Values" section.
Matches a field against any valid Java Regular Expression. Typically that regexp is a String, but variables that resolve to a valid regexp are also allowed. It is important to note that different from java, if you write a String regexp directly on the source file, you don't need to escape '\'. Example:
Cheese( type matches "(Buffalo)?\S*Mozerella" )
Any valid Java 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.It is important to note that different from java, if you write a String regexp directly on the source file, you don't need to escape '\'. Example:
Cheese( type not matches "(Buffulo)?\S*Mozerella" )
'contains' is used to check if a field's
Collection or array contains the specified value.
CheeseCounter( cheeses contains "stilton" ) // contains with a String literal CheeseCounter( cheeses contains $var ) // contains with a variable
'not contains' is used to check if a field's
Collection or array does not contains an object.
CheeseCounter( cheeses not contains "cheddar" ) // not contains with a String literal CheeseCounter( cheeses not contains $var ) // not contains with a variable
NOTE: for backward compatibility, the 'excludes' operator is supported as a synonym for 'not contains'.
'memberOf' is used to check if a field is a member of a collection or array; that collection must be be a variable.
CheeseCounter( cheese memberOf $matureCheeses )
'not memberOf' is used to check if a field is not a member of a collection or array; that collection must be be a variable.
CheeseCounter( cheese not memberOf $matureCheeses )
Similar to 'matches', but checks if a word has almost the same sound as the given value. Uses the 'Soundex' algorithm (http://en.wikipedia.org/wiki/Soundex)
Cheese( name soundslike 'foobar' )
This will match a cheese with a name of "fubar"
Literal restrictions are the simplest form of restrictions and evaluate a field against a specified literal; numeric, date, string or boolean.

Literal Restrictions using the '==' operator, provide for faster execution as we can index using hashing to improve performance;
All standard java numeric primitives are supported.
Cheese( quantity == 5 )
The date format "dd-mmm-yyyy" is supported by default. You can customize 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 inline-eval constraint.
Cheese( bestBefore < "27-Oct-2007" )
Any valid Java String is allowed.
Cheese( type == "stilton" )
only true or false can be used. 0 and 1 are not recognized, nor is Cheese ( smelly ) is allowed
Cheese( smelly == true )
Enums can be used as well, both jdk1.4 and jdk5 style enums are supported - for the later you must be executing on a jdk5 environment.
Cheese( smelly == SomeClass.TRUE )

Variables can be bound to Facts and their Fields and then used in subsequent Field Constraints. A bound variable is called a Declaration. Valid operators are determined by the type of the field being constrained; coercion will be attempted where possible. Bound Variable Restrictions using '==' operator, provide for very fast execution as we can index using hashing to improve performance.
Person( likes : favouriteCheese ) Cheese( type == likes )
'likes' is our variable, our Declaration, that is bound to the favouriteCheese field for any matching Person instance and is used to constrain the type of Cheese in the following Pattern. Any valid java variable name can be used, including '$'; which you will often see used to help differentiate declarations from fields. The example below shows a declaration bound to the Patterns Object Type instance itself and used with a 'contains' operator, note the optional use of '$' this time.
$stilton : Cheese( type == "stilton" ) Cheesery( cheeses contains $stilton )

A Return Value restriction can use any valid Java primitive or object. Avoid using any Drools keywords as Declaration identifiers. Functions used in a Return Value Restriction must return time constant results. Previously bound declarations can be used in the expression.
Person( girlAge : age, sex == "F" ) Person( age == ( girlAge + 2) ), sex == 'M' )
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 separated 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 rewritten as a multi restriction list of != and == restrictions.

Person( $cheese : favouriteCheese ) Cheese( type in ( "stilton", "cheddar", $cheese )
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.


Person( age > 30 && < 40 ) // simple multi restriction using a single && 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

A inline-eval constraint can use any valid dialect 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 created as a variable of the same name; this is autovivification of field variables inside of inline evals.
This example will find all pairs of male/femal people where the male is 2 years older than the female; the boyAge variable is auto created as part of the autovivification process.
Person( girlAge : age, sex = "F" ) Person( eval( girlAge == boyAge + 2 ), sex = 'M' )
Drools does allow for nested accessors in in the field constraints using the MVEL accessor graph notation. Field constraints involving nested accessors are actually re-written as an MVEL dialect inline-eval. Care should be taken when using nested accessors as the Working Memory is not aware of any of the nested values, and do not know when they change; they should be considered immutable while any 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, when in the MVEL dialect, you can use the 'modify' keyword and its block setters to write the nested accessor assignments while retracting and inserting the the root parent object as required. Nested accessors can be used either side of the operator symbol.
$p : Person( ) Pet( owner == $p, age > $p.children[0].age ) // Find a pet who is older than their owners first born child
is internally rewriten as an MVEL inline eval:
$p : Person( ) Pet( owner == $p, eval( age > $p.children[0].age ) ) // Find a pet who is older than their owners first born child