All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.refcodes.connection.ext.observable.ObservableConnectionRequestReceiverImpl Maven / Gradle / Ivy

Go to download

The refcodes-io-ext-observable artifact extends the refcodes-io artifact with a observable functionality.

There is a newer version: 2.0.5
Show newest version
// /////////////////////////////////////////////////////////////////////////////
// REFCODES.ORG
// =============================================================================
// This code is copyright (c) by Siegfried Steiner, Munich, Germany and licensed
// 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/LICENSE-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.connection.ext.observable;

import java.io.Serializable;
import java.util.concurrent.ExecutorService;

import org.refcodes.component.CloseException;
import org.refcodes.component.ConnectionStatus;
import org.refcodes.component.OpenException;
import org.refcodes.component.ext.observer.CloseEvent;
import org.refcodes.component.ext.observer.ClosedEvent;
import org.refcodes.component.ext.observer.ConnectionObserver.ConnectionRequestObserver;
import org.refcodes.component.ext.observer.OpenEvent;
import org.refcodes.component.ext.observer.OpenedEvent;
import org.refcodes.connection.ext.observable.ObservableConnectionReceiver.ObservableConnectionRequestReceiver;
import org.refcodes.controlflow.ExecutionStrategy;
import org.refcodes.exception.VetoException;
import org.refcodes.exception.VetoException.VetoRuntimeException;
import org.refcodes.io.ConnectionReceiver;
import org.refcodes.mixin.Loggable;
import org.refcodes.observer.AbstractObservable;
import org.refcodes.observer.ActionMetaDataEvent;
import org.refcodes.observer.EventMetaData;
import org.refcodes.observer.EventMetaDataImpl;
import org.refcodes.observer.GenericActionEvent;

