8.8 Guarded Patterns
We can rarely write a pattern without wanting to restrict the parameters of the events. As we saw in STRAW-EPL context tests, in Chapter 6, we might want to deliver messages according to the data they contain or whether the sender passes a credit check. We can do this with a feature of Rapide-EPL called guards.
A guarded pattern has this syntax:
pattern where Boolean test
The guard is a Boolean valued test following where. Its meaning is that it restricts the matches of the pattern to those matches for which the Boolean test is true. We often call the guard in a pattern the where clause.
8.8.1 Content-Based Pattern Matching
Guards can refer to data in events (the content of the events). This is called content-based matching.
Example 1: Testing the content of messages
(Dollars ?LatestPrice, ?LastQuote) StockQuote(IBM, ?LatestPrice, ?LastQuote) where ?LatestPrice >?LastQuote + $5;
This pattern will match stock quotes for IBM stock only if the latest price is $5 more than the last quote. The guard uses the content of the StockQuote event to make the test. Typically, these kinds of tests are used in content-driven message delivery.
Example 2: Good banking behavior
(Dollars ?X , ?Y; Account ?A) (Deposit(?X, ?A) Withdraw(?Y, ?A)) where ?Y <?X ;
The pattern, Deposit(?X, ?A) Withdraw(?Y, ?A), will match any pair of causally related Deposit and Withdraw events on the same account. The guard restricts the matches to those pairs for which the amount withdrawn is less than the amount deposited.
When the pattern matches, the placeholders ?X, ?Y are bound to the data values for the amounts of the deposit and the withdrawal. Those values are then used to evaluate the guard. If its value is true, the guarded pattern matches.
8.8.2 Context-Based Pattern Matching
Guards can also refer to information outside the events, such as database queries or values returned by method calls (that is, the context in which the pattern matching happens).
Example 1: Context-based message filtering
(OrderId ?Id, CustId ?C, AccntNo ?A) Order(?Id, ?C, ?A) where CreditCheck(?C) = Pass and Active(?A);
This pattern matches Orders from customers if they pass a credit check and their accounts are active. Both of these tests in the guard refer to the context in which the Order is receivedthe status of the customer's credit and the status of their account at that time.
The Boolean test in the guard may refer to the values of placeholders in the pattern and objects from the context in which the pattern is matched. Matching a guarded pattern proceeds in two steps. The first step is to match the unguarded pattern; if there is a match, all the placeholders in the guard must be bound to values by the match. Then the guarded pattern matches if the guard is true when those values are substituted for the placeholders. The guard is evaluated after the unguarded pattern matches. An error results if there is an unmatched placeholder in a guard when it is evaluatedexcept in some special circumstances, which we mention later.
Context-based pattern matching is more di0cult to implement e0-ciently to allow high throughput of events than content-based matching. Context references in guards make it more di0cult to organize large numbers of patterns for sublinear searches for matches. Details are beyond the scope of our discussion here.
8.8.3 Temporal Operators
Rapide-EPL provides some operators that simplify writing guards that refer to the timestamps and start and end times of events. They are called temporal operators.
at: Applies only to basic event patterns. For example, if P is a basic event pattern, P at 3:00pm matches an event E if E matches P and its timestamp is 3:00pm. An unbound variable can be a parameter of the at operator. If T is a variable of type Time, P at T matches an event E that matches P, and a result of the match is to bind T to the timestamp value of E.
after: Applies to complex patterns. For example, P after T matches posets that match P and contain events all of whose start times or timestamps are greater than T.
during: Applies to complex patterns. For example, P during(T1, T2) matches posets that match P and contain events all of whose start times or timestamps are greater than T1, and all of whose end times or timestamps are less than T2.
Each of these operators is equivalent to writing guards that refer to the timestamps or start and end times of the basic events in the pattern. Normal use of these operators assumes a single global clock in the system. If there are multiple clocks, a particular clock whose readings are to be used can be named as an argument of any of these operators.