public interface ListenerStore
Listeners for certain
listener classes and supplies Listeners to an EventProvider.
Every EventProvider implementation needs a reference to a ListenerStore which
manages its Listeners. It is allowed for different EventProviders to share a
single ListenerStore instance.
When dispatching an Event, the EventProvider will query
get(Class) with the respective listener class of the event to dispatch. This method returns a
Stream of Listeners which were registered for that listener class
using add(Class, Listener). A ListenerStore is said to be
sequential, iff its get method returns the registered
Listeners in the exact order in which they have been registered (FIFO). When
using a non-sequential store with a sequential EventProvider, dispatching
with that provider immediately turns non-sequential too.
In contrast to the aspect of thread safety, concurrency safety also
kicks in on single threaded event dispatching scenarios. In the context of
listener stores, this means that the Stream returned by get(Class)
must not be backed by the internal collection which is also modified
through add and
remove. This guarantees a graceful and
deterministic behavior of synchronous event dispatching. While an event is
dispatched, the following conditions must always hold:
For general purpose use with different kinds of EventProviders, the
ListenerStore implementation must be thread-safe. For example, an
asynchronous EventProvider could dispatch two Events concurrently, where
Listeners for both access the ListenerStore while being notified (E.g. they
remove themselves from the store for not being notified again). For
performance reasons, stores should always be implemented without
synchronization and instead return a synchronized view of themselves with
synchronizedView(). See AbstractSynchronizedListenerStore
for information on how to properly implement this.
Closing the ListenerStore will remove all registered
Listeners. Implementations may perform additional tasks. The ListenerStore is
automatically closed when an EventProvider which uses the store is closed.
jeve makes excessive use of java's generics to provide as much compile time
type checks as possible. When creating an EventProvider, it will always be
parameterized with the type of the store it uses. This is to make API
extensions to the ListenerStore interface (like for example the
PriorityListenerStore does) accessible to the caller of
EventProvider.listeners().
In order to be able to create an EventProvider with a certain ListenerStore
implementation but also with that implementation's
synchronizedView(), the synchronizedView's return type
must be adjusted to be compatible with the actual implementation. For
example, if the synchronizedView method on a
PriorityListenerStore would be declared to return the type
ListenerStore, then
EventProvider.configure().store(new PriorityListenerStore()).create();and
EventProvider.configure()
.store(new PriorityListenerStore().synchronizedView())
.create();
would yield two incompatible EventProvider types (the first is of type
EventProvider<PriorityListenerStore> and the second of type
EventProvider<ListenerStore>.
| Modifier and Type | Method and Description |
|---|---|
<L extends Listener> |
add(Class<L> listenerClass,
L listener)
Adds a listener which will be notified for every event represented by the
given listener class.
|
<L extends Listener> |
add(L listener)
Adds the given object for all listener classes it implements.
|
void |
clearAll()
Removes all registered listeners from this EventProvider.
|
<L extends Listener> |
clearAll(Class<L> listenerClass)
Removes all listeners which have been registered for the provided
listener class.
|
void |
close()
Removes all registered Listeners from this store (
Listener.onUnregister(RegistrationEvent) will be called on each
Listener). |
<L extends Listener> |
get(Class<L> listenerClass)
Gets all listeners that have been registered using
add(Class, Listener) for the given listener class. |
boolean |
isSequential()
States whether this ListenerStore implementation is sequential.
|
<L extends Listener> |
remove(Class<L> listenerClass,
L listener)
Removes a listener.
|
<L extends Listener> |
remove(L listener)
Removes the given object for all listener classes it implements.
|
ListenerStore |
synchronizedView()
Returns a thread safe view of this store.
|
ListenerStore synchronizedView()
Returns a thread safe view of this store. The returned store will be backed by this one, thus changes on the one object are automatically reflected to the other. This also implies that unsynchronized access is still possible through the original object.
Subsequent calls to this method must return a cached instance of the
synchronized view. Store implementations that are natively thread safe
may simply return this.
Note: The actual returned object must be assignment compatible with this store, thus for the implementation 'MyListenerStore' the following statement must compile:
MyListenerStore store = new MyListenerStore().synchronizedView();
<L extends Listener> void add(Class<L> listenerClass, L listener)
onRegister method gets
called to notify the listener about being added to a new parent. The
onRegister method is not subject to the dispatching strategy
implemented by this EventProvider and is called from the current
thread.
Note on concurrency: This method can safely be called from within a listening method during event handling to add a listener. This will have no impact on the current event delegation process.
L - Type of the listener to add.listenerClass - The class representing the event(s) to listen on.listener - The listener to add.IllegalArgumentException - If either listenerClass or listener
argument is null.<L extends Listener> void add(L listener)
Adds the given object for all listener classes it implements. This recursively traverses super classes and super interfaces of the given listener's class. When encountering a super interface X which
Listener.class butListener.class andListenerKind.TAGGINGthen the given listener will be registered for X. Otherwise, all super interfaces of X are processed in the same way. When all super interfaces have been processed, the same process is recursively applied to the super class of the given listener if it has one. The "otherwise" implies, that the inheritance hierarchy of classes which have already been recognized as target listener class will not be traversed. If the same listener class is encountered multiple times while traversing the hierarchy, the listener will still only be registered once for that class.
Note that for each class the listener is being added its
onRegister method is
called.
L - Type of the listener.listener - The listener to add.<L extends Listener> void remove(L listener)
add(Listener) to learn how these classes are collected from the
given listener. If the same listener has been added multiple times for
the same listener class, only one reference will be removed. This is
compatible with the definition of remove(Class, Listener), which
also only removes one reference of the listener.
Note that for each class the listener is being removed its
onUnregister method is
called.
L - Type of the listener.listener - The listener to remove.<L extends Listener> void remove(Class<L> listenerClass, L listener)
onUnregister
method gets called to notify the listener about being removed from a
parent. The onUnregister method is not subject to the dispatching
strategy implemented by this EventProvider and is called from the
current thread.
If any of the arguments is null, this method returns with no
effect.
Note on concurrency: This method can safely be called from within a listening method during event handling to remove a listener. This will have no impact on the current event delegation process.
L - Type of the listener to remove.listenerClass - The class representing the event(s) for which the
listener should be removed.listener - The listener to remove.<L extends Listener> Stream<L> get(Class<L> listenerClass)
add(Class, Listener) for the given listener class.
Note on concurrency: The returned Stream will not be backed by the
internal list which is also modified via add(Class, Listener) or
remove(Class, Listener). This allows to add or remove listeners
to this store while the Stream is being iterated.
L - Type of the listeners to return.listenerClass - The class representing the event for which the
listeners should be retrieved.IllegalArgumentException - If listenerClass is null.<L extends Listener> void clearAll(Class<L> listenerClass)
onUnregister method will
be called. The actual order in which listeners are removed is undefined.
If listenerClass is null this method returns with no effect.
Note on concurrency: This method can safely be called from within a listening method during event handling to remove listeners. This will have no impact on the current event delegation process.
L - Type of the listeners to remove.listenerClass - The class representing the event for which the
listeners should be removedvoid clearAll()
onUnregister method will
be called. The actual order in which listeners are removed is undefined.
Note on concurrency: This method can safely be called from within a listening method during event handling to remove all listeners. This will have no impact on the current event delegation process.
boolean isSequential()
get(Class)
returns the registered Listeners in FIFO order regarding their time of
registration.void close()
Listener.onUnregister(RegistrationEvent) will be called on each
Listener). Implementors may also release additional resource held by
their implementations.
Note: This method is automatically called upon closing an
EventProvider which uses this store.
Copyright © 2014–2015. All rights reserved.