/**
 * The {@link ObservableConnectionRequestReceiverImpl} implements the
 * {@link ObservableConnectionReceiver} for wrapping and extending a
 * {@link ConnectionReceiver} with observable functionality.
 * 

* TODO: Test cases are to be created! * * @param The type of the datagram to be operated with. * @param The type of the connection to be used. */ public class ObservableConnectionRequestReceiverImpl implements ObservableConnectionRequestReceiver, Loggable { // ///////////////////////////////////////////////////////////////////////// // CONSTANTS: // ///////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////// // VARIABLES: // ///////////////////////////////////////////////////////////////////////// private ConnectionReceiver _connectionReceiver; private ConnectionObservable _observable; private EventMetaData _eventMetaData; private Object _source; private boolean _isDestroyed = false; // ///////////////////////////////////////////////////////////////////////// // CONSTRUCTORS: // ///////////////////////////////////////////////////////////////////////// /** * Constructs a {@link ObservableConnectionRequestReceiverImpl} with the * given attributes. * * @param aConnectionReceiver The {@link ConnectionReceiver} to which the * connection method calls are to be delegated to. */ public ObservableConnectionRequestReceiverImpl( ConnectionReceiver aConnectionReceiver ) { _connectionReceiver = aConnectionReceiver; _eventMetaData = new EventMetaDataImpl( this.getClass() ); _source = this; _observable = new ConnectionObservable(); } /** * Constructs a {@link ObservableConnectionRequestReceiverImpl} with the * given attributes. * * @param aConnectionReceiver The {@link ConnectionReceiver} to which the * connection 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 ObservableConnectionRequestReceiverImpl( ConnectionReceiver aConnectionReceiver, Object aSource ) { _connectionReceiver = aConnectionReceiver; _eventMetaData = new EventMetaDataImpl( this.getClass() ); _source = aSource; _observable = new ConnectionObservable(); } /** * Constructs a {@link ObservableConnectionRequestReceiverImpl} with the * given attributes. * * @param aConnectionReceiver The {@link ConnectionReceiver} to which the * connection 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 ObservableConnectionRequestReceiverImpl( ConnectionReceiver aConnectionReceiver, EventMetaData aEventMetaData ) { _connectionReceiver = aConnectionReceiver; _eventMetaData = aEventMetaData; _source = this; _observable = new ConnectionObservable(); } /** * Constructs a {@link ObservableConnectionRequestReceiverImpl} with the * given attributes. * * @param aConnectionReceiver The {@link ConnectionReceiver} to which the * connection 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 ObservableConnectionRequestReceiverImpl( ConnectionReceiver aConnectionReceiver, EventMetaData aEventMetaData, Object aSource ) { _connectionReceiver = aConnectionReceiver; _eventMetaData = aEventMetaData; _source = aSource; _observable = new ConnectionObservable(); } // WITH EXECUTOR-SERVICE: /** * Constructs a {@link ObservableConnectionRequestReceiverImpl} with the * given attributes. * * @param aConnectionReceiver The {@link ConnectionReceiver} to which the * connection method calls are to be delegated to. * * @param aExecutorService The executor service to be used when firing * {@link GenericActionEvent} instances in multiple threads (if null * then a default one is used). * * @param aExecutionStrategy The {@link ExecutionStrategy} to be used when * firing {@link GenericActionEvent} instance (if null then the * default {@link ExecutionStrategy#SEQUENTIAL} is used). */ public ObservableConnectionRequestReceiverImpl( ConnectionReceiver aConnectionReceiver, ExecutorService aExecutorService, ExecutionStrategy aExecutionStrategy ) { _connectionReceiver = aConnectionReceiver; _eventMetaData = new EventMetaDataImpl( this.getClass() ); _source = this; _observable = new ConnectionObservable( aExecutorService, aExecutionStrategy ); } /** * Constructs a {@link ObservableConnectionRequestReceiverImpl} with the * given attributes. * * @param aConnectionReceiver The {@link ConnectionReceiver} to which the * connection 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 GenericActionEvent} instances in multiple threads (if null * then a default one is used). * * @param aExecutionStrategy The {@link ExecutionStrategy} to be used when * firing {@link GenericActionEvent} instance (if null then the * default {@link ExecutionStrategy#SEQUENTIAL} is used). */ public ObservableConnectionRequestReceiverImpl( ConnectionReceiver aConnectionReceiver, Object aSource, ExecutorService aExecutorService, ExecutionStrategy aExecutionStrategy ) { _connectionReceiver = aConnectionReceiver; _eventMetaData = new EventMetaDataImpl( this.getClass() ); _source = aSource; _observable = new ConnectionObservable( aExecutorService, aExecutionStrategy ); } /** * Constructs a {@link ObservableConnectionRequestReceiverImpl} with the * given attributes. * * @param aConnectionReceiver The {@link ConnectionReceiver} to which the * connection 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 GenericActionEvent} instances in multiple threads (if null * then a default one is used). * * @param aExecutionStrategy The {@link ExecutionStrategy} to be used when * firing {@link GenericActionEvent} instance (if null then the * default {@link ExecutionStrategy#SEQUENTIAL} is used). */ public ObservableConnectionRequestReceiverImpl( ConnectionReceiver aConnectionReceiver, EventMetaData aEventMetaData, ExecutorService aExecutorService, ExecutionStrategy aExecutionStrategy ) { _connectionReceiver = aConnectionReceiver; _eventMetaData = aEventMetaData; _source = this; _observable = new ConnectionObservable( aExecutorService, aExecutionStrategy ); } /** * Constructs a {@link ObservableConnectionRequestReceiverImpl} with the * given attributes. * * @param aConnectionReceiver The {@link ConnectionReceiver} to which the * connection 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 GenericActionEvent} instances in multiple threads (if null * then a default one is used). * * @param aExecutionStrategy The {@link ExecutionStrategy} to be used when * firing {@link GenericActionEvent} instance (if null then the * default {@link ExecutionStrategy#SEQUENTIAL} is used). */ public ObservableConnectionRequestReceiverImpl( ConnectionReceiver aConnectionReceiver, EventMetaData aEventMetaData, Object aSource, ExecutorService aExecutorService, ExecutionStrategy aExecutionStrategy ) { _connectionReceiver = aConnectionReceiver; _eventMetaData = aEventMetaData; _source = aSource; _observable = new ConnectionObservable( aExecutorService, aExecutionStrategy ); } // ///////////////////////////////////////////////////////////////////////// // METHODS: // ///////////////////////////////////////////////////////////////////////// /** * {@inheritDoc} */ @Override public boolean isClosed() { return _connectionReceiver.isClosed(); } /** * {@inheritDoc} */ @Override public boolean isOpened() { return _connectionReceiver.isOpened(); } /** * {@inheritDoc} */ @Override public ConnectionStatus getConnectionStatus() { return _connectionReceiver.getConnectionStatus(); } /** * {@inheritDoc} */ @Override public void releaseAll() { _connectionReceiver.releaseAll(); } /** * {@inheritDoc} */ @Override public void close() throws CloseException { try { _observable.fireEvent( new CloseEvent( _eventMetaData, _source ) ); } catch ( VetoException aException ) { throw new VetoRuntimeException( aException ); } _connectionReceiver.close(); try { _observable.fireEvent( new ClosedEvent( _eventMetaData, _source ) ); } catch ( VetoException ignore ) { /* Cannot happen here */ } } /** * {@inheritDoc} */ @Override public void open( CON aConnection ) throws OpenException { try { _observable.fireEvent( new OpenEvent( _eventMetaData, _source ) ); } catch ( VetoException aException ) { throw new OpenException( aException ); } _connectionReceiver.open( aConnection ); try { _observable.fireEvent( new OpenedEvent( _eventMetaData, _source ) ); } catch ( VetoException e ) { /* Cannot happen here */ } } /** * {@inheritDoc} */ @Override public DATA readDatagram() throws OpenException, InterruptedException { return _connectionReceiver.readDatagram(); } /** * {@inheritDoc} */ @Override public boolean isClosable() { return _connectionReceiver.isClosable(); } /** * {@inheritDoc} */ @Override public boolean isOpenable( CON aConnection ) { return _connectionReceiver.isOpenable( aConnection ); } /** * {@inheritDoc} */ @Override public boolean hasDatagram() throws OpenException { return _connectionReceiver.hasDatagram(); } // ///////////////////////////////////////////////////////////////////////// // OBSERVERS: // ///////////////////////////////////////////////////////////////////////// /** * {@inheritDoc} */ @Override public boolean hasObserverSubscription( ConnectionRequestObserver aObserver ) { return _observable.hasObserverSubscription( aObserver ); } /** * {@inheritDoc} */ @Override public boolean subscribeObserver( ConnectionRequestObserver aObserver ) { return _observable.subscribeObserver( aObserver ); } /** * {@inheritDoc} */ @Override public boolean unsubscribeObserver( ConnectionRequestObserver aObserver ) { return _observable.unsubscribeObserver( aObserver ); } // ///////////////////////////////////////////////////////////////////////// // COMPONENT: // ///////////////////////////////////////////////////////////////////////// /** * {@inheritDoc} */ @Override public void destroy() { if ( !_isDestroyed ) { _isDestroyed = true; try { close(); } catch ( CloseException e ) { warn( "Unable to close malfunctioning connection.", e ); } _connectionReceiver = null; _observable.clear(); _observable = null; _source = null; _eventMetaData = null; } } // ///////////////////////////////////////////////////////////////////////// // HOOKS: // ///////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////// // HELPER: // ///////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////// // INNER CLASSES: // ///////////////////////////////////////////////////////////////////////// /** * The {@link ConnectionObservable} extends the {@link AbstractObservable} * to make the using class {@link GenericActionEvent} aware. */ private class ConnectionObservable extends AbstractObservable { // ///////////////////////////////////////////////////////////////////// // VARIABLES: // ///////////////////////////////////////////////////////////////////// private ExecutionStrategy _executionStrategy; // ///////////////////////////////////////////////////////////////////// // CONSTRUCTORS: // ///////////////////////////////////////////////////////////////////// /** * Instantiates a new connection observable. */ public ConnectionObservable() { super(); _executionStrategy = ExecutionStrategy.SEQUENTIAL; } /** * Instantiates a new connection observable. * * @param aExecutorService the executor service * @param aExecutionStrategy the execution strategy */ public ConnectionObservable( 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: // ///////////////////////////////////////////////////////////////////// /** * Same as {@link #fireEvent(MetaDataEvent, ExecutionStrategy)} with * a predefined {@link ExecutionStrategy#JOIN}. * * @param aEvent the event * @return true, if successful * @throws VetoException the veto exception * @see #fireEvent(MetaDataEvent, ExecutionStrategy) */ protected boolean fireEvent( ActionMetaDataEvent aEvent ) throws VetoException { return super.fireEvent( aEvent, _executionStrategy ); } /** * {@inheritDoc} */ @Override protected boolean fireEvent( ActionMetaDataEvent aEvent, ConnectionRequestObserver aObserver, ExecutionStrategy aExecutionStrategy ) throws VetoException { if ( aEvent instanceof OpenEvent ) { aObserver.onOpenEvent( (OpenEvent) aEvent ); } else if ( aEvent instanceof CloseEvent ) { aObserver.onCloseEvent( (CloseEvent) aEvent ); } else if ( aEvent instanceof OpenedEvent ) { aObserver.onOpendEvent( (OpenedEvent) aEvent ); } else if ( aEvent instanceof ClosedEvent ) { aObserver.onClosedEvent( (ClosedEvent) aEvent ); } aObserver.onEvent( aEvent ); return true; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy