GuardConstraints let you use existing class constraints as the guard for a state-machine transition, so you can reuse business rules and show users why a transition is unavailable.
Use constraints as transition guards
A constraint is a business rule on a class. A constraint evaluates to true or false and has a description and an error level. A guard is the condition that must be satisfied before a state-machine transition can run.
Use GuardConstraints when the same rule must be valid for more than one transition. Define the rule once as a class constraint, then associate that constraint with every transition that depends on it.
For example, a class named Thing can have two constraints that must both be valid before the Trigger1 transition is available. Instead of copying both OCL expressions into the transition guard, associate the two constraints with Trigger1.
Why use GuardConstraints
A normal guard controls whether a transition is available, but it does not carry the user-facing explanation that a constraint has. A GuardConstraint combines the transition rule with the constraint descriptions.
| Need | Use | Result |
|---|---|---|
| A rule applies to the class regardless of transition | A class constraint | The rule is evaluated as a constraint and can be presented in ViewModels. |
| A transition depends on one or more existing class rules | GuardConstraints | The transition is disabled while any associated constraint is broken. |
| A transition needs a condition that is not a reusable class rule | A regular state-machine guard | The guard controls the transition without reusing a constraint definition. |
This approach avoids repeated expressions and makes the reason for an unavailable transition visible through the associated constraint message.
Define and associate GuardConstraints
- Define the required business rules as constraints on the relevant class. Write the expressions in OCL and give each constraint a meaningful description.
- Add or select the state-machine transition that must require those rules.
- In the state diagram, right-click the transition.
- Choose Edit GuardConstraintsâŚ.
- Associate one or more constraints from the transition's class with the transition.
- Save the model and test the transition with objects that break and satisfy the selected constraints.
The associated constraints implement the guard. All associated rules must be valid before the transition becomes available.
Example: two required rules
Assume Thing has two class constraints:
- Constraint A: a required business condition for
Thing. - Constraint B: another required business condition for
Thing.
Associate both constraints with the Trigger1 transition.
| Constraint A | Constraint B | Trigger1 availability
|
|---|---|---|
| Broken | Broken | Disabled. Both constraint problems remain visible. |
| Valid | Broken | Disabled. The remaining broken constraint still blocks the transition. |
| Valid | Valid | Enabled. |
This behavior is useful when users must correct several parts of an object before moving it to the next state. They can see the constraint descriptions, correct the reported issues, and retry the transition.
Write constraints for reuse
Keep a constraint focused on a rule that belongs to the class. Give it a description that tells the user what must be corrected. Then reuse it in GuardConstraints, ViewModel validation, or other model logic rather than duplicating the expression.
For example, if a rule is both a general validity requirement and a requirement for several state changes, model it as a class constraint first. Do not maintain separate copies of the same OCL expression in each transition guard.
Constraints can be configured with Information, Warning, or Error levels, and can also be delete constraints. For details on defining, presenting, and deleting with constraints, see Training:Constraints.
Inspect constraint state in OCL
You can inspect constraint metadata and whether a constraint is broken through the constraints OCL operator. This is useful when you need to base ViewModel behavior on the same rules used by a GuardConstraint.
For example, the following expression checks that no Error-level constraint is broken:
self.constraints->select(c|(c.ErrorLevel = #Error) and c.Broken)->isEmpty
See Documentation:OCLOperators constraints for the returned constraint information and further examples.
ViewModel behavior
Constraints automatically appear in ViewModels unless you opt them out for a specific ViewModel. If you add separate ViewModel validation for a class constraint, do not repeat the constraint expression. Instead, check the existing constraint so that the class rule, its message, and the transition requirement remain aligned.
See Documentation:ViewModel validations for linking ViewModel validation to constraints. If a constraint must be opted out in every relevant ViewModel, see Documentation:Opt out a constraint in all relevant viewmodel.
