Behavioral links are the relation between the hookset and the metaobject definition. Links are the most important element of Reflex. They have a serie of attributed related to: the cardinality of the relation, the protocol of the communication among others.
In this section we will review all the attributes of a behavioral link: control, scope, activation, mintypes, updatable, declared type and initialization.
Description:
The Control attribute of a link specifies when (relative to the operation matched by the hookset) the associated metaobject will take the control of execution.
Possible values:
Control.BEFORE
The control will be taken before the operation occurrence.
Control.AFTER
The control will be taken after the operation occurrence.
Control.BEFORE_AFTER
The control will be taken both before and after the operation occurrence.
Control.AROUND
The control will be taken instead of the operation occurrence (it will be taken before and it will return after the operation occurrence).
Default value: Control.AROUND
Example code:
BLink theBLink = ...; theBLink.setControl(Control.BEFORE_AFTER);
The Scope attribute is used to specify the scope of a metaobject in this link.
Posible values:
Scope.OBJECT
Means that for each object in the application (which class is subject to this link) there will be one metaobject.
Scope.CLASS
Means that for each class in the application (which is subject to this link) there will be one metaobject.
* Scope.GLOBAL
Means that for all classes in the application (which are subject to this link) there will be one metaobject.
Default value: Scope.GLOBAL
Example code:
BLink theBLink = ...; theBLink.setScope(Scope.CLASS);
Description:
The Activation attribute defines how to calculate if a link is active or not. This calculation is delegated to an Active
object the Activation must return through its getActiveInstance
method (note that this delegation only occurs if the method isEnabled
returns true
at code generation time). The relevant part of the definition of both classes is:
public class Activation{ public boolean isEnabled(){ ... } public Active getActiveInstance(){ ... } }
* Active
public interface Active { public boolean evaluate(Object aObject); }
At the end, and this must be be clear, the method that determines if a metaobject is active at a given time is Active.evaluate
. This method takes as parameter the object in which the hook is occurring: the java.lang.Class
(if the link is in a static context) or the evaluation of this
in the hook.
The Active
instance can be changed at runtime if the Activation.isEnabled
returned true at generation time. The API to change this is in the RTLink class, that is reviewed here;
Util values have been defined for both classes, let us review them now.
Activation:
Activation.DISABLED
An activation that dicatates that the metaobject is always active (because its isEnabled method returns false, so the delegation never occur) and hence, it can not be changed at runtime.
Activation.ENABLED_START_ON
An activation that dictates that the metaobject starts active, but this situation can be changed at runtime (because its isEnabled method returned true at generation time, and hence a delegation is occurring each time the hook is reached to determine if the metaobject is active).
Activation.ENABLED_START_OFF
An activation that dictates that the metaobject starts inactive, but this situation can be changed at runtime (because its isEnabled method returned true at generation time, and hence a delegation is occurring each time the hook is reached to determine if the metaobject is active).
Active:
Active.ON
Means that the metaobject is active.
Active.OFF
Means that the metaobject is not active.
Active.SUB
Means that to determine of the metaobject is active, a delegation should be done: For hook belonging to a hookset in link L in a given object O instance of C will be active if and only if:
SUB
and the activation condition of C (for L) evaluates to true, orSUB
and the activation condition of C (for L) is SUB
and the activation condition of O (for L) evaluates to true.
Default value: N/A depends on the specified Activation
The MinTypes attribute makes us able to specify a set of classes and/or interfaces the metaobject should be compatible with.
Default value: [] (empty list)
Example code:
BLink theBLink = ...; theBLink.getMinTypes().add("java.io.Serializable"); theBLink.getMinTypes().add(java.io.Externalizable.class);
The Updatable attribute allows us to specify if the metaobject associated to this link can be changed at runtime.
Posible values:
true
Means that the metaobject can be changed at runtime.
false
Means that the metaobject can not be changed at runtime.
Default value: true
Example code:
BLink theBLink = ...; theBLink.setUpdatable(false);
The DeclaredType attribute allows us to specify the declared type of the metaobject.
When Reflex generates code, it assumes that the metaobject's type is java.lang.Object
. Then, when a method call must be done, a cast is inserted to make the metaobject fit the correct type. The purpose of this attribute is to avoid those casts.
Note: this attribute is only taken into account for links with scope object or class (it is ignored if the link has global scope).
Default value: java.lang.Object
Example code:
BLink theBLink = ...; theBLink.setDeclaredType(new DeclaredType("java.io.PrintStream"); //or theBLink.setDeclaredType(new DeclaredType(java.lang.Appendable.class);
The Initialization attribute specifies when and how the metaobject should be instantiated.
Posible values:
Initilization.EAGER
Means that the metaobject will be initialized eagerly at the end of each contructor if the scope is OBJECT
, at the class static initialization block if the scope is CLASS and at a global initilizer class if the scope is GLOBAL
.
Initilization.LAZY_UNSAFE
Means that the metaobject will be initialized the first time it is required. This initialization is not synchronized, then, data races can occur.
Initilization.LAZY_SAFE
Means that the metaobject will be initialized the first time it is required. This initialization is synchronized, then, no data races can occur, but the synchronization cost must be paid.
Default value: Initilization.LAZY_SAFE
Example code:
BLink theBLink = ...; theBLink.setInitialization(Initilization.EAGER);