/* * 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.ae.ui.views.views; import java.util.Collection; import java.util.LinkedList; import org.eclipse.core.databinding.observable.Realm; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.TreeSelection; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.ui.IMemento; import org.eclipse.ui.ISelectionListener; import org.eclipse.ui.IViewSite; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.PartInitException; import org.eclipse.ui.part.ViewPart; import org.openscada.ae.BrowserType; import org.openscada.ae.client.Connection; import org.openscada.ae.connection.provider.ConnectionService; import org.openscada.ae.ui.connection.data.BrowserEntryBean; import org.openscada.ae.ui.views.Activator; import org.openscada.ae.ui.views.CustomizableAction; import org.openscada.core.ConnectionInformation; import org.openscada.core.client.ConnectionState; import org.openscada.core.client.ConnectionStateListener; 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.core.connection.provider.ConnectionTracker.Listener; import org.openscada.core.ui.connection.data.ConnectionHolder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author jrose * */ public abstract class AbstractAlarmsEventsView extends ViewPart { private static final Logger logger = LoggerFactory.getLogger ( AbstractAlarmsEventsView.class ); private static final String CONNECTION_ID = "connection.id"; //$NON-NLS-1$ private static final String CONNECTION_URI = "connection.uri"; //$NON-NLS-1$ private static final int RECONNECT_DELAY = 10000; private String connectionId = null; private String connectionUri = null; private ConnectionService connectionService; private ConnectionTracker connectionTracker; private ISelectionListener selectionListener; private Composite contentPane; private Label stateLabel; private final Object jobLock = new Object (); // we are only interested if the connection is actually there final ConnectionStateListener connectionStateListener = new ConnectionStateListener () { @Override public void stateChange ( final org.openscada.core.client.Connection changedConnection, final ConnectionState state, final Throwable error ) { try { // preconditions if ( changedConnection == null ) { throw new IllegalArgumentException ( Messages.AbstractAlarmsEventsView_IllegalArgument_changedConnection ); } if ( ! ( changedConnection instanceof Connection ) ) { throw new IllegalArgumentException ( Messages.AbstractAlarmsEventsView_IllegalArgument_changedConnection_Type + Connection.class.getName () ); } // actual check if ( state == ConnectionState.BOUND ) { onConnect (); } else { onDisconnect (); } } catch ( final Exception e ) { logger.warn ( "reInitializeConnection ()", e ); //$NON-NLS-1$ } } }; final ConnectionTracker.Listener connectionServiceListener = new Listener () { @Override public void setConnection ( final org.openscada.core.connection.provider.ConnectionService connectionService ) { if ( connectionService == null ) { onDisconnect (); AbstractAlarmsEventsView.this.connectionService = null; return; } AbstractAlarmsEventsView.this.connectionService = (ConnectionService)connectionService; if ( connectionService.getConnection () == null ) { onDisconnect (); return; } connectionService.getConnection ().addConnectionStateListener ( AbstractAlarmsEventsView.this.connectionStateListener ); if ( connectionService.getConnection ().getState () == ConnectionState.BOUND ) { onConnect (); } else { onDisconnect (); } } }; /* (non-Javadoc) * @see org.eclipse.ui.part.ViewPart#saveState(org.eclipse.ui.IMemento) */ @Override public void saveState ( final IMemento memento ) { memento.putString ( CONNECTION_ID, this.connectionId ); memento.putString ( CONNECTION_URI, this.connectionUri ); super.saveState ( memento ); } /* (non-Javadoc) * @see org.eclipse.ui.part.ViewPart#init(org.eclipse.ui.IViewSite, org.eclipse.ui.IMemento) */ @Override public void init ( final IViewSite site, final IMemento memento ) throws PartInitException { if ( memento != null ) { this.connectionId = memento.getString ( CONNECTION_ID ); this.connectionUri = memento.getString ( CONNECTION_URI ); } super.init ( site, memento ); try { // it is OK to fail at this stage reInitializeConnection ( this.connectionId, this.connectionUri ); } catch ( final Exception e ) { logger.warn ( "init () - couldn't recreate connection", e ); //$NON-NLS-1$ // just reset all values this.connectionId = null; this.connectionUri = null; this.connectionService = null; this.connectionTracker = null; } } @Override public void createPartControl ( final Composite parent ) { addSelectionListener (); this.contentPane = new Composite ( parent, SWT.NONE ); final GridLayout layout = new GridLayout ( 1, false ); layout.marginWidth = 0; layout.marginHeight = 0; this.contentPane.setLayout ( layout ); // label which contains no of retrieved events this.stateLabel = new Label ( this.contentPane, SWT.NONE ); this.stateLabel.setLayoutData ( new GridData ( SWT.FILL, SWT.CENTER, true, false ) ); } /** * @param connectionId * @throws Exception */ public void setConnectionId ( final String connectionId ) throws Exception { reInitializeConnection ( connectionId, null ); } /** * @param connectionUri * @throws Exception */ public void setConnectionUri ( final String connectionUri ) throws Exception { reInitializeConnection ( null, connectionUri ); } /** * onConnect is only called if connection is actually there */ protected void onConnect () { updateStatusBar (); } /** * onDisonnect is only called if connection is not there or no connection is found at all * it also maybe called multiple times */ protected void onDisconnect () { updateStatusBar (); } /** * @return */ protected boolean isConnected () { return this.connectionService != null && this.connectionService.getConnection () != null && this.connectionService.getConnection ().getState () == ConnectionState.BOUND; } private void reInitializeConnection ( final String connectionId, final String connectionUri ) throws Exception { if ( this.connectionTracker == null ) { if ( connectionId != null ) { trackIdConnection ( connectionId ); } else if ( connectionUri != null ) { trackUriConnection ( connectionUri ); } } else { if ( this.connectionTracker instanceof ConnectionIdTracker ) { if ( ! ( (ConnectionIdTracker)this.connectionTracker ).getConnectionId ().equals ( connectionId ) ) { this.connectionTracker.close (); this.connectionTracker = null; trackIdConnection ( connectionId ); } } else if ( this.connectionTracker instanceof ConnectionRequestTracker ) { if ( ! ( (ConnectionRequestTracker)this.connectionTracker ).getConnectionInformation ().toString ().equals ( connectionUri ) ) { this.connectionTracker.close (); this.connectionTracker = null; trackUriConnection ( connectionUri ); } } } } private void trackIdConnection ( final String connectionId ) { if ( connectionId == null ) { return; } this.connectionTracker = new ConnectionIdTracker ( Activator.getDefault ().getBundle ().getBundleContext (), connectionId, this.connectionServiceListener ); this.connectionId = connectionId; this.connectionUri = null; this.connectionService = null; this.connectionTracker.open (); } private void trackUriConnection ( final String connectionUri ) { if ( connectionUri == null ) { return; } final ConnectionInformation ci = ConnectionInformation.fromURI ( connectionUri ); final ConnectionRequest request = new ConnectionRequest ( null, ci, RECONNECT_DELAY, true ); this.connectionTracker = new ConnectionRequestTracker ( Activator.getDefault ().getBundle ().getBundleContext (), request, this.connectionServiceListener ); this.connectionId = null; this.connectionUri = connectionUri; this.connectionService = null; this.connectionTracker.open (); } protected void addSelectionListener () { if ( this.selectionListener == null ) { getViewSite ().getWorkbenchWindow ().getSelectionService ().addSelectionListener ( this.selectionListener = new ISelectionListener () { @Override public void selectionChanged ( final IWorkbenchPart part, final ISelection selection ) { AbstractAlarmsEventsView.this.setSelection ( selection ); } } ); } } protected void setSelection ( final ISelection selection ) { if ( ! ( selection instanceof TreeSelection ) || selection.isEmpty () ) { return; } final TreeSelection treeSelection = (TreeSelection)selection; if ( treeSelection.getFirstElement () instanceof ConnectionHolder ) { final ConnectionHolder connectionHolder = (ConnectionHolder)treeSelection.getFirstElement (); if ( connectionHolder.getConnectionService ().getConnection () != null && connectionHolder.getConnectionService ().getConnection () instanceof Connection ) { try { setConnectionUri ( connectionHolder.getConnectionService ().getConnection ().getConnectionInformation ().toString () ); } catch ( final Exception e ) { e.printStackTrace (); } } } else if ( treeSelection.getFirstElement () instanceof BrowserEntryBean ) { final BrowserEntryBean browserEntryBean = (BrowserEntryBean)treeSelection.getFirstElement (); if ( browserEntryBean.getConnection () != null && browserEntryBean.getConnection ().getConnection () != null ) { try { setConnectionUri ( browserEntryBean.getConnection ().getConnection ().getConnectionInformation ().toString () ); } catch ( final Exception e ) { e.printStackTrace (); } } if ( browserEntryBean.getEntry ().getTypes ().contains ( BrowserType.EVENTS ) ) { watchPool ( browserEntryBean.getEntry ().getId () ); } if ( browserEntryBean.getEntry ().getTypes ().contains ( BrowserType.CONDITIONS ) ) { watchMonitors ( browserEntryBean.getEntry ().getId () ); } } } abstract protected void watchPool ( String poolId ); abstract protected void watchMonitors ( String monitorsId ); abstract protected void updateStatusBar (); protected void removeSelectionListener () { if ( this.selectionListener != null ) { getViewSite ().getWorkbenchWindow ().getSelectionService ().removeSelectionListener ( this.selectionListener ); this.selectionListener = null; } } public String getConnectionUri () { return this.connectionUri; } public Connection getConnection () { if ( this.connectionService != null ) { return this.connectionService.getConnection (); } return null; } public ConnectionService getConnectionService () { return this.connectionService; } public Composite getContentPane () { return this.contentPane; } public Label getStateLabel () { return this.stateLabel; } @Override public void dispose () { removeSelectionListener (); } protected CustomizableAction createCommentAction ( final Runnable runnable ) { final CustomizableAction action = new CustomizableAction (); action.setText ( Messages.AbstractAlarmsEventsView_SetCommentAction_Text ); action.setToolTipText ( Messages.AbstractAlarmsEventsView_SetCommentAction_ToolTip ); action.setDescription ( Messages.AbstractAlarmsEventsView_SetCommentAction_Description ); action.setImageDescriptor ( ImageDescriptor.createFromURL ( Activator.getDefault ().getBundle ().getResource ( "icons/event_comment.gif" ) ) ); //$NON-NLS-1$ action.setRunnable ( runnable ); return action; } private Collection<Runnable> taskList = null; protected abstract Realm getRealm (); protected void scheduleJob ( final Runnable runnable ) { synchronized ( this.jobLock ) { boolean created = false; if ( this.taskList == null ) { created = true; this.taskList = new LinkedList<Runnable> (); } this.taskList.add ( runnable ); if ( created ) { if ( getRealm () != null ) { getRealm ().asyncExec ( new Runnable () { @Override public void run () { AbstractAlarmsEventsView.this.getRealm ().timerExec ( 1000, new Runnable () { @Override public void run () { processQueue (); } } ); } } ); } } } } private void processQueue () { Collection<Runnable> list = null; synchronized ( this.jobLock ) { list = this.taskList; this.taskList = null; } if ( list != null ) { for ( final Runnable r : list ) { r.run (); } } } protected String getLabelForConnection () { if ( getConnection () != null ) { final ConnectionState state = getConnection ().getState (); if ( state == ConnectionState.BOUND ) { return String.format ( Messages.AbstractAlarmsEventsView_Label_Format_Connected, makeStringFromConnection ( getConnection () ) ); } else { return String.format ( Messages.AbstractAlarmsEventsView_Label_Format_Disconnected, state, makeStringFromConnection ( getConnection () ) ); } } else { return String.format ( Messages.AbstractAlarmsEventsView_Label_Format_NoConnection, makeStringFromConnection ( getConnection () ) ); } } protected String makeStringFromConnection ( final Connection connection ) { if ( connection == null ) { return Messages.AbstractAlarmsEventsView_Label_Format_NoConnection_String; } final ConnectionInformation ci = connection.getConnectionInformation (); if ( ci == null ) { return Messages.AbstractAlarmsEventsView_Label_Format_NoConnection_String; } return ci.toMaskedString (); } }