The ModuleIdentifierinterface refers to a Class name. This Class should be a instance of the Module class. Its interface is shown in Listing 3. There are quite a few other methods in this class, but most of them have been elided here for the sake of simplicity.
[label=lst:module,caption=The Module class] public abstract class Module public void load() throws ModuleException ; public void start(); public void destroy(); public ModuleIdentifierList getRequiredIdentifiers(); public Module getRequiredModule( ModuleIdentifier ident ); public abstract String getVersion(); // Module
We can divide the methods shown here into three groups.
Dealing with this in order. One of the requirements is for explicit dependency between modules. This is provided by the public ModuleIdentifierList getRequiredIdentifiers() method. In this method any modules which this module depends on should be identified. For example, see Listing 4, which comes from the CinemaConsensusDisplay module. This requires two other modules, namely CinemaConsensus, which actually takes on the task of calculating the consensus, and CinemaSystemEvents. The consensus display is threaded, and needs to know when the application is about to close, so that it can shut down cleanly.
[label=lst:reqident, caption=An example of getRequiredIdentifiers] public ModuleIdentifierList getRequiredIdentifiers() ModuleIdentifierList list = super.getRequiredIdentifiers(); list.add( CinemaConsensusIdentifier.CINEMA_CONSENSUS ); list.add( CinemaCoreIdentifier.CINEMA_SYSTEM_EVENTS ); return list;
The second method public Module getRequiredModule(ModuleIdentifier ident) actually allows access to these modules. Listing 5 comes again from the CinemaConsensusDisplay class
[label=lst:reqmod, caption=An example of getRequiredModule] if( queue == null ) queue = new InvokerInternalQueue ( (CinemaSystemEvents)getRequiredModule ( CinemaCoreIdentifier.CINEMA_SYSTEM_EVENTS ) );
The methods dealing with module functionality are hopefully largely self-explanatory. When the module is initially loaded, unsurprising the public void load method is called. During this time the module should perform any initialisation that is required. The rule at this time is that only initialisation that does not require other modules should be performed, as this may well not be available yet. Or in another way, while the load() method is running, there are no guarantee's about what the getRequiredModule() method will return (most likely it will return null).
Immediately after this time the public void start() method will be called. At this time it is guaranteed that the getRequiredModule() method will return any of the Modules identified, and that further all of their load() methods will have been called and have successfully completed.
This is actually simpler than it sounds, but it's designed to cope with a fairly complex dependency graph, and generally it just works. No checking is performed to ensure that the graph is acyclic The system will crash if you do this, but as per the design requirement it will fail immediately.
And finally the other method. This is meant to return a String identifying the version of the Module. This is not widely used. No specific semantics is required for this String, and generally the CVS version keyword has been used. This might be removed at a later date.