Drools provides a set of operations that you can use to compare different objects against each other. These objects might be living directly on the working memory, global variables, literal values, or any combination of these types. We’re going to enumerate the most used ones in the following sections, splitting them into the following:
- Boolean and numeric operations
- Regex operations
- Collection-based operations
Boolean and numeric operations
We’ve seen some examples of these operations in our previous rules as they are the simplest to understand for anyone with programming experience. Boolean operations are the ones that use
XOR, and so on. Numeric operations are the ones that compare two numeric values. Here’s an example of some of these operations against an attribute of the Item type:
Item( salePrice > 100.00 && salePrice <= 500.00&& salePrice != 101.00 )
In the previous example of a condition, we checked whether the
salePrice attribute of our Item object has a value greater than
100, lesser or equal to
500, and different from
101, in that order.
Some of these operations are intrinsic to Drools, such as the use of the
AND operation. Using the
&& method is not necessary in the conditions of the previous example as any comparison that is separated by a comma is considered a new condition that must be checked as well. However, boolean conditions are required to express the situations where either one of the two conditions needs to be true (that is, an OR boolean expression).
Using boolean expressions is possible, but if required, they will usually mark places where the design of our rules needs revision. This is because the AND expressions are intrinsic to the language and rules that use OR expressions should be considered as more than one condition in the same rule (and therefore, non-atomic). Whenever an OR expression is required to express a rule, consider splitting the rule into two different rules, as shown in the following example:
rule "Add 5% discount for minors or seniors" when $o: Order(customer.age < 18 || customer.age > 60) then $o.increaseDiscount(0.05); end
This could be broken into this two rules:
rule "Add 5% discount for minors" when $o: Order(customer.age < 18) then $o.increaseDiscount(0.05); end rule "Add 5% discount for seniors" when $o: Order(customer.age > 60) then $o.increaseDiscount(0.05); end
It might seem that boolean expressions are something to avoid as much as possible, however, we will see some other uses that they have when combining other operations later in this chapter. For the moment, let’s just remember that they exist and try to use them only if really needed.
Regex operations – matches
Matches is an operator that we can use against string-based objects and attributes. It allows us to check whether they follow a specific regular expression. Most common uses of them are to check whether a string represents a valid number, e-mail, or any special character order that we need to validate. Regular expressions are a very complex topic to cover here and you can learn more about them online. We will see a small example of how matches are used in a rule condition by creating a rule to check whether customers have a valid e-mail address, as follows:
rule "validate customer emails" when $c: Customer(email not matches "[A-Za-z0-9-.]+@[A-Za-z0-9-.]+$") then $c.setEmail(null); //invalidate email end
The previous rule has a simplified regular expression to validate e-mails. Any Java regular expression could be used with the matches and not matches operators and they can both work with variables and literal values. This means that the regular expression could be a global variable defined somewhere else.
Collection operations – contains and memberOf
The collection operations are the ones prepared to work with one or more collections, whether they are variables, attributes, or literal values. They are used to determine whether a collection has an element in them. An example of using these operations would be something similar to the following:
rule "print orders with pencils in them" when $i: Item(name == "pencil") $ol: OrderLine(item == $i) $o: Order($ol memberOf orderLines, orderLines contains $ol) then System.out.println("order with pencils: " + $o); end
In the previous rule, we’re using both operations one after the other. They are both checking for the same condition, whether the found order line is in the orderLines collection of the order object.