Guaranį allows multiple meta-objects to be (indirectly) associated with an application object. This design creates the problem of organizing the flow of intercepted operations through the meta-objects. A specialized form of meta-object called composer is responsible for the enforcement of the policies that give structure and order to the flow of operations delegated to meta-objects.
Composers can be used to group meta-objects that are commonly used together, and these groups can be composed further, forming recursive, potentially infinite, hierarchy of meta-objects. These groups can be used as building blocks for setting up complex meta-level configurations.
We have implemented a simple (yet very useful) type of composer: the sequential composer. It organizes meta-objects in sequence, mostly like a stack: operations are fed to meta-objects descending in the stack, whereas results are presented in the reverse order to meta-objects that have requested to inspect them or to change them. Figure 3 illustrates the behavior of a sequential composer.
A concurrent composer might have been implemented too: it would present an operation to all meta-objects concurrently. Some may generate results or actions that conflict with those generated by others. In order to cope with this situation a default adjudicator could be provided: it would raise an exception to signal the conflict. Specializations of this composer may add decision-making mechanisms to the adjudicator, so that it is able to solve some conflicts.
Other more specialized composers can be implemented, as well as other generic implementations that handle conflicts in different ways, or that specify different policies for ordering the flow of operations forwarded to meta-objects. Composers may also be used to filter operations that need not be forwarded to certain meta-objects.
1
To guarantee adaptability, the design of Guaranį precludes non-composer meta-objects of maintaining direct references to other meta-objects. However, meta-objects may have to interact. To illustrate the need for interaction, consider the case of a persistent aggregate object. Making the whole aggregate persistent requires the application of the persistence mechanism to each of the component objects. In this case, the meta-objects of each component must communicate to ensure that all components have their state saved to stable storage. Guaranį implements a broadcast operation that can deliver arbitrary messages to all meta-objects associated with an application object.