A singleton class that manages the addition and removal of WikiEvent
listeners to a event source, as well as the firing of events to those
listeners. An "event source" is the object delegating its event
handling to an inner delegating class supplied by this manager. The
class being serviced is considered a "client" of the delegate. The
WikiEventManager operates across any number of simultaneously-existing
WikiEngines since it manages all delegation on a per-object basis.
Anything that might fire a WikiEvent (or any of its subclasses) can be
a client.
Using a Delegate for Event Listener Management
Basically, rather than have all manner of client classes maintain their
own listener lists, add and remove listener methods, any class wanting
to attach listeners can simply request a delegate object to provide that
service. The delegate handles the listener list, the add and remove
listener methods. Firing events is then a matter of calling the
WikiEventManager's
WikiEventManager.fireEvent(Object,WikiEvent) method, where
the Object is the client. Prior to instantiating the event object, the
client can call
WikiEventManager.isListening(Object) to see there are any
listeners attached to its delegate.
Adding Listeners
Adding a WikiEventListener to an object is very simple:
WikiEventManager.addWikiEventListener(object,listener);
Removing Listeners
Removing a WikiEventListener from an object is very simple:
WikiEventManager.removeWikiEventListener(object,listener);
If you only have a reference to the listener, the following method
will remove it from any clients managed by the WikiEventManager:
WikiEventManager.removeWikiEventListener(listener);
Backward Compatibility: Replacing Existing fireEvent() Methods
Using one manager for all events processing permits consolidation of all event
listeners and their associated methods in one place rather than having them
attached to specific subcomponents of an application, and avoids a great deal
of event-related cut-and-paste code. Convenience methods that call the
WikiEventManager for event delegation can be written to maintain existing APIs.
For example, an existing fireEvent() method might look something like
this:
protected final void fireEvent( WikiEvent event )
{
for ( Iterator it = m_listeners.iterator(); it.hasNext(); )
{
WikiEventListener listener = (WikiEventListener)it.next();
listener.actionPerformed(event);
}
}
One disadvantage is that the above method is supplied with event objects,
which are created even when no listener exists for them. In a busy wiki
with many users unused/unnecessary event creation could be considerable.
Another advantage is that in addition to the iterator, there must be code
to support the addition and remove of listeners. The above could be
replaced with the below code (and with no necessary local support for
adding and removing listeners):
protected final void fireEvent( int type )
{
if ( WikiEventManager.isListening(this) )
{
WikiEventManager.fireEvent(this,new WikiEngineEvent(this,type));
}
}
This only needs to be customized to supply the specific parameters for
whatever WikiEvent you want to create.
Preloading Listeners
This may be used to create listeners for objects that don't yet exist,
particularly designed for embedded applications that need to be able
to listen for the instantiation of an Object, by maintaining a cache
of client-less WikiEvent sources that set their client upon being
popped from the cache. Each time any of the methods expecting a client
parameter is called with a null parameter it will preload an internal
cache with a client-less delegate object that will be popped and
returned in preference to creating a new object. This can have unwanted
side effects if there are multiple clients populating the cache with
listeners. The only check is for a Class match, so be aware if others
might be populating the client-less cache with listeners.
Listener lifecycle
Note that in most cases it is not necessary to remove a listener.
As of 2.4.97, the listeners are stored as WeakReferences, and will be
automatically cleaned at the next garbage collection, if you no longer
hold a reference to them. Of course, until the garbage is collected,
your object might still be getting events, so if you wish to avoid that,
please remove it explicitly as described above.
author: Murray Altheim since: 2.4.20 |