/*
* This file is part of the OpenSCADA project
* Copyright (C) 2006-2012 TH4 SYSTEMS GmbH (http://th4-systems.com)
*
* OpenSCADA is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* OpenSCADA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenSCADA. If not, see
* <http://opensource.org/licenses/lgpl-3.0.html> for a copy of the LGPLv3 License.
*/
package org.openscada.da.ui.connection.data;
import java.util.Map;
import java.util.Observable;
import java.util.Observer;
import org.openscada.core.ConnectionInformation;
import org.openscada.core.Variant;
import org.openscada.core.connection.provider.ConnectionIdTracker;
import org.openscada.core.connection.provider.ConnectionRequest;
import org.openscada.core.connection.provider.ConnectionRequestTracker;
import org.openscada.core.connection.provider.ConnectionTracker;
import org.openscada.da.client.DataItem;
import org.openscada.da.client.DataItemValue;
import org.openscada.da.client.WriteAttributeOperationCallback;
import org.openscada.da.client.WriteOperationCallback;
import org.openscada.da.connection.provider.ConnectionService;
import org.openscada.da.core.OperationParameters;
import org.openscada.da.core.WriteAttributeResults;
import org.openscada.utils.concurrent.AbstractFuture;
import org.openscada.utils.concurrent.NotifyFuture;
import org.osgi.framework.BundleContext;
public class DataItemHolder
{
private final class WriteFuture extends AbstractFuture<Object>
{
@Override
public void setError ( final Throwable error )
{
super.setError ( error );
}
@Override
protected void setResult ( final Object result )
{
super.setResult ( result );
}
}
private final class WriteAttributesFuture extends AbstractFuture<WriteAttributeResults>
{
@Override
public void setError ( final Throwable error )
{
super.setError ( error );
}
@Override
protected void setResult ( final WriteAttributeResults result )
{
super.setResult ( result );
}
}
private final Item item;
private final BundleContext context;
private final ConnectionTracker tracker;
private final DataSourceListener listener;
private ConnectionService connection;
private DataItem dataItem;
private final Observer observer;
public DataItemHolder ( final BundleContext context, final Item item, final DataSourceListener listener )
{
this.context = context;
this.item = item;
synchronized ( this )
{
this.listener = listener;
this.observer = new Observer () {
@Override
public void update ( final Observable o, final Object arg )
{
DataItemHolder.this.update ( o, arg );
}
};
switch ( item.getType () )
{
case ID:
this.tracker = new ConnectionIdTracker ( this.context, item.getConnectionString (), new ConnectionTracker.Listener () {
@Override
public void setConnection ( final org.openscada.core.connection.provider.ConnectionService connectionService )
{
DataItemHolder.this.setConnection ( (ConnectionService)connectionService );
}
} );
break;
case URI:
default:
this.tracker = new ConnectionRequestTracker ( this.context, createRequest (), new ConnectionTracker.Listener () {
@Override
public void setConnection ( final org.openscada.core.connection.provider.ConnectionService connectionService )
{
DataItemHolder.this.setConnection ( (ConnectionService)connectionService );
}
} );
break;
}
}
this.tracker.listen ();
}
protected void update ( final Observable o, final Object arg )
{
if ( o != this.dataItem )
{
return;
}
if ( ! ( arg instanceof DataItemValue ) )
{
return;
}
fireListenerChange ( (DataItemValue)arg );
}
protected synchronized void setConnection ( final ConnectionService connectionService )
{
clearConnection ();
createConnection ( connectionService );
}
private synchronized void createConnection ( final ConnectionService connectionService )
{
this.connection = connectionService;
if ( this.connection != null )
{
this.dataItem = new DataItem ( this.item.getId () );
this.dataItem.addObserver ( this.observer );
this.dataItem.register ( this.connection.getItemManager () );
}
}
private synchronized void clearConnection ()
{
if ( this.dataItem != null )
{
this.dataItem.deleteObserver ( this.observer );
this.dataItem.unregister ();
this.dataItem = null;
}
if ( this.connection != null )
{
this.connection = null;
}
fireListenerChange ( null );
}
private synchronized void fireListenerChange ( final DataItemValue value )
{
if ( this.listener != null )
{
this.listener.updateData ( value );
}
}
private ConnectionRequest createRequest ()
{
return new ConnectionRequest ( null, ConnectionInformation.fromURI ( this.item.getConnectionString () ), null, false );
}
public synchronized void dispose ()
{
clearConnection ();
this.tracker.close ();
}
public NotifyFuture<Object> write ( final Variant value )
{
return write ( value, null );
}
public NotifyFuture<Object> write ( final Variant value, final OperationParameters operationParameters )
{
final WriteFuture writeResult = new WriteFuture ();
this.connection.getConnection ().write ( this.item.getId (), value, operationParameters, new WriteOperationCallback () {
@Override
public void failed ( final String error )
{
writeResult.setError ( new RuntimeException ( error ).fillInStackTrace () );
}
@Override
public void error ( final Throwable e )
{
writeResult.setError ( e );
}
@Override
public void complete ()
{
writeResult.setResult ( null );
}
} );
return writeResult;
}
public NotifyFuture<WriteAttributeResults> writeAtrtibutes ( final Map<String, Variant> attributes )
{
return writeAtrtibutes ( attributes, null );
}
public NotifyFuture<WriteAttributeResults> writeAtrtibutes ( final Map<String, Variant> attributes, final OperationParameters operationParameters )
{
final WriteAttributesFuture writeResult = new WriteAttributesFuture ();
this.connection.getConnection ().writeAttributes ( this.item.getId (), attributes, operationParameters, new WriteAttributeOperationCallback () {
@Override
public void failed ( final String error )
{
writeResult.setError ( new RuntimeException ( error ).fillInStackTrace () );
}
@Override
public void error ( final Throwable e )
{
writeResult.setError ( e );
}
@Override
public void complete ( final WriteAttributeResults result )
{
writeResult.setResult ( result );
}
} );
return writeResult;
}
public Item getItem ()
{
return this.item;
}
public boolean waitForConnection ( final long timeout ) throws InterruptedException
{
return this.tracker.waitForService ( timeout ) != null;
}
}