Class StoreListeners
- All Implemented Interfaces:
Localized
StoreListener instances and provides convenience methods for sending events.
This is a helper class for DataStore and Resource implementations.
Observers can add listeners for being notified about events,
and producers can invoke one of the warning(…) and other methods for emitting events.
Warning events
All warnings are given to the listeners asLogRecord instances (this allows localizable messages
and additional information like stack trace, timestamp, etc.).
This StoreListeners class provides convenience methods like warning(String, Exception),
which build LogRecord from an exception or from a string. But all those warning(…) methods
ultimately delegate to warning(LogRecord, Filter), thus providing a single point that subclasses
can override. When a warning is emitted, the default behavior is:
- Notify all listeners that are registered for a given
WarningEventtype in thisStoreListenersand in the parent resource or data store. Each listener will be notified only once, even if the same listener is registered in two or more places. - If previous step found no listener registered for
WarningEvent, then log the warning in the first logger found in following choices:- The logger specified by
LogRecord.getLoggerName()if non-null. - Otherwise the logger specified by
DataStoreProvider.getLogger()if the provider can be found. - Otherwise a logger whose name is the source
DataStorepackage name.
- The logger specified by
Thread safety
The sameStoreListeners instance can be safely used by many threads without synchronization
on the part of the caller. Subclasses should make sure that any overridden methods remain safe to call
from multiple threads.- Since:
- 1.0
- Version:
- 1.3
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprivate static final classStoreListeners.ForType<E extends StoreEvent>All listeners for a given even type. -
Field Summary
FieldsModifier and TypeFieldDescriptionprivate Map<Class<?>,StoreListener<?>> TheCascadedStoreEvent.ParentListeners registered onparent.private StoreListeners.ForType<?>The head of a chained list of listeners, ornullif none.private final StoreListenersParent set of listeners to notify in addition to this set of listeners, ornullif none.private Set<Class<? extends StoreEvent>>All types of of events that may be fired, ornullif no restriction.private static final Set<Class<? extends StoreEvent>>Frequently used value forpermittedEventTypes.private final ResourceThe declared source of events. -
Constructor Summary
ConstructorsConstructorDescriptionStoreListeners(StoreListeners parent, Resource source) Creates a new instance with the given parent and initially no listener. -
Method Summary
Modifier and TypeMethodDescription<E extends StoreEvent>
voidaddListener(Class<E> eventType, StoreListener<? super E> listener) Registers a listener to notify when the specified kind of event occurs.(package private) static voidcanNotNotify(String method, ExecutionException error) Invoked if an error occurred in a least one listener during the propagation of an event.voidclose()Sends aCloseEventto all listeners registered for that kind of event, then discards listeners in this instance (but not in parents).<E extends StoreEvent>
booleanDeprecated.<E extends StoreEvent>
booleanSends the given event to all listeners registered for the given type or for a super-type.(package private) static <E extends StoreEvent>
booleanfire(StoreListeners m, Class<E> eventType, E event) Sends the given event to all listeners registered in the given set of listeners and its parent.private static DataStoreReturns the data store of the source, ornullif unknown.Returns the locale used by this manager, ornullif unspecified.Returns the logger where to send warnings when no other destination is specified.Returns the parent set of listeners that are notified in addition to this set of listeners.Returns the source of events.Returns a short name or label for the source.<E extends StoreEvent>
booleanhasListener(Class<E> eventType, StoreListener<? super E> listener) Returnstrueif the given listener is registered for the given type or a super-type.booleanhasListeners(Class<? extends StoreEvent> eventType) Returnstrueif at least one listener is registered for the given type or a super-type.private IllegalArgumentExceptionillegalEventType(Class<?> type) Returns the exception to throw for an event type which is not in the set of permitted types.private static booleanisPossibleEvent(Set<Class<? extends StoreEvent>> permittedEventTypes, Class<?> eventType) Verifies if a listener interested in the specified type of events could receive some events from thisStoreListeners.<E extends StoreEvent>
voidremoveListener(Class<E> eventType, StoreListener<? super E> listener) Unregisters a listener previously added for the given type of events.private static booleansetPublicSource(LogRecord record, Class<?> type, String methodName) Eventually sets the class name and method name in the given record, and returnstrueif the method is public resource method.voidsetUsableEventTypes(Class<?>... permitted) Notifies thisStoreListenersthat only events of the specified types will be fired.toString()Returns a string representation for debugging purposes.voidvoidDeprecated.RenameduseReadOnlyEvents().voidReports a warning described by the given exception.voidReports a warning described by the given message.voidReports a warning described by the given message and exception.voidReports a warning at the given level represented by the given message and exception.voidReports a warning described by the given log record.voidReports a warning described by the given log record.
-
Field Details
-
parent
Parent set of listeners to notify in addition to this set of listeners, ornullif none. This is used when a resource is created for reading components of a larger data store. -
source
The declared source of events. This is not necessarily the real source, but this is the source that the implementer wants to declare as public API. Shall not benull. -
listeners
The head of a chained list of listeners, ornullif none. Each element in this chain contains all listeners for a given even type. -
permittedEventTypes
All types of of events that may be fired, ornullif no restriction. This is a copy on write set: no elements are modified after a set has been created.- See Also:
-
READ_EVENT_TYPES
Frequently used value forpermittedEventTypes.- See Also:
-
cascadedListeners
TheCascadedStoreEvent.ParentListeners registered onparent. This is created the first time that aCascadedStoreEventlistener is registered on a resource which is not the root resource. Those listeners are handled in a special way, because a closing event on the root resource should cause all children to also fire their ownCloseEvent.
-
-
Constructor Details
-
StoreListeners
Creates a new instance with the given parent and initially no listener. The parent is typically the listeners of theDataStorethat created a resource. When an event is fired, listeners registered in the parent will be notified as well as listeners registered in thisStoreListeners. Each listener will be notified only once even if it has been registered in two places.Permitted even types
If the parent restricts the usable event types to a subset ofStoreEventsubtypes, then thisStoreListenersinherits those restrictions. The list of usable types can be rectricted more but cannot be relaxed.- Parameters:
parent- the manager to notify in addition to this manager, ornullif none.source- the source of events. Cannot be null.
-
-
Method Details
-
getParent
Returns the parent set of listeners that are notified in addition to this set of listeners. This is the value of theparentargument given to the constructor.- Returns:
- parent set of listeners that are notified in addition to this set of listeners.
- Since:
- 1.3
-
getSource
Returns the source of events. This value is specified at construction time.- Returns:
- the source of events (never
null).
-
getDataStore
Returns the data store of the source, ornullif unknown. -
getSourceName
Returns a short name or label for the source. It may be the name of the file opened by a data store. The returned name can be useful in warning messages for identifying the problematic source.The default implementation fetches a name from the data store, or returns an arbitrary name if no better name is found.
- Returns:
- a short name of label for the source (never
null). - See Also:
-
getLocale
Returns the locale used by this manager, ornullif unspecified. That locale is typically inherited from theDataStorelocale and can be used for formatting messages. -
getLogger
Returns the logger where to send warnings when no other destination is specified. This method tries to get the logger fromDataStoreProvider.getLogger(). If that logger cannot be found, then this method infers a logger name from the package name of the source data store. The returned logger is used when:- no listener has been registered for the
WarningEventtype, and - the
LogRecorddoes not specify a logger.
- Returns:
- the logger where to send the warnings when there are no other destinations.
- Since:
- 1.1
- See Also:
- no listener has been registered for the
-
useWarningEventsOnly
Deprecated.RenameduseReadOnlyEvents().- Since:
- 1.2
-
warning
Reports a warning described by the given message.This method is a shortcut for
warning(Level.WARNING, message, null).- Parameters:
message- the warning message to report.
-
warning
Reports a warning described by the given exception. The exception stack trace will be omitted at logging time for avoiding to pollute console output (keeping in mind that this method should be invoked only for non-fatal warnings). See below for more explanation.This method is a shortcut for
warning(Level.WARNING, null, exception).- Parameters:
exception- the exception to report.
-
warning
Reports a warning described by the given message and exception. At least one ofmessageandexceptionarguments shall be non-null. If both are non-null, then the exception message will be concatenated after the given message. If the exception is non-null, its stack trace will be omitted at logging time for avoiding to pollute console output (keeping in mind that this method should be invoked only for non-fatal warnings). See below for more explanation.This method is a shortcut for
warning(Level.WARNING, message, exception).- Parameters:
message- the warning message to report, ornullif none.exception- the exception to report, ornullif none.
-
warning
Reports a warning at the given level represented by the given message and exception. At least one ofmessageandexceptionarguments shall be non-null. If both are non-null, then the exception message will be concatenated after the given message.Stack trace omission
If there are no registered listeners for theWarningEventtype, then theLogRecordwill be sent to aLoggerbut without the stack trace. This is done that way because stack traces consume lot of space in the logging files, while being considered implementation details in the context ofStoreListeners(on the assumption that the logging message provides sufficient information).- Parameters:
level- the warning level.message- the message to log, ornullif none.exception- the exception to log, ornullif none.
-
setPublicSource
Eventually sets the class name and method name in the given record, and returnstrueif the method is public resource method.- Parameters:
record- the record where to set the source class/method name.type- the source class. This method does nothing if the class is not aResource.methodName- the source method.- Returns:
- whether the source is a public method of a
Resource. - Throws:
SecurityException- if this method is not allowed to get the list of public methods.
-
warning
Reports a warning described by the given log record. Invoking this method is equivalent to invokingwarning(LogRecord, Filter)with a null filter.- Parameters:
description- warning details provided as a log record.
-
warning
Reports a warning described by the given log record. The default implementation forwards the given record to one of the following destinations, in preference order:StoreListener.eventOccured(new WarningEvent(source, record))on all listeners registered for this kind of event.onUnhandled.isLoggable(description)if above step found no listener and theonUnhandledfilter is non-null.Logger.getLogger(record.loggerName).log(record)if the filter in above step returnedtrue(or if the filter is null). In that case,loggerNameis one of the following:record.getLoggerName()if that value is non-null.- Otherwise the value of
DataStoreProvider.getLogger()if the provider is found. - Otherwise the source
DataStorepackage name.
- Parameters:
description- warning details provided as a log record.onUnhandled- filter invoked if the record has not been handled by aStoreListener, ornullif none. This filter determines whether the record should be sent to the logger returned bygetLogger().- Since:
- 1.2
-
canNotNotify
Invoked if an error occurred in a least one listener during the propagation of an event. The cause of the exception is aRuntimeException. If exceptions occurred in more than one listener, all exceptions after the first one are specified as suppressed exceptions of the cause.This method should not delegate to
warning(Exception)because the error is not with the data store itself. Furthermore, the exception may have occurred duringwarning(…)execution, in which case the exception is a kind of "warning about warning report".- Parameters:
method- name of the method invoking this method.error- the exception that occurred.
-
fire
Deprecated.Replaced byfire(Class, StoreEvent)for consistency with the argument order in all other methods of this class. -
fire
Sends the given event to all listeners registered for the given type or for a super-type. This method first notifies the listeners registered in thisStoreListeners, then notifies listeners registered in parentStoreListenerss. Each listener will be notified only once even if it has been registered many times.If one or many
StoreListener.eventOccured(StoreEvent)implemetations throw aRuntimeException, those exceptions will be collected and reported in a single log record. Runtime exceptions in listeners do not cause this method to fail.- Type Parameters:
E- compile-time value of theeventTypeargument.- Parameters:
eventType- the type of the event to be fired.event- the event to fire.- Returns:
trueif the event has been sent to at least one listener.- Throws:
IllegalArgumentException- if the given event type is not one of the types of events that thisStoreListenerscan fire.- Since:
- 1.3
- See Also:
-
fire
static <E extends StoreEvent> boolean fire(StoreListeners m, Class<E> eventType, E event) throws ExecutionException Sends the given event to all listeners registered in the given set of listeners and its parent. This method does not perform any argument validation; they must be done by the caller.This method does not need (and should not) be synchronized.
- Type Parameters:
E- compile-time value of theeventTypeargument.- Parameters:
m- the set of listeners that may be interested in the event.eventType- the type of the event to be fired.event- the event to fire.- Returns:
trueif the event has been sent to at least one listener.- Throws:
ExecutionException- if an exception is thrown insideStoreListener.eventOccured(StoreEvent). All other listeners continue to receive the event beforeExecutionExceptionis thrown.
-
illegalEventType
Returns the exception to throw for an event type which is not in the set of permitted types. -
isPossibleEvent
private static boolean isPossibleEvent(Set<Class<? extends StoreEvent>> permittedEventTypes, Class<?> eventType) Verifies if a listener interested in the specified type of events could receive some events from thisStoreListeners.- Parameters:
eventType- type of events to listen.- Returns:
- whether a listener could receive events of the specified type.
- See Also:
-
addListener
public <E extends StoreEvent> void addListener(Class<E> eventType, StoreListener<? super E> listener) Registers a listener to notify when the specified kind of event occurs. Registering a listener for a giveneventTypealso register the listener for all event sub-types. The same listener can be registered many times, but itsStoreListener.eventOccured(StoreEvent)method will be invoked only once per event. This filtering applies even if the listener is registered on different resources in the same tree, for example a parent and its children.Warning events
IfeventTypeis assignable fromWarningEvent.class, then registering that listener turns off logging of warning messages for this manager. This side-effect is applied on the assumption that the registered listener will handle warnings in its own way, for example by showing warnings in a widget.- Type Parameters:
E- compile-time value of theeventTypeargument.- Parameters:
eventType- type ofStoreEventto listen (cannot benull).listener- listener to notify about events.- See Also:
-
removeListener
public <E extends StoreEvent> void removeListener(Class<E> eventType, StoreListener<? super E> listener) Unregisters a listener previously added for the given type of events. TheeventTypemust be the exact same class than the one given to theaddListener(…)method; this method does not remove listeners registered for subclasses and does not remove listeners registered in parent manager.If the same listener has been registered many times for the same even type, then this method removes only the most recent registration. In other words if
addListener(type, ls)has been invoked twice, thenremoveListener(type, ls)needs to be invoked twice in order to remove all instances of that listener. If the given listener is not found, then this method does nothing (no exception is thrown).Warning events
IfeventTypeisWarningEvent.classand if, after this method invocation, there are no remaining listeners for warning events, then thisStoreListenerswill send future warnings to the loggers.- Type Parameters:
E- compile-time value of theeventTypeargument.- Parameters:
eventType- type ofStoreEventwhich were listened (cannot benull).listener- listener to stop notifying about events.- See Also:
-
hasListener
public <E extends StoreEvent> boolean hasListener(Class<E> eventType, StoreListener<? super E> listener) Returnstrueif the given listener is registered for the given type or a super-type. This method may unconditionally returnfalseif the given type of event is never fired by thisStoreListeners, because calls toaddListener(eventType, …)are free to ignore the listeners for those types.- Type Parameters:
E- compile-time value of theeventTypeargument.- Parameters:
eventType- type ofStoreEventto check (cannot benull).listener- listener to check for registration.- Returns:
trueif this object contains the specified listener for given event type,falseotherwise.- Since:
- 1.3
-
hasListeners
Returnstrueif at least one listener is registered for the given type or a super-type. This method may unconditionally returnfalseif the given type of event is never fired by thisStoreListeners, because calls toaddListener(eventType, …)are free to ignore the listeners for those types.- Parameters:
eventType- the type of event for which to check listener presence.- Returns:
trueif this object contains at least one listener for given event type,falseotherwise.
-
setUsableEventTypes
Notifies thisStoreListenersthat only events of the specified types will be fired. With this knowledge,StoreListenerswill not retain any reference to listeners that are not listening to events of those types or to events of a parent type. This restriction allows the garbage collector to dispose unnecessary listeners.Example: an application may unconditionally register listeners for being notified about additions of new data. If aThe argument shall enumerate all permitted types, including sub-types (they are not automatically accepted). All types given in argument must be types that were accepted before the invocation of this method. In other words, this method can be invoked for reducing the set of permitted types but not for expanding it.DataStoreimplementation is read-only, then such listeners would never receive any notification. As a slight optimization, theDataStoreconstructor can invoke this method for example as below: With this configuration, calls toaddListener(DataAddedEvent.class, foo)will be ignored, thus avoiding this instance to retain a never-used reference to thefoolistener.- Parameters:
permitted- type of events that are permitted. Permitted sub-types shall be explicitly enumerated as well.- Throws:
IllegalArgumentException- if one of the given types was not permitted before invocation of this method.- Since:
- 1.2
- See Also:
-
useReadOnlyEvents
public void useReadOnlyEvents()Notifies thisStoreListenersthat it will fire onlyWarningEvents andCloseEvent. This method is a shortcut forsetUsableEventTypes(WarningEvent.class, CloseEvent.class)}, provided because frequently used by read-only data store implementations.Declaring a root resource (typically a
DataStore) as read-only implies that all children (e.g. components of an aggregate) are also read-only.- Since:
- 1.3
- See Also:
-
close
public void close()Sends aCloseEventto all listeners registered for that kind of event, then discards listeners in this instance (but not in parents). Because listeners are discarded, invoking this method many times on the same instance has no effect after the first invocation.If one or many
StoreListener.eventOccured(StoreEvent)implementations throw aRuntimeException, those exceptions will be collected and reported in a single log record. Runtime exceptions in listeners do not cause this method to fail.- Since:
- 1.3
- See Also:
-
toString
Returns a string representation for debugging purposes.
-
fire(Class, StoreEvent)for consistency with the argument order in all other methods of this class.