/*
* This file is part of the OpenSCADA project
* Copyright (C) 2006-2011 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.ui.databinding;
import java.util.Observable;
import java.util.Observer;
import org.eclipse.core.databinding.observable.value.AbstractObservableValue;
import org.eclipse.core.databinding.observable.value.ValueDiff;
import org.openscada.core.connection.provider.ConnectionIdTracker;
import org.openscada.core.connection.provider.ConnectionService;
import org.openscada.core.connection.provider.ConnectionTracker;
import org.openscada.core.connection.provider.ConnectionTracker.Listener;
import org.openscada.da.client.DataItem;
import org.openscada.da.client.DataItemValue;
import org.openscada.da.client.ItemManager;
import org.osgi.framework.BundleContext;
public class DataItemObservableValue extends AbstractObservableValue
{
private final ConnectionTracker tracker;
private DataItemValue value = DataItemValue.DISCONNECTED;
private DataItem dataItem;
private String itemId;
private Observer observer;
private org.openscada.da.connection.provider.ConnectionService service;
public DataItemObservableValue ( final BundleContext context, final String connectionId, final String itemId )
{
this.itemId = itemId;
final Listener listener = new Listener () {
@Override
public void setConnection ( final ConnectionService connectionService )
{
bind ( connectionService );
}
};
this.tracker = new ConnectionIdTracker ( context, connectionId, listener, org.openscada.da.connection.provider.ConnectionService.class );
this.tracker.open ();
}
protected synchronized void bind ( final ConnectionService connectionService )
{
unbind ();
this.service = null;
if ( connectionService instanceof org.openscada.da.connection.provider.ConnectionService )
{
this.service = (org.openscada.da.connection.provider.ConnectionService)connectionService;
bind ();
}
}
private void bind ()
{
if ( this.service != null && this.itemId != null )
{
final ItemManager im = this.service.getItemManager ();
this.dataItem = new DataItem ( this.itemId );
this.dataItem.addObserver ( this.observer = createObserver () );
this.dataItem.register ( im );
}
}
private Observer createObserver ()
{
return new Observer () {
@Override
public void update ( final Observable o, final Object arg )
{
if ( arg instanceof DataItemValue )
{
handleUpdate ( this, (DataItemValue)arg );
}
}
};
}
protected synchronized void handleUpdate ( final Observer observer, final DataItemValue value )
{
if ( observer != this.observer )
{
return;
}
fireChange ( this.value, this.value = value );
}
private void fireChange ( final DataItemValue oldValue, final DataItemValue newValue )
{
final ValueDiff diff = new ValueDiff () {
@Override
public Object getOldValue ()
{
return oldValue;
}
@Override
public Object getNewValue ()
{
return newValue;
}
};
getRealm ().asyncExec ( new Runnable () {
@Override
public void run ()
{
fireValueChange ( diff );
};
} );
}
protected synchronized void unbind ()
{
this.observer = null;
if ( this.dataItem != null )
{
this.dataItem.unregister ();
this.dataItem.deleteObservers ();
}
}
@Override
public synchronized void dispose ()
{
this.service = null;
this.tracker.close ();
unbind ();
super.dispose ();
}
@Override
public Object getValueType ()
{
return DataItemValue.class;
}
@Override
protected Object doGetValue ()
{
return this.value;
}
public String getItemId ()
{
return this.itemId;
}
public synchronized void setItemId ( final String itemId )
{
if ( this.itemId == null && itemId == null )
{
return;
}
if ( this.itemId != null && this.itemId.equals ( itemId ) )
{
return;
}
// unregister
unbind ();
// set new id
this.itemId = itemId;
// register
bind ();
if ( itemId == null )
{
handleUpdate ( this.observer, DataItemValue.DISCONNECTED );
}
}
}