/******************************************************************************* * This file is protected by Copyright. * Please refer to the COPYRIGHT file distributed with this source distribution. * * This file is part of REDHAWK IDE. * * All rights reserved. This program and the accompanying materials are made available under * the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html *******************************************************************************/ package gov.redhawk.sca.ui; import gov.redhawk.model.sca.CorbaObjWrapper; import gov.redhawk.model.sca.ScaEventChannel; import gov.redhawk.model.sca.ScaFileStore; import gov.redhawk.model.sca.ScaFileSystem; import gov.redhawk.model.sca.ScaProvidesPort; import gov.redhawk.model.sca.ScaUsesPort; import gov.redhawk.model.sca.ScaWaveformFactory; import gov.redhawk.model.sca.provider.ScaEventChannelsContainerItemProvider; import gov.redhawk.model.sca.provider.ScaWaveformFactoriesContainerItemProvider; import gov.redhawk.sca.ScaPlugin; import gov.redhawk.sca.ui.views.ScaExplorer; import gov.redhawk.sca.util.PropertyChangeSupport; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.lang.reflect.InvocationTargetException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.Callable; import mil.jpeojtrs.sca.util.CorbaUtils; import org.eclipse.core.databinding.DataBindingContext; import org.eclipse.core.databinding.UpdateValueStrategy; import org.eclipse.core.databinding.ValidationStatusProvider; import org.eclipse.core.databinding.beans.BeanProperties; import org.eclipse.core.databinding.observable.list.IObservableList; import org.eclipse.core.databinding.observable.list.WritableList; import org.eclipse.core.databinding.observable.value.IObservableValue; import org.eclipse.core.databinding.observable.value.WritableValue; import org.eclipse.core.databinding.validation.IValidator; import org.eclipse.core.databinding.validation.ValidationStatus; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.databinding.swt.WidgetProperties; import org.eclipse.jface.databinding.viewers.ViewerProperties; import org.eclipse.jface.databinding.wizard.WizardPageSupport; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.jface.wizard.Wizard; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.navigator.CommonViewer; import org.eclipse.ui.progress.UIJob; import org.eclipse.ui.statushandlers.StatusManager; import CF.PortPackage.InvalidPort; /** * @since 9.3 * */ public class ConnectPortWizard extends Wizard { private static final SimpleDateFormat FORMAT = new SimpleDateFormat("yyyyMMddHHmmss"); private static class ConnectWizardPage extends WizardPage { private class SourceTargetValidator extends ValidationStatusProvider implements PropertyChangeListener { private final WritableValue<IStatus> status = new WritableValue<IStatus>(); private IObservableList<WritableValue<IStatus>> list = new WritableList<WritableValue<IStatus>>(); { list.add(status); } @Override public IObservableValue<IStatus> getValidationStatus() { return status; } @Override public IObservableList<WritableValue<IStatus>> getTargets() { return list; } @Override public IObservableList< ? > getModels() { return null; } @Override public void propertyChange(PropertyChangeEvent evt) { if (source != null && target != null) { if (!target._is_a(source.getRepid())) { status.setValue(ValidationStatus.warning("Warning: Connection types are not an exact match, connection may not be possible. Target is not of type: " + source.getRepid())); return; } } status.setValue(ValidationStatus.ok()); } } private SourceTargetValidator connectionValidator = new SourceTargetValidator(); private static final String SDR_ROOT_CLASS = "gov.redhawk.ide.sdr.impl.SdrRootImpl"; private ScaUsesPort source; private CorbaObjWrapper< ? > target; private String connectionID = ConnectPortWizard.generateDefaultConnectionID(); private WizardPageSupport support; private DataBindingContext context; private PropertyChangeSupport pcs = new PropertyChangeSupport(this); private boolean connectionIDEnabled = true; private Object defaultInput = ScaPlugin.getDefault().getDomainManagerRegistry(Display.getCurrent()); private boolean showAllInputs = true; private boolean showAllOutputs = true; private Object sourceInput = defaultInput; private Object targetInput = defaultInput; protected ConnectWizardPage() { super("connectPage", "Create new connection", null); setDescription("Select the source and target connection elements.\nAlso enter a connection id."); pcs.addPropertyChangeListener(connectionValidator); } /** * @param listener * @see java.beans.PropertyChangeSupport#addPropertyChangeListener(java.beans.PropertyChangeListener) */ @SuppressWarnings("unused") public void addPropertyChangeListener(PropertyChangeListener listener) { pcs.addPropertyChangeListener(listener); } /** * @param listener * @see java.beans.PropertyChangeSupport#removePropertyChangeListener(java.beans.PropertyChangeListener) */ @SuppressWarnings("unused") public void removePropertyChangeListener(PropertyChangeListener listener) { pcs.removePropertyChangeListener(listener); } @SuppressWarnings("unchecked") @Override public void createControl(Composite parent) { Composite composite = new Composite(parent, SWT.None); composite.setLayout(new GridLayout(4, true)); Group sourceGroup = new Group(composite, SWT.None); sourceGroup.setText("Source"); sourceGroup.setLayout(new FillLayout()); sourceGroup.setLayoutData(GridDataFactory.fillDefaults().grab(true, false).span(2, 1).hint(SWT.DEFAULT, 200).create()); int sourceViewerStyle = SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE | SWT.FULL_SELECTION; if (!isShowAllInputs() && getSource() != null) { sourceViewerStyle = sourceViewerStyle | SWT.READ_ONLY; } CommonViewer sourceViewer = new CommonViewer(ScaExplorer.VIEW_ID, sourceGroup, sourceViewerStyle); sourceViewer.addFilter(new ViewerFilter() { @Override public boolean select(Viewer viewer, Object parentElement, Object element) { if (!isShowAllInputs()) { return element == source; } // This is a hack to filter out the sdr root. if (element.getClass().getName().equals(ConnectWizardPage.SDR_ROOT_CLASS)) { return false; } else if (element instanceof ScaProvidesPort) { return false; } else if (element instanceof ScaFileStore) { return false; } else if (element instanceof ScaWaveformFactory) { return false; } else if (element instanceof ScaWaveformFactoriesContainerItemProvider) { return false; } else if (element instanceof ScaEventChannelsContainerItemProvider) { return false; } else if (element instanceof ScaEventChannel) { return false; } return true; } }); Group targetGroup = new Group(composite, SWT.None); targetGroup.setText("Target"); targetGroup.setLayout(new FillLayout()); targetGroup.setLayoutData(GridDataFactory.fillDefaults().grab(true, false).span(2, 1).hint(SWT.DEFAULT, 200).create()); int targetViewerStyle = SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE | SWT.FULL_SELECTION; if (!isShowAllOutputs() && getTarget() != null) { targetViewerStyle = targetViewerStyle | SWT.READ_ONLY; } CommonViewer targetViewer = new CommonViewer(ScaExplorer.VIEW_ID, targetGroup, targetViewerStyle); targetViewer.addFilter(new ViewerFilter() { @Override public boolean select(Viewer viewer, Object parentElement, Object element) { if (!isShowAllOutputs()) { return element == target; } // This is a hack to filter out the sdr root. if (element.getClass().getName().equals(ConnectWizardPage.SDR_ROOT_CLASS)) { return false; } else if (element instanceof ScaUsesPort) { return false; } else if (element instanceof ScaWaveformFactoriesContainerItemProvider) { return false; } else if (element instanceof ScaFileSystem< ? >) { return true; } else if (element instanceof ScaFileStore) { return false; } return true; } }); Label label = new Label(composite, SWT.None); label.setText("Connection ID:"); Text idText = new Text(composite, SWT.BORDER); idText.setLayoutData(GridDataFactory.fillDefaults().grab(true, false).span(3, 1).create()); setControl(composite); context = new DataBindingContext(); context.bindValue(ViewerProperties.input().observe(sourceViewer), BeanProperties.value("sourceInput").observe(this)); context.bindValue(ViewerProperties.input().observe(targetViewer), BeanProperties.value("targetInput").observe(this)); context.bindValue(ViewerProperties.singleSelection().observe(sourceViewer), BeanProperties.value("source").observe(this), createSourceTargetToModel(), null); context.bindValue(ViewerProperties.singleSelection().observe(targetViewer), BeanProperties.value("target").observe(this), createTargetTargetToModel(), null); context.bindValue(WidgetProperties.text(SWT.Modify).observe(idText), BeanProperties.value("connectionID").observe(this), createConnectionIDTargetToModel(), null); context.bindValue(WidgetProperties.enabled().observe(idText), BeanProperties.value("connectionIDReadOnly").observe(this)); context.addValidationStatusProvider(connectionValidator); support = WizardPageSupport.create(this, context); } private UpdateValueStrategy createConnectionIDTargetToModel() { UpdateValueStrategy strategy = new UpdateValueStrategy(); strategy.setAfterConvertValidator(new IValidator() { @Override public IStatus validate(Object value) { if (value == null || value.toString().trim().isEmpty()) { return ValidationStatus.error("Must enter a connection ID"); } return ValidationStatus.ok(); } }); return strategy; } @Override public void dispose() { super.dispose(); support.dispose(); context.dispose(); } private UpdateValueStrategy createTargetTargetToModel() { UpdateValueStrategy strategy = new UpdateValueStrategy(); strategy.setAfterGetValidator(new IValidator() { @Override public IStatus validate(Object value) { if (!(value instanceof CorbaObjWrapper< ? >)) { return ValidationStatus.error("Target not specified."); } return ValidationStatus.ok(); } }); return strategy; } private UpdateValueStrategy createSourceTargetToModel() { UpdateValueStrategy strategy = new UpdateValueStrategy(); strategy.setAfterGetValidator(new IValidator() { @Override public IStatus validate(Object value) { if (value instanceof ScaUsesPort) { return ValidationStatus.ok(); } return ValidationStatus.error("Source must be of type 'Uses Port'"); } }); return strategy; } public String getConnectionID() { return connectionID; } public void setConnectionID(String connectionID) { String oldValue = this.connectionID; this.connectionID = connectionID; pcs.firePropertyChange("connectionID", oldValue, connectionID); } public ScaUsesPort getSource() { return source; } public void setSource(ScaUsesPort source) { ScaUsesPort oldValue = this.source; this.source = source; pcs.firePropertyChange("source", oldValue, source); } public CorbaObjWrapper< ? > getTarget() { return target; } public void setTarget(CorbaObjWrapper< ? > target) { CorbaObjWrapper< ? > oldValue = this.target; this.target = target; pcs.firePropertyChange("target", oldValue, target); } public void setConnectionIDReadOnly(boolean connectionIDReadOnly) { boolean oldValue = this.connectionIDEnabled; this.connectionIDEnabled = connectionIDReadOnly; pcs.firePropertyChange("connectionIDReadOnly", oldValue, connectionIDReadOnly); } public boolean isConnectionIDReadOnly() { return connectionIDEnabled; } public void setSourceInput(Object sourceInput) { if (sourceInput == null) { sourceInput = defaultInput; } Object oldValue = this.sourceInput; this.sourceInput = sourceInput; pcs.firePropertyChange("sourceInput", oldValue, sourceInput); } public Object getSourceInput() { return sourceInput; } public void setTargetInput(Object targetInput) { if (targetInput == null) { targetInput = defaultInput; } Object oldValue = this.targetInput; this.targetInput = targetInput; pcs.firePropertyChange("targetInput", oldValue, targetInput); } public Object getTargetInput() { return targetInput; } public boolean isShowAllInputs() { return showAllInputs; } public void setShowAllInputs(boolean showAllInputs) { this.showAllInputs = showAllInputs; } public boolean isShowAllOutputs() { return showAllOutputs; } public void setShowAllOutputs(boolean showAllOutputs) { this.showAllOutputs = showAllOutputs; } } public static String generateDefaultConnectionID() { return System.getProperty("user.name", "user") + "_" + ConnectPortWizard.FORMAT.format(new Date()); } private ConnectWizardPage page = new ConnectWizardPage(); public ConnectPortWizard() { setWindowTitle("Connect"); setNeedsProgressMonitor(true); } @Override public void addPages() { addPage(page); } /* * (non-Javadoc) * * @see org.eclipse.jface.wizard.Wizard#performFinish() */ @Override public final boolean performFinish() { try { getContainer().run(true, true, new IRunnableWithProgress() { @Override public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { performFinish(monitor); } }); } catch (InvocationTargetException e) { StatusManager.getManager().handle(new Status(IStatus.ERROR, ScaUiPlugin.PLUGIN_ID, "Failed to make connection.", e.getCause())); return false; } catch (InterruptedException e) { return true; } return true; } public String getConnectionID() { return page.getConnectionID(); } public void setConnectionID(String connectionID) { page.setConnectionID(connectionID); } public ScaUsesPort getSource() { return page.getSource(); } public void setSource(ScaUsesPort source) { page.setSource(source); } public CorbaObjWrapper< ? > getTarget() { return page.getTarget(); } public void setTarget(CorbaObjWrapper< ? > target) { page.setTarget(target); } public void setConnectionIDReadOnly(boolean connectionIDReadOnly) { page.setConnectionIDReadOnly(!connectionIDReadOnly); } public boolean isConnectionIDReadOnly() { return !page.isConnectionIDReadOnly(); } /** * @param sourceInput * @see gov.redhawk.sca.ui.ConnectPortWizard.ConnectWizardPage#setSourceInput(java.lang.Object) */ public void setSourceInput(Object sourceInput) { page.setSourceInput(sourceInput); } /** * @return * @see gov.redhawk.sca.ui.ConnectPortWizard.ConnectWizardPage#getSourceInput() */ public Object getSourceInput() { return page.getSourceInput(); } /** * @param targetInput * @see gov.redhawk.sca.ui.ConnectPortWizard.ConnectWizardPage#setTargetInput(java.lang.Object) */ public void setTargetInput(Object targetInput) { page.setTargetInput(targetInput); } /** * @return * @see gov.redhawk.sca.ui.ConnectPortWizard.ConnectWizardPage#getTargetInput() */ public Object getTargetInput() { return page.getTargetInput(); } public boolean isShowAllInputs() { return page.isShowAllInputs(); } public void setShowAllInputs(boolean showAllInputs) { page.setShowAllInputs(showAllInputs); } public boolean isShowAllOutputs() { return page.isShowAllOutputs(); } public void setShowAllOutputs(boolean showAllOutputs) { page.setShowAllOutputs(showAllOutputs); } protected void performFinish(IProgressMonitor monitor) throws InterruptedException, InvocationTargetException { monitor.beginTask("Connecting...", IProgressMonitor.UNKNOWN); try { CorbaUtils.invoke(new Callable<Object>() { @Override public Object call() throws Exception { page.source.connectPort(page.target.getCorbaObj(), page.connectionID); return null; } }, monitor); } catch (final CoreException e) { UIJob uiJob = new UIJob("Port connection error") { @Override public IStatus runInUIThread(IProgressMonitor monitor) { Throwable cause = e.getCause(); String errorMsg; if (cause instanceof InvalidPort) { InvalidPort invalidPort = ((InvalidPort) cause); errorMsg = "The source port refused to connect to the target.\n"; errorMsg += String.format("Received an InvalidPort exception (code %d, message '%s')", invalidPort.errorCode, invalidPort.msg); } else { errorMsg = "Error completing connection: " + cause.getMessage(); } MessageDialog errorDialog = new MessageDialog(getShell(), "Error", null, errorMsg, MessageDialog.ERROR, new String[] { "OK" }, 0); errorDialog.open(); return Status.OK_STATUS; } }; uiJob.schedule(); throw new InvocationTargetException(e); } } }