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

org.refcodes.connection.ext.observable.impls.ObservableConnectionReceiverImpl 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.impls;

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.ClosedEvent;
import org.refcodes.component.ext.observer.ConnectionObserver;
import org.refcodes.component.ext.observer.OpenedEvent;
import org.refcodes.component.ext.observer.impls.ClosedEventImpl;
import org.refcodes.component.ext.observer.impls.OpenedEventImpl;
import org.refcodes.connection.ext.observable.ObservableConnectionReceiver;
import org.refcodes.controlflow.ExecutionStrategy;
import org.refcodes.exception.VetoException;
import org.refcodes.io.ConnectionReceiver;
import org.refcodes.logger.RuntimeLogger;
import org.refcodes.logger.impls.RuntimeLoggerSingleton;
import org.refcodes.observer.ActionEvent;
import org.refcodes.observer.EventMetaData;
import org.refcodes.observer.MetaDataEvent;
import org.refcodes.observer.impls.AbstractObservable;
import org.refcodes.observer.impls.EventMetaDataImpl;

/**
 * The {@link ObservableConnectionReceiverImpl} 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 ObservableConnectionReceiverImpl implements ObservableConnectionReceiver { protected static RuntimeLogger LOGGER = RuntimeLoggerSingleton.getInstance(); // ///////////////////////////////////////////////////////////////////////// // CONSTANTS: // ///////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////// // VARIABLES: // ///////////////////////////////////////////////////////////////////////// private ConnectionReceiver _connectionReceiver; private ConnectionObservable _observable; private EventMetaData _eventMetaData; private Object _source; private boolean _isDestroyed = false; // ///////////////////////////////////////////////////////////////////////// // CONSTRUCTORS: // ///////////////////////////////////////////////////////////////////////// /** * Constructs a {@link ObservableConnectionReceiverImpl} with the given * attributes. * * @param aConnectionReceiver The {@link ConnectionReceiver} to which the * connection method calls are to be delegated to. */ public ObservableConnectionReceiverImpl( ConnectionReceiver aConnectionReceiver ) { _connectionReceiver = aConnectionReceiver; _eventMetaData = new EventMetaDataImpl( this.getClass() ); _source = this; _observable = new ConnectionObservable(); } /** * Constructs a {@link ObservableConnectionReceiverImpl} 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 ObservableConnectionReceiverImpl( ConnectionReceiver aConnectionReceiver, Object aSource ) { _connectionReceiver = aConnectionReceiver; _eventMetaData = new EventMetaDataImpl( this.getClass() ); _source = aSource; _observable = new ConnectionObservable(); } /** * Constructs a {@link ObservableConnectionReceiverImpl} 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 ObservableConnectionReceiverImpl( ConnectionReceiver aConnectionReceiver, EventMetaData aEventMetaData ) { _connectionReceiver = aConnectionReceiver; _eventMetaData = aEventMetaData; _source = this; _observable = new ConnectionObservable(); } /** * Constructs a {@link ObservableConnectionReceiverImpl} 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 ObservableConnectionReceiverImpl( ConnectionReceiver aConnectionReceiver, EventMetaData aEventMetaData, Object aSource ) { _connectionReceiver = aConnectionReceiver; _eventMetaData = aEventMetaData; _source = aSource; _observable = new ConnectionObservable(); } // WITH EXECUTOR-SERVICE: /** * Constructs a {@link ObservableConnectionReceiverImpl} 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 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 ObservableConnectionReceiverImpl( ConnectionReceiver aConnectionReceiver, ExecutorService aExecutorService, ExecutionStrategy aExecutionStrategy ) { _connectionReceiver = aConnectionReceiver; _eventMetaData = new EventMetaDataImpl( this.getClass() ); _source = this; _observable = new ConnectionObservable( aExecutorService, aExecutionStrategy ); } /** * Constructs a {@link ObservableConnectionReceiverImpl} 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 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 ObservableConnectionReceiverImpl( 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 ObservableConnectionReceiverImpl} 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 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 ObservableConnectionReceiverImpl( ConnectionReceiver aConnectionReceiver, EventMetaData aEventMetaData, ExecutorService aExecutorService, ExecutionStrategy aExecutionStrategy ) { _connectionReceiver = aConnectionReceiver; _eventMetaData = aEventMetaData; _source = this; _observable = new ConnectionObservable( aExecutorService, aExecutionStrategy ); } /** * Constructs a {@link ObservableConnectionReceiverImpl} 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 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 ObservableConnectionReceiverImpl( ConnectionReceiver aConnectionReceiver, EventMetaData aEventMetaData, Object aSource, ExecutorService aExecutorService, ExecutionStrategy aExecutionStrategy ) { _connectionReceiver = aConnectionReceiver; _eventMetaData = aEventMetaData; _source = aSource; _observable = new ConnectionObservable( aExecutorService, aExecutionStrategy ); } // ///////////////////////////////////////////////////////////////////////// // METHODS: // ///////////////////////////////////////////////////////////////////////// @Override public boolean isClosed() { return _connectionReceiver.isClosed(); } @Override public boolean isOpened() { return _connectionReceiver.isOpened(); } @Override public ConnectionStatus getConnectionStatus() { return _connectionReceiver.getConnectionStatus(); } @Override public void releaseAll() { _connectionReceiver.releaseAll(); } @Override public void close() throws CloseException { _connectionReceiver.close(); try { _observable.fireEvent( new ClosedEventImpl( _eventMetaData, _source ) ); } catch ( VetoException e ) { /* Cannot happen here */ } } @Override public void open( CON aConnection ) throws OpenException { _connectionReceiver.open( aConnection ); try { _observable.fireEvent( new OpenedEventImpl( _eventMetaData, _source ) ); } catch ( VetoException e ) { /* Cannot happen here */ } } @Override public DATA readDatagram() throws OpenException, InterruptedException { return _connectionReceiver.readDatagram(); } @Override public boolean isClosable() { return _connectionReceiver.isClosable(); } @Override public boolean isOpenable( CON aConnection ) { return _connectionReceiver.isOpenable( aConnection ); } @Override public boolean hasDatagram() throws OpenException { return _connectionReceiver.hasDatagram(); } // ///////////////////////////////////////////////////////////////////////// // OBSERVERS: // ///////////////////////////////////////////////////////////////////////// @Override public boolean hasObserverSubscription( ConnectionObserver aObserver ) { return _observable.hasObserverSubscription( aObserver ); } @Override public boolean subscribeObserver( ConnectionObserver aObserver ) { return _observable.subscribeObserver( aObserver ); } @Override public boolean unsubscribeObserver( ConnectionObserver aObserver ) { return _observable.unsubscribeObserver( aObserver ); } // ///////////////////////////////////////////////////////////////////////// // COMPONENT: // ///////////////////////////////////////////////////////////////////////// @Override public void destroy() { if ( !_isDestroyed ) { _isDestroyed = true; try { close(); } catch ( CloseException e ) { LOGGER.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 ActionEvent} aware. */ private class ConnectionObservable extends AbstractObservable> { // ///////////////////////////////////////////////////////////////////// // VARIABLES: // ///////////////////////////////////////////////////////////////////// private ExecutionStrategy _executionStrategy; // ///////////////////////////////////////////////////////////////////// // CONSTRUCTORS: // ///////////////////////////////////////////////////////////////////// public ConnectionObservable() { super(); _executionStrategy = ExecutionStrategy.SEQUENTIAL; } public ConnectionObservable( ExecutorService aExecutorService, ExecutionStrategy aExecutionStrategy ) { super( aExecutorService ); _executionStrategy = (aExecutionStrategy != null) ? aExecutionStrategy : ExecutionStrategy.SEQUENTIAL; } // ///////////////////////////////////////////////////////////////////// // METHODS: // ///////////////////////////////////////////////////////////////////// @Override public int size() { return super.size(); } @Override public boolean isEmpty() { return super.isEmpty(); } @Override public void clear() { super.clear(); } // ///////////////////////////////////////////////////////////////////// // HOOKS: // ///////////////////////////////////////////////////////////////////// /** * Same as {@link #fireEvent(MetaDataEvent, ExecutionStrategy)} with a * predefined {@link ExecutionStrategy#JOIN}. * * @see #fireEvent(MetaDataEvent, ExecutionStrategy) */ protected boolean fireEvent( MetaDataEvent aEvent ) throws VetoException { return super.fireEvent( aEvent, _executionStrategy ); } @Override protected boolean fireEvent( MetaDataEvent aEvent, ConnectionObserver aObserver, ExecutionStrategy aExecutionStrategy ) throws VetoException { if ( aEvent instanceof OpenedEvent ) { aObserver.onOpendEvent( (OpenedEvent) aEvent ); } else if ( aEvent instanceof ClosedEvent ) { aObserver.onClosedEvent( (ClosedEvent) aEvent ); } aObserver.onEvent( aEvent ); return true; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy