| A Registration represents an AndFilter with only elementary or negated |
| elementary filters. (In a future version, a Registration can represent |
| multiple equal such AndFilters.) |
| |
| A Registration is entered into all tables for whose type its AndFilter |
| contains an elementary filter. |
| |
| Each table maps a value for the filter criterion to a YesSet and a |
| NoSet. The YesSet contains all Registrations where a non-negated |
| elementary filter for the key criterion occurred. The NoSet contains |
| all Registrations where a negated elementary filter for the key |
| criterion occurred. |
| |
| When an event occurs, it matches a Registration if and only if all |
| (negated and non-negated) elementary filters of the registration are |
| matched. This means that: |
| |
| - if a Registration is in table t's YesSet, it MUST be matched by the |
| event e (R1). This in particular requires that e affects t. |
| |
| - if a Registration is in a table t's NoSet, it MUST NOT be matched by |
| the event e (R2). This is in particular the case if e does not |
| affect t. |
| |
| Formally, we can define a test function that for a given Registration |
| r and a given event e determines if the Registration if matched by the |
| event: |
| |
| matches(r, e) := tables->forAll(t | |
| (t.allYes->includes(r) implies |
| (t.yes(e)->includes(r) and t.affectedBy(e))) |
| and (t.allNo->includes(r) implies |
| (not t.affectedBy(e) or not t.no(e)->includes(r)))) |
| |
| Transformed: |
| |
| matches(r, e) := tables->forAll(t | matches(t, r, e)) |
| matches(t, r, e) := |
| (not t.allYes->includes(r) or t.yes(e)->includes(r) and t.affectedBy(e)) |
| and (not t.allNo->includes(r) or not (t.no(e)->includes(r) and t.affectedBy(e))) |
| |
| which shows that registrations neither in the allYes nor allNo of a |
| table t are matched by that table. |
| |
| Thinking in sets, the set of registrations matching e is the |
| intersection of the sets of registrations matched by each table. The |
| problem with this definition is only that the "universe" of all |
| registrations to be considered is the union of all allYes and allNo |
| sets of all tables, computing which would be inefficient. |
| |
| |
| The challenge now is to compute all r for a given event e for which |
| matches(r, e) holds. Fast operations (O(1)) are t.allNo, t.allYes, |
| t.yes(e), t.no(e), also t.affectedBy(e). The number of Registrations r |
| may be large, and so may be t.allYes, t.allNo, t.yes(e) and t.no(e), |
| although typically t.allNo is fairly small, and so is t.no(e), |
| particularly in the context of the OCL impact analysis. |
| |
| We also know that the union of t.allYes->union(t.allNo) over all |
| tables t results in the complete set of all Registrations. In other |
| words, each Registration to be considered is in the allYes or allNo |
| set of at least one table. The number of tables is constant and fairly |
| small (usually <10). |
| |
| We are looking for a function |
| |
| registrations(e) := all registrations r such that matches(r, e) |
| |
| that can be computed efficiently. |
| |
| |
| |
| TODO Special handling for multi-registrations, such as for multiple |
| classes in the class filter table: In this case the Registration is |
| matched if any of the multiple criteria are matched by the event. TODO |
| What happens for a negated filter that would expand to multiple |
| criteria? |