/* * 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.ae.ui.views.views; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.eclipse.core.databinding.observable.ChangeEvent; import org.eclipse.core.databinding.observable.IChangeListener; import org.eclipse.core.databinding.observable.Realm; import org.eclipse.core.databinding.observable.map.IMapChangeListener; import org.eclipse.core.databinding.observable.map.MapChangeEvent; import org.eclipse.core.databinding.observable.map.WritableMap; import org.eclipse.core.databinding.observable.set.WritableSet; import org.eclipse.jface.databinding.swt.SWTObservables; import org.eclipse.swt.widgets.Composite; import org.openscada.ae.MonitorStatusInformation; import org.openscada.ae.client.MonitorListener; import org.openscada.ae.ui.views.model.DecoratedMonitor; import org.openscada.core.client.ConnectionState; import org.openscada.core.subscription.SubscriptionState; public abstract class MonitorSubscriptionAlarmsEventsView extends AbstractAlarmsEventsView { protected String monitorsId; protected WritableSet monitors; protected WritableMap monitorsMap; private MonitorListener monitorListener; @Override protected Realm getRealm () { if ( this.monitors != null ) { return this.monitors.getRealm (); } return SWTObservables.getRealm ( getSite ().getShell ().getDisplay () ); } public void setMonitorsId ( final String monitorsId ) { if ( monitorsId == null ) { unSubscribe (); this.monitorsId = null; return; } if ( !String.valueOf ( monitorsId ).equals ( String.valueOf ( this.monitorsId ) ) ) { unSubscribe (); this.monitorsId = monitorsId; subscribe (); } } public String getMonitorsId () { return this.monitorsId; } protected void subscribe () { if ( getConnection () != null && this.monitorsId != null ) { this.monitorListener = new MonitorListener () { @Override public void statusChanged ( final SubscriptionState state ) { statusChangedMonitorSubscription ( state ); } @Override public void dataChanged ( final MonitorStatusInformation[] addedOrUpdated, final String[] removed ) { MonitorSubscriptionAlarmsEventsView.this.dataChanged ( addedOrUpdated, removed ); } }; getConnectionService ().getMonitorManager ().addMonitorListener ( this.monitorsId, this.monitorListener ); } } protected void unSubscribe () { if ( getConnection () != null && this.monitorsId != null ) { if ( this.monitorListener != null ) { getConnectionService ().getMonitorManager ().removeMonitorListener ( this.monitorsId, this.monitorListener ); } } clear (); } private void clear () { this.monitors.getRealm ().asyncExec ( new Runnable () { @Override public void run () { if ( MonitorSubscriptionAlarmsEventsView.this.monitors != null ) { MonitorSubscriptionAlarmsEventsView.this.monitors.clear (); } if ( MonitorSubscriptionAlarmsEventsView.this.monitorsMap != null ) { MonitorSubscriptionAlarmsEventsView.this.monitorsMap.clear (); } } } ); } @Override protected void onConnect () { super.onConnect (); subscribe (); } @Override protected void onDisconnect () { unSubscribe (); super.onDisconnect (); }; public void statusChangedMonitorSubscription ( final SubscriptionState state ) { updateStatusBar (); } protected void dataChanged ( final MonitorStatusInformation[] addedOrUpdated, final String[] removed ) { scheduleJob ( new Runnable () { @Override public void run () { performDataChanged ( addedOrUpdated, removed ); } } ); } private void performDataChanged ( final MonitorStatusInformation[] addedOrUpdated, final String[] removed ) { try { this.monitorsMap.setStale ( true ); if ( removed != null ) { for ( final String id : removed ) { this.monitorsMap.remove ( id ); } } if ( addedOrUpdated != null ) { // do it in 2 steps // 1. add all missing final Map<String, DecoratedMonitor> missing = new HashMap<String, DecoratedMonitor> (); for ( final MonitorStatusInformation monitorStatusInformation : addedOrUpdated ) { if ( !this.monitorsMap.containsKey ( monitorStatusInformation.getId () ) ) { missing.put ( monitorStatusInformation.getId (), new DecoratedMonitor ( monitorStatusInformation ) ); } } this.monitorsMap.putAll ( missing ); // 2. update data for ( final MonitorStatusInformation monitorStatusInformation : addedOrUpdated ) { if ( !missing.keySet ().contains ( monitorStatusInformation.getId () ) ) { final DecoratedMonitor dm = (DecoratedMonitor)this.monitorsMap.get ( monitorStatusInformation.getId () ); if ( dm == null ) { this.monitorsMap.put ( monitorStatusInformation.getId (), new DecoratedMonitor ( monitorStatusInformation ) ); } else { dm.setMonitor ( monitorStatusInformation ); } } } } } finally { this.monitorsMap.setStale ( false ); } } @Override public void createPartControl ( final Composite parent ) { super.createPartControl ( parent ); this.monitorsMap = new WritableMap ( SWTObservables.getRealm ( parent.getDisplay () ) ); this.monitors = new WritableSet ( SWTObservables.getRealm ( parent.getDisplay () ) ); this.monitorsMap.addMapChangeListener ( new IMapChangeListener () { @Override public void handleMapChange ( final MapChangeEvent event ) { final Set<DecoratedMonitor> toRemove = new HashSet<DecoratedMonitor> (); for ( final Object key : event.diff.getRemovedKeys () ) { toRemove.add ( (DecoratedMonitor)event.diff.getOldValue ( key ) ); } MonitorSubscriptionAlarmsEventsView.this.monitors.removeAll ( toRemove ); final Set<DecoratedMonitor> toAdd = new HashSet<DecoratedMonitor> (); for ( final Object key : event.diff.getAddedKeys () ) { toAdd.add ( (DecoratedMonitor)event.diff.getNewValue ( key ) ); } MonitorSubscriptionAlarmsEventsView.this.monitors.addAll ( toAdd ); for ( final Object key : event.diff.getChangedKeys () ) { MonitorSubscriptionAlarmsEventsView.this.monitors.remove ( event.diff.getOldValue ( key ) ); MonitorSubscriptionAlarmsEventsView.this.monitors.add ( event.diff.getNewValue ( key ) ); } } } ); this.monitors.addChangeListener ( new IChangeListener () { @Override public void handleChange ( final ChangeEvent event ) { updateStatusBar (); } } ); } public void acknowledgeMonitor ( final String monitorId, final Date timestamp ) { if ( getConnection () != null && getConnection ().getState () == ConnectionState.BOUND ) { getConnection ().acknowledge ( monitorId, timestamp ); } } }