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

org.refcodes.connection.ext.observable.ObservableConnectionSenderImpl 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.ClosedEvent;
import org.refcodes.component.ext.observer.ConnectionObserver;
import org.refcodes.component.ext.observer.OpenedEvent;
import org.refcodes.controlflow.ExecutionStrategy;
import org.refcodes.exception.VetoException;
import org.refcodes.io.ConnectionSender;
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 ObservableConnectionSenderImpl} implements the
 * {@link ObservableConnectionSender} for wrapping and extending a
 * {@link ConnectionSender} 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 ObservableConnectionSenderImpl implements ObservableConnectionSender, Loggable { // ///////////////////////////////////////////////////////////////////////// // CONSTANTS: // ///////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////// // VARIABLES: // ///////////////////////////////////////////////////////////////////////// private ConnectionSender _connectionSender; private ConnectionObservable _observable; private EventMetaData _eventMetaData; private Object _source; private boolean _isDestroyed = false; // ///////////////////////////////////////////////////////////////////////// // CONSTRUCTORS: // ///////////////////////////////////////////////////////////////////////// /** * Constructs a {@link ObservableConnectionSenderImpl} with the given * attributes. * * @param aConnectionSender The {@link ConnectionSender} to which the * connection method calls are to be delegated to. */ public ObservableConnectionSenderImpl( ConnectionSender aConnectionSender ) { _connectionSender = aConnectionSender; _eventMetaData = new EventMetaDataImpl( this.getClass() ); _source = this; _observable = new ConnectionObservable(); } /** * Constructs a {@link ObservableConnectionSenderImpl} with the given * attributes. * * @param aConnectionSender The {@link ConnectionSender} 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 ObservableConnectionSenderImpl( ConnectionSender aConnectionSender, Object aSource ) { _connectionSender = aConnectionSender; _eventMetaData = new EventMetaDataImpl( this.getClass() ); _source = aSource; _observable = new ConnectionObservable(); } /** * Constructs a {@link ObservableConnectionSenderImpl} with the given * attributes. * * @param aConnectionSender The {@link ConnectionSender} 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 ObservableConnectionSenderImpl( ConnectionSender aConnectionSender, EventMetaData aEventMetaData ) { _connectionSender = aConnectionSender; _eventMetaData = aEventMetaData; _source = this; _observable = new ConnectionObservable(); } /** * Constructs a {@link ObservableConnectionSenderImpl} with the given * attributes. * * @param aConnectionSender The {@link ConnectionSender} 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 ObservableConnectionSenderImpl( ConnectionSender aConnectionSender, EventMetaData aEventMetaData, Object aSource ) { _connectionSender = aConnectionSender; _eventMetaData = aEventMetaData; _source = aSource; _observable = new ConnectionObservable(); } // WITH EXECUTOR-SERVICE: /** * Constructs a {@link ObservableConnectionSenderImpl} with the given * attributes. * * @param aConnectionSender The {@link ConnectionSender} 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 ObservableConnectionSenderImpl( ConnectionSender aConnectionSender, ExecutorService aExecutorService, ExecutionStrategy aExecutionStrategy ) { _connectionSender = aConnectionSender; _eventMetaData = new EventMetaDataImpl( this.getClass() ); _source = this; _observable = new ConnectionObservable( aExecutorService, aExecutionStrategy ); } /** * Constructs a {@link ObservableConnectionSenderImpl} with the given * attributes. * * @param aConnectionSender The {@link ConnectionSender} 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 ObservableConnectionSenderImpl( ConnectionSender aConnectionSender, Object aSource, ExecutorService aExecutorService, ExecutionStrategy aExecutionStrategy ) { _connectionSender = aConnectionSender; _eventMetaData = new EventMetaDataImpl( this.getClass() ); _source = aSource; _observable = new ConnectionObservable( aExecutorService, aExecutionStrategy ); } /** * Constructs a {@link ObservableConnectionSenderImpl} with the given * attributes. * * @param aConnectionSender The {@link ConnectionSender} 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 ObservableConnectionSenderImpl( ConnectionSender aConnectionSender, EventMetaData aEventMetaData, ExecutorService aExecutorService, ExecutionStrategy aExecutionStrategy ) { _connectionSender = aConnectionSender; _eventMetaData = aEventMetaData; _source = this; _observable = new ConnectionObservable( aExecutorService, aExecutionStrategy ); } /** * Constructs a {@link ObservableConnectionSenderImpl} with the given * attributes. * * @param aConnectionSender The {@link ConnectionSender} 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 ObservableConnectionSenderImpl( ConnectionSender aConnectionSender, EventMetaData aEventMetaData, Object aSource, ExecutorService aExecutorService, ExecutionStrategy aExecutionStrategy ) { _connectionSender = aConnectionSender; _eventMetaData = aEventMetaData; _source = aSource; _observable = new ConnectionObservable( aExecutorService, aExecutionStrategy ); } // ///////////////////////////////////////////////////////////////////////// // METHODS: // ///////////////////////////////////////////////////////////////////////// /** * {@inheritDoc} */ @Override public boolean isClosed() { return _connectionSender.isClosed(); } /** * {@inheritDoc} */ @Override public boolean isOpened() { return _connectionSender.isOpened(); } /** * {@inheritDoc} */ @Override public ConnectionStatus getConnectionStatus() { return _connectionSender.getConnectionStatus(); } /** * {@inheritDoc} */ @Override public void flush() throws OpenException { _connectionSender.flush(); } /** * {@inheritDoc} */ @Override public void close() throws CloseException { _connectionSender.close(); try { _observable.fireEvent( new ClosedEvent( _eventMetaData, _source ) ); } catch ( VetoException e ) { /* Cannot happen here */ } } /** * {@inheritDoc} */ @Override public void open( CON aConnection ) throws OpenException { _connectionSender.open( aConnection ); try { _observable.fireEvent( new OpenedEvent( _eventMetaData, _source ) ); } catch ( VetoException e ) { /* Cannot happen here */ } } /** * {@inheritDoc} */ @Override public void writeDatagram( DATA aDatagram ) throws OpenException { _connectionSender.writeDatagram( aDatagram ); } /** * {@inheritDoc} */ @Override public boolean isClosable() { return _connectionSender.isClosable(); } /** * {@inheritDoc} */ @Override public boolean isOpenable( CON aConnection ) { return _connectionSender.isOpenable( aConnection ); } // ///////////////////////////////////////////////////////////////////////// // OBSERVERS: // ///////////////////////////////////////////////////////////////////////// /** * {@inheritDoc} */ @Override public boolean hasObserverSubscription( ConnectionObserver aObserver ) { return _observable.hasObserverSubscription( aObserver ); } /** * {@inheritDoc} */ @Override public boolean subscribeObserver( ConnectionObserver aObserver ) { return _observable.subscribeObserver( aObserver ); } /** * {@inheritDoc} */ @Override public boolean unsubscribeObserver( ConnectionObserver 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 ); } _connectionSender = 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, 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 - 2024 Weber Informatics LLC | Privacy Policy