Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.
OTPattern/ObjectRegistration
Intent
A role class should only apply to explicitly registered base objects.
Motivation
Normally, a role class virtually adapts all instance of their base class. As a result, any callin binding OTJLD §4 within the role class is triggered on each base instance executing the method bound by the callin. If the effect of the role class should, however, be constrained to specific base objects, a technique is needed for registering some objects while excluding all others.
Structure
This pattern only requires three classes, Role and Base, bound by a playedBy declaration, plus of course an enclosing team Registry.
Collaboration
- Role: The role class excludes all base instances from firing callins using a simple guard predicate (OTJLD §5.4).
- Registry: The enclosing team offers a registration method with declared lifting (OTJLD §2.3.2) which may even have an empty body.
- Client: The client, who knows for which base instances callins should fire, registers these base instances using the team's registration method.
public team class Registry { protected class Role playedBy Base base when (Registry.this.hasRole(base, Role.class)) { // role declarations including callins: roleMethod <- before baseMethod; } public void registerBase(Base as Role object) { // no statements required } } ... // Client code: Registry reg= new Registry(); reg.activate(ALL_THREADS); Base b= new Base(); reg.registerBase(b); // some time later: b.baseMethod(); // callin binding fires Base b2= new Base(); b2.baseMethod(); // callin binding does not fire, object is not registered
- Notes
- A base guard (OTJLD §5.4.2) has to be used in order to actually prevent lifting when evaluating to false.
- The guard predicate uses the reflective method hasRole (OTJLD §6.1). Passing the class literal
Role.class
is not strictly required (but might improve performance, as fewer lookups are used internally).
Consequences
In standard cases these few lines completely suffice. In particular, no hand-coded registry is needed since every team is already a registry for its roles.
If other locations exist (callin or callout bindings) where an instance of Base could be lifted to Role, this will have the effect of implicitly registering that instance, because the guard predicate only applies to the call target of a callin, never to arguments or return values. If this effect is not intended, yet temporarily lifting a Base is required, the reflective method unregisterRole (OTJLD §6.1) might help. However, such situation may indicate that usage of roles is not fully consistent: if a base instance enters a team by lifting as an argument or return value, it is probably relevant for this context and thus it might indeed need to be registered (implicitly or explicitly). In other words, implicit lifting may very well be a part of the required registration protocol.
Related Patterns
- ObjectRegistration is frequently used in the context of Notification.