Constraints often require matching rows exist / do not exist in other collections. See the examples below.
Solution: provide re-usable Logic
Since this is a common pattern, we provide a re-usable Java class with:
aLogicContext identifies the current source row, as described below
aSet e.g., productBillofmaterials.getProduct().getComponents()
aFilter e.g., source.kit.name = product.name
This service is typically called from a constraint. A similar method FindFirst ensures that only one matching row exists (else throws an Exception).
The following examples illustrate Find Where.
LanguageSpoken exists for each LanguageTranslated
Thanks to Florian of MinuteProject
for this clear example: imagine a Person had 2 n:m relationships to Language: LanguageSpoken and LanguageTranslates. It is a certain requirement that a person must speak a language in order to translate it. So, we can use FindWhere to verify a Person has a LanguageSpoken for each LanguageTranslates.
Component may not be a containing kit
With a Bill of Materials structure
, we want to ensure that a component is not a containing kit. We can enforce this with the following constraint:
The key system capability is that Constraint methods can invoke Java methods, such as FindWhere. The invocation at line 73 passes the sub-components of our component, searching for sub-component where the product.name equals our source kit name.
The BusLogicIntro samples provide a jUnit test of this service. As shown below, we attempt to add a plane as a component of a Wing, and then verify that the expected constraint exception was raised:
FindWhere operates by iterating though the collection, evaluating the filter condition via jexl
. This makes effective use of the Hibernate cache, but is not suitable for large collections.
The filter passed to FindWhere is evaluated for each row in aSet. By default, the operands are properties of this domain object.
In most cases, you need to compare these to some property in the source domain object (i.e., the
where you defined the Constraint). You can reference these attributes using the
reference as illustrated above. The actual bean instance is obtained from the
passed to FindWhere.