Class AbstractObservable<O,EV>

  • Type Parameters:
    O - The observer's (event listeners) to be managed by the Observable.
    EV - The base event to be fired by this Observable.
    All Implemented Interfaces:
    org.refcodes.mixin.Disposable, org.refcodes.mixin.Loggable, Observable<O>


    public abstract class AbstractObservable<O,EV>
    extends java.lang.Object
    implements Observable<O>, org.refcodes.mixin.Disposable, org.refcodes.mixin.Loggable
    This abstract class provides functionality to implement default refcodes Observable behavior. The fireEvent(Object, Object, ExecutionStrategy) is to be overwritten to invoke the according event lister'#s method for a given event to be distributed. The doHandleEventListenerException(Exception, Object, Object, ExecutionStrategy) method can be overwritten to handle any exceptions thrown by the fireEvent(Object, Object, ExecutionStrategy) method. Depending on the ExecutionStrategy, distribution of the events is handled differently: ExecutionStrategy.SEQUENTIAL: You determine that each event listener is signaled one after the other and not in parallel. In case you want to restrict thread generation, this sequential event distribution is the one to go for: Each event listener is invoked after the other one after the other. The execution chain of invoking the event listeners can be aborted by a boolean flag returned by an invoked event listener method or by a VetoException thrown by an invoked event listener method. In sequential event distribution, you can also take care of exceptions thrown or return vales passed to you by the event listeners to affect the execution of the chain of event listeners. As soon as the execution chain of invoking event listeners terminates, then this method terminates. ExecutionStrategy.PARALLEL: You determine that each event listener is signaled in parallel. In case you want to prevent that one event listener can cause the succeeding event listeners to be delayed for signaling, then the parallel mode is the one to go for. As soon as all event listeners have their own thread, this method exits. You cannot affect the execution of event listeners as all of them are invoked ignoring any exceptions or return values of the other invoked event listeners. Here as we do not collect any exceptions or any results from each invoked event listener, there are no means provided to evaluate them during or after event distribution. ExecutionStrategy.JOIN: Similar to ExecutionStrategy.PARALLEL with the difference, that all threads are joined and the method terminates as soon as the latest thread terminates. As of this, a VetoException as well as a return value can be evaluated though still no influence can be taken upon the execution of the invocation of the event listeners. In case any of the listeners returns false, then this event distribution mode will cause to return false, in case any event listener throws a VetoException, then the first detected VetoException is thrown when executing with this event distribution mode. No matter of the exceptions or return values, as of the ExecutionStrategy.PARALLEL event distribution mode, all event listeners are invoked.
    • Nested Class Summary

      • Nested classes/interfaces inherited from interface org.refcodes.mixin.Disposable

        org.refcodes.mixin.Disposable.Disposedable
    • Field Summary

      • Fields inherited from interface org.refcodes.mixin.Loggable

        RUNTIME_LOGGER_CLASS, RUNTIME_LOGGER_FACTORY_CLASS, RUNTIME_LOGGER_FACTORY_METHOD
    • Method Summary

      All Methods Instance Methods Abstract Methods Concrete Methods 
      Modifier and Type Method Description
      protected void clear​()
      Clears all observers from this AbstractObservable.
      void dispose​()
      protected void doHandleEventListenerException​(java.lang.Exception aException, O aObserver, EV aEvent, org.refcodes.controlflow.ExecutionStrategy aExecutionStrategy)
      This hook method allows you to handle any exceptions being thrown by an event listener whilst invoking a given event.
      protected boolean fireEvent​(EV aEvent, org.refcodes.controlflow.ExecutionStrategy aExecutionStrategy)
      To be used by the implementing class when firing an event to it's listeners.
      protected abstract boolean fireEvent​(EV aEvent, O aObserver, org.refcodes.controlflow.ExecutionStrategy aExecutionStrategy)
      This hook method is to be implemented by the implementing class.
      int getThreadPriority​()
      In case of ExecutionStrategy.PARALLEL or ExecutionStrategy.JOIN, the threads' priority is defined by this attribute.
      boolean hasObserverSubscription​(O aObserver)
      Tests whether the given observer (event listener) has been added to this Observable.
      protected boolean isEmpty​()
      Determines whether there are observers being registered.
      protected boolean isObserversActive​()  
      protected java.util.Iterator<O> observers​()  
      protected void setObserversActive​(boolean isActive)  
      void setThreadPriority​(int threadPriority)
      In case of ExecutionStrategy.PARALLEL or ExecutionStrategy.JOIN, the threads' priority is defined by this attribute.
      protected int size​()
      Determines the number of observers being registered.
      boolean subscribeObserver​(O aObserver)
      Adds the given observer (event listener).
      boolean unsubscribeObserver​(O aObserver)
      Removes the observer (event listener).
      • Methods inherited from interface org.refcodes.mixin.Loggable

        alert, alert, critical, critical, debug, error, info, notice, panic, trace, warn, warn
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • Constructor Detail

      • AbstractObservable

        public AbstractObservable​()
        Constructs the AbstractObservable with a default ExecutorService pool.
      • AbstractObservable

        public AbstractObservable​(java.util.concurrent.ExecutorService aExecutorService)
        Constructs the AbstractObservable with a provided ExecutorService pool.
        Parameters:
        aExecutorService - The ExecutorService to be used when firing GenericActionEvent instances in ExecutionStrategy.PARALLEL or ExecutionStrategy.JOIN
    • Method Detail

      • fireEvent

        protected boolean fireEvent​(EV aEvent,
                                    org.refcodes.controlflow.ExecutionStrategy aExecutionStrategy)
                             throws org.refcodes.exception.VetoException
        To be used by the implementing class when firing an event to it's listeners. Use one of the event distribution modes as defined in ExecutionStrategy.
        Parameters:
        aEvent - The event to be fired.
        aExecutionStrategy - The event
        Returns:
        True in case all event listeners were invoked, false in case one invoked event listener returned false ("stop continuing") upon invocation or the overall observers have been disables as of setObserversActive(boolean).
        Throws:
        org.refcodes.exception.VetoException - in case one of the invoked event listeners signaled a veto by throwing that according method. The VetoException can only reliably be evaluated in case the event listeners are executed in sequence.
      • hasObserverSubscription

        public boolean hasObserverSubscription​(O aObserver)
        Tests whether the given observer (event listener) has been added to this Observable.
        Specified by:
        hasObserverSubscription in interface Observable<O>
        Parameters:
        aObserver - The observer (event listener) for which to test if it has been added.
        Returns:
        True if the given observer (event listener) has been added already.
      • subscribeObserver

        public boolean subscribeObserver​(O aObserver)
        Adds the given observer (event listener). The observer (event listener) itself acts as the handle which is used when removing the given observer (event listener) later.
        Specified by:
        subscribeObserver in interface Observable<O>
        Parameters:
        aObserver - The observer (event listener) which is to be added to the Observable.
        Returns:
        True if the observer (event listener) has been added successfully. If the observer (event listener) has already been added, false is returned.
      • unsubscribeObserver

        public boolean unsubscribeObserver​(O aObserver)
        Removes the observer (event listener). In case the observer (event listener) has not been added before, then false is returned.
        Specified by:
        unsubscribeObserver in interface Observable<O>
        Parameters:
        aObserver - The observer (event listener) which is to be removed.
        Returns:
        True if the observer (event listener) has been removed successfully. If there was none such observer (event listener) or if the observer (event listener) has already been removed, then false is returned.
      • setObserversActive

        protected void setObserversActive​(boolean isActive)
      • isObserversActive

        protected boolean isObserversActive​()
      • observers

        protected java.util.Iterator<O> observers​()
      • fireEvent

        protected abstract boolean fireEvent​(EV aEvent,
                                             O aObserver,
                                             org.refcodes.controlflow.ExecutionStrategy aExecutionStrategy)
                                      throws java.lang.Exception
        This hook method is to be implemented by the implementing class. Here you decide which method of the event listener is to be invoked with the provided event and what actions apply upon invoking the event listener's methods. E.g. your event listener's methods might veto an event by throwing an according exception which you can pass down the stack here, or you might want to ignore any exceptions being thrown or you proceed according the the return value of some listener's method. Distribution of events to succeeding event listeners, in case of the SEQUENTIAL ExecutionStrategy, is prevented, when false is returned ("stop invoking succeeding event listeners"), succeeding event listeners are invoked in case true is returned ("continue invoking succeeding event listeners"). In CONCURRENT ExecutionStrategy the return value does not have an effect. Throwing a VetoException has a similar effect in case of the SEQUENTIAL ExecutionStrategy, preventing execution of succeeding event listeners and passing down the exception the stack so that your business logic can stop a vetoed operation.
        Parameters:
        aEvent - The event to be passed to the event listener
        aObserver - The event listener to which to pass the event
        aExecutionStrategy - Can be either CONCURRENT signaling that the event has been fired concurrently to the event listeners, each event listener is invoked in its own thread or SEQUENTIAL signaling that the event has been fired to the event listeners in sequence, each event listener is invoked one after the other one by one in the calling thread.
        Returns:
        True in case succeeding event listeners are to be invoked in case of the SEQUENTIAL ExecutionStrategy.
        Throws:
        org.refcodes.exception.VetoException - thrown in case an operation published by the given event has been vetoed by an event listener. Succeeding event listeners are not being invoked any more in case of the SEQUENTIAL ExecutionStrategy.
        java.lang.Exception
      • doHandleEventListenerException

        protected void doHandleEventListenerException​(java.lang.Exception aException,
                                                      O aObserver,
                                                      EV aEvent,
                                                      org.refcodes.controlflow.ExecutionStrategy aExecutionStrategy)
        This hook method allows you to handle any exceptions being thrown by an event listener whilst invoking a given event.
        Parameters:
        aException - The exception thrown by the given event listener.
        aObserver - The listener which caused the exception.
        aEvent - The event for which the exception was caused.
        aExecutionStrategy - the execution strategy
      • size

        protected int size​()
        Determines the number of observers being registered.
        Returns:
        The number of observers being registered.
      • isEmpty

        protected boolean isEmpty​()
        Determines whether there are observers being registered.
        Returns:
        True in case there are observers being registered.
      • getThreadPriority

        public int getThreadPriority​()
        In case of ExecutionStrategy.PARALLEL or ExecutionStrategy.JOIN, the threads' priority is defined by this attribute.
        Returns:
        The thread priority for the threads to be generated.
      • setThreadPriority

        public void setThreadPriority​(int threadPriority)
        In case of ExecutionStrategy.PARALLEL or ExecutionStrategy.JOIN, the threads' priority is defined by this attribute.
        Parameters:
        threadPriority - The thread priority for the threads to be generated.
      • dispose

        public void dispose​()
        Specified by:
        dispose in interface org.refcodes.mixin.Disposable