org.refcodes.component.ext.observer.ObservableLifecycleRequestMachine Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of refcodes-component-ext-observer Show documentation
Show all versions of refcodes-component-ext-observer Show documentation
Artifact for providing event based extended functionality for the
refcodes-component artifact.
// /////////////////////////////////////////////////////////////////////////////
// REFCODES.ORG
// =============================================================================
// This code is copyright (c) by Siegfried Steiner, Munich, Germany, distributed
// on an "AS IS" BASIS WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, and licen-
// sed under the following (see "http://en.wikipedia.org/wiki/Multi-licensing")
// licenses:
// =============================================================================
// GNU General Public License, v3.0 ("http://www.gnu.org/licenses/gpl-3.0.html")
// together with the GPL linking exception applied; as being applied by the GNU
// Classpath ("http://www.gnu.org/software/classpath/license.html")
// =============================================================================
// Apache License, v2.0 ("http://www.apache.org/licenses/TEXT-2.0")
// =============================================================================
// Please contact the copyright holding author(s) of the software artifacts in
// question for licensing issues not being covered by the above listed licenses,
// also regarding commercial licensing models or regarding the compatibility
// with other open source licenses.
// /////////////////////////////////////////////////////////////////////////////
package org.refcodes.component.ext.observer;
import java.lang.reflect.Field;
import java.util.concurrent.ExecutorService;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.refcodes.component.InitializeException;
import org.refcodes.component.LifecycleComponent;
import org.refcodes.component.LifecycleMachine;
import org.refcodes.component.LifecycleRequest;
import org.refcodes.component.LifecycleStatus;
import org.refcodes.component.PauseException;
import org.refcodes.component.ResumeException;
import org.refcodes.component.StartException;
import org.refcodes.component.StopException;
import org.refcodes.controlflow.ExecutionStrategy;
import org.refcodes.exception.VetoException;
import org.refcodes.observer.AbstractObservable;
import org.refcodes.observer.ActionEvent;
import org.refcodes.observer.EventMetaData;
import org.refcodes.observer.Observable;
/**
* The {@link ObservableLifecycleRequestMachine} extends the
* {@link LifecycleMachine} with request {@link ActionEvent} functionality which
* can be vetoed. The implementation is suffixed with "Machine" instead of
* "Automaton" for differentiation with any interface of similar (same) name.
*
* @param The source of the events consumed by the
* {@link LifecycleRequestObserver}.
*/
public class ObservableLifecycleRequestMachine extends LifecycleMachine implements Observable, StartRequestedEvent, ResumeRequestedEvent, PauseRequestedEvent, StopRequestedEvent, DestroyRequestedEvent, EventMetaData, SRC>> {
// /////////////////////////////////////////////////////////////////////////
// STATICS:
// /////////////////////////////////////////////////////////////////////////
private static final Logger LOGGER = Logger.getLogger( ObservableLifecycleRequestMachine.class.getName() );
// /////////////////////////////////////////////////////////////////////////
// VARIABLES:
// /////////////////////////////////////////////////////////////////////////
private LifecycleRequestObservable _observable;
private EventMetaData _eventMetaData;
private SRC _source;
// /////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS:
// /////////////////////////////////////////////////////////////////////////
/**
* Instantiates a new {@link ObservableLifecycleRequestMachine}.
*/
public ObservableLifecycleRequestMachine() {
_eventMetaData = new EventMetaData();
_observable = new LifecycleRequestObservable();
_source = toSource();
}
/**
* Instantiates a new {@link ObservableLifecycleRequestMachine}.
*
* @param aSource The source instance to be used when firing events in case
* the source is to be different from this class' instance.
*/
public ObservableLifecycleRequestMachine( SRC aSource ) {
_eventMetaData = new EventMetaData();
_observable = new LifecycleRequestObservable();
_source = aSource;
}
/**
* Instantiates a new {@link ObservableLifecycleRequestMachine}.
* {@inheritDoc}
*
* @param aEventMetaData The {@link EventMetaData} to be used when firing
* events in case the {@link EventMetaData} is to be different from
* the auto-generated {@link EventMetaData}.
*/
public ObservableLifecycleRequestMachine( EventMetaData aEventMetaData ) {
_eventMetaData = aEventMetaData;
_observable = new LifecycleRequestObservable();
_source = toSource();
}
/**
* Instantiates a new {@link ObservableLifecycleRequestMachine}.
*
* @param aEventMetaData The {@link EventMetaData} to be used when firing
* events in case the {@link EventMetaData} is to be different from
* the auto-generated {@link EventMetaData}.
* @param aSource The source instance to be used when firing events in case
* the source is to be different from this class' instance.
*/
public ObservableLifecycleRequestMachine( EventMetaData aEventMetaData, SRC aSource ) {
_eventMetaData = aEventMetaData;
_observable = new LifecycleRequestObservable();
_source = aSource;
}
/**
* {@inheritDoc}
*
* @param aLifecycleComponent The {@link LifecycleComponent} to which the
* life-cycle method calls are to be delegated to.
*/
public ObservableLifecycleRequestMachine( LifecycleComponent aLifecycleComponent ) {
super( aLifecycleComponent );
_eventMetaData = new EventMetaData( this.getClass() );
_source = toSource();
_observable = new LifecycleRequestObservable();
}
/**
* {@inheritDoc}
*
* @param aLifecycleComponent The {@link LifecycleComponent} to which the
* life-cycle method calls are to be delegated to.
* @param aSource The source instance to be used when firing events in case
* the source is to be different from this class' instance.
*/
public ObservableLifecycleRequestMachine( LifecycleComponent aLifecycleComponent, SRC aSource ) {
super( aLifecycleComponent );
_eventMetaData = new EventMetaData( this.getClass() );
_source = aSource;
_observable = new LifecycleRequestObservable();
}
/**
* {@inheritDoc}
*
* @param aLifecycleComponent The {@link LifecycleComponent} to which the
* life-cycle method calls are to be delegated to.
* @param aEventMetaData The {@link EventMetaData} to be used when firing
* events in case the {@link EventMetaData} is to be different from
* the auto-generated {@link EventMetaData}.
*/
public ObservableLifecycleRequestMachine( LifecycleComponent aLifecycleComponent, EventMetaData aEventMetaData ) {
super( aLifecycleComponent );
_eventMetaData = aEventMetaData;
_source = toSource();
_observable = new LifecycleRequestObservable();
}
/**
* {@inheritDoc}
*
* @param aLifecycleComponent The {@link LifecycleComponent} to which the
* life-cycle method calls are to be delegated to.
* @param aEventMetaData The {@link EventMetaData} to be used when firing
* events in case the {@link EventMetaData} is to be different from
* the auto-generated {@link EventMetaData}.
* @param aSource The source instance to be used when firing events in case
* the source is to be different from this class' instance.
*/
public ObservableLifecycleRequestMachine( LifecycleComponent aLifecycleComponent, EventMetaData aEventMetaData, SRC aSource ) {
super( aLifecycleComponent );
_eventMetaData = aEventMetaData;
_source = aSource;
_observable = new LifecycleRequestObservable();
}
/**
* {@inheritDoc}
*
* @param aExecutorService The executor service to be used when firing
* {@link ActionEvent} instances in multiple threads (if null then a
* default one is used).
* @param aExecutionStrategy The {@link ExecutionStrategy} to be used when
* firing {@link ActionEvent} instance (if null then the default
* {@link ExecutionStrategy#SEQUENTIAL} is used).
*/
public ObservableLifecycleRequestMachine( ExecutorService aExecutorService, ExecutionStrategy aExecutionStrategy ) {
_eventMetaData = new EventMetaData();
_source = toSource();
_observable = new LifecycleRequestObservable( aExecutorService, aExecutionStrategy );
}
/**
* {@inheritDoc}
*
* @param aSource The source instance to be used when firing events in case
* the source is to be different from this class' instance.
* @param aExecutorService The executor service to be used when firing
* {@link ActionEvent} instances in multiple threads (if null then a
* default one is used).
* @param aExecutionStrategy The {@link ExecutionStrategy} to be used when
* firing {@link ActionEvent} instance (if null then the default
* {@link ExecutionStrategy#SEQUENTIAL} is used).
*/
public ObservableLifecycleRequestMachine( SRC aSource, ExecutorService aExecutorService, ExecutionStrategy aExecutionStrategy ) {
_eventMetaData = new EventMetaData();
_source = aSource;
_observable = new LifecycleRequestObservable( aExecutorService, aExecutionStrategy );
}
/**
* {@inheritDoc}
*
* @param aEventMetaData The {@link EventMetaData} to be used when firing
* events in case the {@link EventMetaData} is to be different from
* the auto-generated {@link EventMetaData}.
* @param aExecutorService The executor service to be used when firing
* {@link ActionEvent} instances in multiple threads (if null then a
* default one is used).
* @param aExecutionStrategy The {@link ExecutionStrategy} to be used when
* firing {@link ActionEvent} instance (if null then the default
* {@link ExecutionStrategy#SEQUENTIAL} is used).
*/
public ObservableLifecycleRequestMachine( EventMetaData aEventMetaData, ExecutorService aExecutorService, ExecutionStrategy aExecutionStrategy ) {
_eventMetaData = aEventMetaData;
_source = toSource();
_observable = new LifecycleRequestObservable( aExecutorService, aExecutionStrategy );
}
/**
* {@inheritDoc}
*
* @param aEventMetaData The {@link EventMetaData} to be used when firing
* events in case the {@link EventMetaData} is to be different from
* the auto-generated {@link EventMetaData}.
* @param aSource The source instance to be used when firing events in case
* the source is to be different from this class' instance.
* @param aExecutorService The executor service to be used when firing
* {@link ActionEvent} instances in multiple threads (if null then a
* default one is used).
* @param aExecutionStrategy The {@link ExecutionStrategy} to be used when
* firing {@link ActionEvent} instance (if null then the default
* {@link ExecutionStrategy#SEQUENTIAL} is used).
*/
public ObservableLifecycleRequestMachine( EventMetaData aEventMetaData, SRC aSource, ExecutorService aExecutorService, ExecutionStrategy aExecutionStrategy ) {
_eventMetaData = aEventMetaData;
_source = aSource;
_observable = new LifecycleRequestObservable( aExecutorService, aExecutionStrategy );
}
/**
* {@inheritDoc}
*
* @param aLifecycleComponent The {@link LifecycleComponent} to which the
* life-cycle method calls are to be delegated to.
* @param aExecutorService The executor service to be used when firing
* {@link ActionEvent} instances in multiple threads (if null then a
* default one is used).
* @param aExecutionStrategy The {@link ExecutionStrategy} to be used when
* firing {@link ActionEvent} instance (if null then the default
* {@link ExecutionStrategy#SEQUENTIAL} is used).
*/
public ObservableLifecycleRequestMachine( LifecycleComponent aLifecycleComponent, ExecutorService aExecutorService, ExecutionStrategy aExecutionStrategy ) {
super( aLifecycleComponent );
_eventMetaData = new EventMetaData( this.getClass() );
_source = toSource();
_observable = new LifecycleRequestObservable( aExecutorService, aExecutionStrategy );
}
/**
* {@inheritDoc}
*
* @param aLifecycleComponent The {@link LifecycleComponent} to which the
* life-cycle method calls are to be delegated to.
* @param aSource The source instance to be used when firing events in case
* the source is to be different from this class' instance.
* @param aExecutorService The executor service to be used when firing
* {@link ActionEvent} instances in multiple threads (if null then a
* default one is used).
* @param aExecutionStrategy The {@link ExecutionStrategy} to be used when
* firing {@link ActionEvent} instance (if null then the default
* {@link ExecutionStrategy#SEQUENTIAL} is used).
*/
public ObservableLifecycleRequestMachine( LifecycleComponent aLifecycleComponent, SRC aSource, ExecutorService aExecutorService, ExecutionStrategy aExecutionStrategy ) {
super( aLifecycleComponent );
_eventMetaData = new EventMetaData( this.getClass() );
_source = aSource;
_observable = new LifecycleRequestObservable( aExecutorService, aExecutionStrategy );
}
/**
* {@inheritDoc}
*
* @param aLifecycleComponent The {@link LifecycleComponent} to which the
* life-cycle method calls are to be delegated to.
* @param aEventMetaData The {@link EventMetaData} to be used when firing
* events in case the {@link EventMetaData} is to be different from
* the auto-generated {@link EventMetaData}.
* @param aExecutorService The executor service to be used when firing
* {@link ActionEvent} instances in multiple threads (if null then a
* default one is used).
* @param aExecutionStrategy The {@link ExecutionStrategy} to be used when
* firing {@link ActionEvent} instance (if null then the default
* {@link ExecutionStrategy#SEQUENTIAL} is used).
*/
public ObservableLifecycleRequestMachine( LifecycleComponent aLifecycleComponent, EventMetaData aEventMetaData, ExecutorService aExecutorService, ExecutionStrategy aExecutionStrategy ) {
super( aLifecycleComponent );
_eventMetaData = aEventMetaData;
_source = toSource();
_observable = new LifecycleRequestObservable( aExecutorService, aExecutionStrategy );
}
/**
* {@inheritDoc}
*
* @param aLifecycleComponent The {@link LifecycleComponent} to which the
* life-cycle method calls are to be delegated to.
* @param aEventMetaData The {@link EventMetaData} to be used when firing
* events in case the {@link EventMetaData} is to be different from
* the auto-generated {@link EventMetaData}.
* @param aSource The source instance to be used when firing events in case
* the source is to be different from this class' instance.
* @param aExecutorService The executor service to be used when firing
* {@link ActionEvent} instances in multiple threads (if null then a
* default one is used).
* @param aExecutionStrategy The {@link ExecutionStrategy} to be used when
* firing {@link ActionEvent} instance (if null then the default
* {@link ExecutionStrategy#SEQUENTIAL} is used).
*/
public ObservableLifecycleRequestMachine( LifecycleComponent aLifecycleComponent, EventMetaData aEventMetaData, SRC aSource, ExecutorService aExecutorService, ExecutionStrategy aExecutionStrategy ) {
super( aLifecycleComponent );
_eventMetaData = aEventMetaData;
_source = aSource;
_observable = new LifecycleRequestObservable( aExecutorService, aExecutionStrategy );
}
// /////////////////////////////////////////////////////////////////////////
// OBSERVERS:
// /////////////////////////////////////////////////////////////////////////
/**
* {@inheritDoc}
*/
@Override
public boolean hasObserver( LifecycleRequestObserver, StartRequestedEvent, ResumeRequestedEvent, PauseRequestedEvent, StopRequestedEvent, DestroyRequestedEvent, EventMetaData, SRC> aObserver ) {
return _observable.hasObserver( aObserver );
}
/**
* {@inheritDoc}
*/
@Override
public boolean subscribeObserver( LifecycleRequestObserver, StartRequestedEvent, ResumeRequestedEvent, PauseRequestedEvent, StopRequestedEvent, DestroyRequestedEvent, EventMetaData, SRC> aObserver ) {
return _observable.subscribeObserver( aObserver );
}
/**
* {@inheritDoc}
*/
@Override
public boolean unsubscribeObserver( LifecycleRequestObserver, StartRequestedEvent, ResumeRequestedEvent, PauseRequestedEvent, StopRequestedEvent, DestroyRequestedEvent, EventMetaData, SRC> aObserver ) {
return _observable.unsubscribeObserver( aObserver );
}
// /////////////////////////////////////////////////////////////////////////
// LIFE-CYCLE:
// /////////////////////////////////////////////////////////////////////////
/**
* {@inheritDoc}
*/
@Override
public synchronized void initialize() throws InitializeException {
LOGGER.log( Level.INFO, "About to " + LifecycleRequest.INITIALIZE + " component \"" + ( ( getLifecycleComponent() != null ) ? ( getLifecycleComponent().getClass().getName() ) : ( getClass().getName() ) ) + "\" ..." );
if ( _observable != null ) {
try {
_observable.fireEvent( new InitializeEvent<>( _eventMetaData, _source ) );
}
catch ( VetoException e ) {
throw new InitializeException( e );
}
}
super.initialize();
LOGGER.log( Level.INFO, "Component \"" + ( ( getLifecycleComponent() != null ) ? ( getLifecycleComponent().getClass().getName() ) : ( getClass().getName() ) ) + "\" is " + LifecycleStatus.INITIALIZED + "." );
}
/**
* {@inheritDoc}
*/
@Override
public synchronized void start() throws StartException {
LOGGER.log( Level.INFO, "About to " + LifecycleRequest.START + " component \"" + ( ( getLifecycleComponent() != null ) ? ( getLifecycleComponent().getClass().getName() ) : ( getClass().getName() ) ) + "\" ..." );
if ( _observable != null ) {
try {
_observable.fireEvent( new StartEvent<>( _eventMetaData, _source ) );
}
catch ( VetoException e ) {
throw new StartException( e );
}
}
super.start();
LOGGER.log( Level.INFO, "Component \"" + ( ( getLifecycleComponent() != null ) ? ( getLifecycleComponent().getClass().getName() ) : ( getClass().getName() ) ) + "\" is " + LifecycleStatus.STARTED + "." );
}
/**
* {@inheritDoc}
*/
@Override
public synchronized void pause() throws PauseException {
LOGGER.log( Level.INFO, "About to " + LifecycleRequest.PAUSE + " component \"" + ( ( getLifecycleComponent() != null ) ? ( getLifecycleComponent().getClass().getName() ) : ( getClass().getName() ) ) + "\" ..." );
if ( _observable != null ) {
try {
_observable.fireEvent( new PauseEvent<>( _eventMetaData, _source ) );
}
catch ( VetoException e ) {
throw new PauseException( e );
}
}
super.pause();
LOGGER.log( Level.INFO, "Component \"" + ( ( getLifecycleComponent() != null ) ? ( getLifecycleComponent().getClass().getName() ) : ( getClass().getName() ) ) + "\" is " + LifecycleStatus.PAUSED + "." );
}
/**
* {@inheritDoc}
*/
@Override
public synchronized void resume() throws ResumeException {
LOGGER.log( Level.INFO, "About to " + LifecycleRequest.RESUME + " component \"" + ( ( getLifecycleComponent() != null ) ? ( getLifecycleComponent().getClass().getName() ) : ( getClass().getName() ) ) + "\" ..." );
if ( _observable != null ) {
try {
_observable.fireEvent( new ResumeEvent<>( _eventMetaData, _source ) );
}
catch ( VetoException e ) {
throw new ResumeException( e );
}
}
super.resume();
LOGGER.log( Level.INFO, "Component \"" + ( ( getLifecycleComponent() != null ) ? ( getLifecycleComponent().getClass().getName() ) : ( getClass().getName() ) ) + "\" is " + LifecycleStatus.STARTED + "." );
}
/**
* {@inheritDoc}
*/
@Override
public synchronized void stop() throws StopException {
LOGGER.log( Level.INFO, "About to " + LifecycleRequest.STOP + " component \"" + ( ( getLifecycleComponent() != null ) ? ( getLifecycleComponent().getClass().getName() ) : ( getClass().getName() ) ) + "\" ..." );
if ( _observable != null ) {
try {
_observable.fireEvent( new StopEvent<>( _eventMetaData, _source ) );
}
catch ( VetoException e ) {
throw new StopException( e );
}
}
super.stop();
LOGGER.log( Level.INFO, "Component \"" + ( ( getLifecycleComponent() != null ) ? ( getLifecycleComponent().getClass().getName() ) : ( getClass().getName() ) ) + "\" is " + LifecycleStatus.STOPPED + "." );
}
/**
* {@inheritDoc}
*/
@Override
public synchronized void destroy() {
LOGGER.log( Level.INFO, "About to " + LifecycleRequest.DESTROY + " component \"" + ( ( getLifecycleComponent() != null ) ? ( getLifecycleComponent().getClass().getName() ) : ( getClass().getName() ) ) + "\" ..." );
if ( _observable != null ) {
try {
_observable.fireEvent( new DestroyEvent<>( _eventMetaData, _source ) );
}
catch ( VetoException ignore ) {
/* Cannot happen here */
}
}
super.destroy();
_observable.clear();
_observable = null;
_source = null;
_eventMetaData = null;
LOGGER.log( Level.INFO, "Component \"" + ( ( getLifecycleComponent() != null ) ? ( getLifecycleComponent().getClass().getName() ) : ( getClass().getName() ) ) + "\" is " + LifecycleStatus.DESTROYED + "." );
}
// /////////////////////////////////////////////////////////////////////////
// HELPER:
// /////////////////////////////////////////////////////////////////////////
@SuppressWarnings("unchecked")
private SRC toSource() {
try {
final Field theField = getClass().getField( "_source" );
if ( theField.getGenericType() instanceof Class> theClass ) {
return theClass.isAssignableFrom( getClass() ) ? (SRC) this : null;
}
}
catch ( Exception ignore ) { /* ignore */ }
return null;
}
// /////////////////////////////////////////////////////////////////////////
// INNER CLASSES:
// /////////////////////////////////////////////////////////////////////////
/**
* Implementation of the {@link AbstractObservable} for event distribution.
*/
private class LifecycleRequestObservable extends AbstractObservable, StartRequestedEvent, ResumeRequestedEvent, PauseRequestedEvent, StopRequestedEvent, DestroyRequestedEvent, EventMetaData, SRC>, LifecycleRequestEvent> {
// /////////////////////////////////////////////////////////////////////
// VARIABLES:
// /////////////////////////////////////////////////////////////////////
private final ExecutionStrategy _executionStrategy;
// /////////////////////////////////////////////////////////////////////
// CONSTRUCTORS:
// /////////////////////////////////////////////////////////////////////
/**
* Instantiates a new life cycle observable.
*/
public LifecycleRequestObservable() {
_executionStrategy = ExecutionStrategy.SEQUENTIAL;
}
/**
* Instantiates a new life cycle observable.
*
* @param aExecutorService the executor service
* @param aExecutionStrategy the execution strategy
*/
public LifecycleRequestObservable( ExecutorService aExecutorService, ExecutionStrategy aExecutionStrategy ) {
super( aExecutorService );
_executionStrategy = ( aExecutionStrategy != null ) ? aExecutionStrategy : ExecutionStrategy.SEQUENTIAL;
}
// /////////////////////////////////////////////////////////////////////
// METHODS:
// /////////////////////////////////////////////////////////////////////
/**
* {@inheritDoc}
*/
@Override
public int size() {
return super.size();
}
/**
* {@inheritDoc}
*/
@Override
public boolean isEmpty() {
return super.isEmpty();
}
/**
* {@inheritDoc}
*/
@Override
public void clear() {
super.clear();
}
// /////////////////////////////////////////////////////////////////////
// HOOKS:
// /////////////////////////////////////////////////////////////////////
/**
* {@inheritDoc}
*/
@Override
protected boolean fireEvent( LifecycleRequestEvent aEvent, LifecycleRequestObserver, StartRequestedEvent, ResumeRequestedEvent, PauseRequestedEvent, StopRequestedEvent, DestroyRequestedEvent, EventMetaData, SRC> aEventListener, ExecutionStrategy aEventExecutionStrategy ) throws Exception {
if ( aEvent instanceof InitializeEvent ) {
aEventListener.onInitialize( (InitializeEvent) aEvent );
}
else if ( aEvent instanceof StartEvent ) {
aEventListener.onStart( (StartEvent) aEvent );
}
else if ( aEvent instanceof PauseEvent ) {
aEventListener.onPause( (PauseEvent) aEvent );
}
else if ( aEvent instanceof ResumeEvent ) {
aEventListener.onResume( (ResumeEvent) aEvent );
}
else if ( aEvent instanceof StopEvent ) {
aEventListener.onStop( (StopEvent) aEvent );
}
else if ( aEvent instanceof DestroyEvent ) {
aEventListener.onDestroy( (DestroyEvent) aEvent );
}
return true;
}
/**
* Fires the according event.
*
* @param aEvent The {@link ActionEvent} to be fired.
*
* @return true, if successful
*
* @throws VetoException Thrown in case of a veto.
*/
protected boolean fireEvent( LifecycleRequestEvent aEvent ) throws VetoException {
return super.fireEvent( aEvent, _executionStrategy );
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy