/* * Copyright (C) 2006-2015 DLR, Germany * * All rights reserved * * http://www.rcenvironment.de/ */ package de.rcenvironment.core.gui.workflow.editor; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileWriter; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collection; import java.util.EventObject; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.io.FileUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.resources.IResourceChangeListener; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.IResourceDeltaVisitor; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.draw2d.ColorConstants; import org.eclipse.draw2d.FigureCanvas; import org.eclipse.draw2d.geometry.Dimension; import org.eclipse.draw2d.geometry.PointList; import org.eclipse.draw2d.geometry.Rectangle; import org.eclipse.gef.ContextMenuProvider; import org.eclipse.gef.DefaultEditDomain; import org.eclipse.gef.EditPart; import org.eclipse.gef.GraphicalViewer; import org.eclipse.gef.SnapToGeometry; import org.eclipse.gef.SnapToGrid; import org.eclipse.gef.commands.CommandStack; import org.eclipse.gef.dnd.TemplateTransferDragSourceListener; import org.eclipse.gef.dnd.TemplateTransferDropTargetListener; import org.eclipse.gef.editparts.ScalableFreeformRootEditPart; import org.eclipse.gef.editparts.ZoomManager; import org.eclipse.gef.palette.CombinedTemplateCreationEntry; import org.eclipse.gef.palette.ConnectionCreationToolEntry; import org.eclipse.gef.palette.PaletteDrawer; import org.eclipse.gef.palette.PaletteEntry; import org.eclipse.gef.palette.PaletteGroup; import org.eclipse.gef.palette.PaletteRoot; import org.eclipse.gef.ui.actions.ToggleGridAction; import org.eclipse.gef.ui.actions.ToggleSnapToGeometryAction; import org.eclipse.gef.ui.palette.FlyoutPaletteComposite; import org.eclipse.gef.ui.palette.FlyoutPaletteComposite.FlyoutPreferences; import org.eclipse.gef.ui.palette.PaletteViewer; import org.eclipse.gef.ui.palette.PaletteViewerProvider; import org.eclipse.gef.ui.parts.GraphicalEditorWithFlyoutPalette; import org.eclipse.help.IContextProvider; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DragDetectEvent; import org.eclipse.swt.events.DragDetectListener; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.events.MenuAdapter; import org.eclipse.swt.events.MenuDetectEvent; import org.eclipse.swt.events.MenuDetectListener; import org.eclipse.swt.events.MenuEvent; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseListener; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MenuItem; import org.eclipse.swt.widgets.MessageBox; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IFileEditorInput; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.contexts.IContextService; import org.eclipse.ui.ide.FileStoreEditorInput; import org.eclipse.ui.part.FileEditorInput; import org.eclipse.ui.progress.IProgressService; import org.eclipse.ui.views.contentoutline.IContentOutlinePage; import org.eclipse.ui.views.properties.IPropertySheetPage; import org.eclipse.ui.views.properties.tabbed.ITabbedPropertySheetPageContributor; import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage; import de.rcenvironment.core.communication.api.PlatformService; import de.rcenvironment.core.communication.common.LogicalNodeId; import de.rcenvironment.core.communication.common.NodeIdentifierUtils; import de.rcenvironment.core.component.api.ComponentConstants; import de.rcenvironment.core.component.api.ComponentUtils; import de.rcenvironment.core.component.api.DistributedComponentKnowledge; import de.rcenvironment.core.component.api.DistributedComponentKnowledgeService; import de.rcenvironment.core.component.integration.ToolIntegrationConstants; import de.rcenvironment.core.component.integration.ToolIntegrationContextRegistry; import de.rcenvironment.core.component.model.api.ComponentDescription; import de.rcenvironment.core.component.model.api.ComponentInstallation; import de.rcenvironment.core.component.model.api.ComponentInstallationBuilder; import de.rcenvironment.core.component.model.api.ComponentInterface; import de.rcenvironment.core.component.model.endpoint.api.EndpointDefinition; import de.rcenvironment.core.component.model.endpoint.api.EndpointDescription; import de.rcenvironment.core.component.spi.DistributedComponentKnowledgeListener; import de.rcenvironment.core.component.workflow.execution.api.WorkflowExecutionService; import de.rcenvironment.core.component.workflow.execution.api.WorkflowFileException; import de.rcenvironment.core.component.workflow.model.api.Connection; import de.rcenvironment.core.component.workflow.model.api.WorkflowDescription; import de.rcenvironment.core.component.workflow.model.api.WorkflowDescriptionPersistenceHandler; import de.rcenvironment.core.component.workflow.model.api.WorkflowLabel; import de.rcenvironment.core.component.workflow.model.api.WorkflowNode; import de.rcenvironment.core.gui.resources.api.ComponentImageManager; import de.rcenvironment.core.gui.resources.api.ImageManager; import de.rcenvironment.core.gui.resources.api.StandardImages; import de.rcenvironment.core.gui.utils.common.EditorsHelper; import de.rcenvironment.core.gui.utils.incubator.ContextMenuItemRemover; import de.rcenvironment.core.gui.wizards.toolintegration.ShowIntegrationEditWizardHandler; import de.rcenvironment.core.gui.wizards.toolintegration.ShowIntegrationRemoveHandler; import de.rcenvironment.core.gui.wizards.toolintegration.ShowIntegrationWizardHandler; import de.rcenvironment.core.gui.workflow.Activator; import de.rcenvironment.core.gui.workflow.EditorMouseWheelAndKeyListener; import de.rcenvironment.core.gui.workflow.GUIWorkflowDescriptionLoaderCallback; import de.rcenvironment.core.gui.workflow.WorkflowNodeLabelConnectionHelper; import de.rcenvironment.core.gui.workflow.editor.commands.WorkflowNodeDeleteCommand; import de.rcenvironment.core.gui.workflow.editor.commands.WorkflowNodeLabelConnectionCreateCommand; import de.rcenvironment.core.gui.workflow.editor.documentation.ToolIntegrationDocumentationGUIHelper; import de.rcenvironment.core.gui.workflow.editor.handlers.OpenConnectionEditorHandler; import de.rcenvironment.core.gui.workflow.editor.handlers.OpenConnectionsViewHandler; import de.rcenvironment.core.gui.workflow.editor.validator.WorkflowDescriptionValidationUtils; import de.rcenvironment.core.gui.workflow.parts.ConnectionPart; import de.rcenvironment.core.gui.workflow.parts.WorkflowEditorEditPartFactory; import de.rcenvironment.core.gui.workflow.parts.WorkflowNodePart; import de.rcenvironment.core.gui.workflow.parts.WorkflowPart; import de.rcenvironment.core.gui.workflow.view.Outline.OutlineView; import de.rcenvironment.core.utils.common.StringUtils; import de.rcenvironment.core.utils.incubator.ServiceRegistry; import de.rcenvironment.core.utils.incubator.ServiceRegistryPublisherAccess; /** * Editor window which opens when selecting a workflow file in the project explorer. * * @author Heinrich Wendel * @author Christian Weiss * @author Sascha Zur * @author Doreen Seider * @author Oliver Seebach * @author Robert Mischke * @author David Scholz * @author Goekhan Guerkan * @author Jan Flink * @author Martin Misiak */ public class WorkflowEditor extends GraphicalEditorWithFlyoutPalette implements ITabbedPropertySheetPageContributor, DistributedComponentKnowledgeListener { /** Property change event. */ public static final int PROP_FINAL_WORKFLOW_DESCRIPTION_SET = 0x300; /** Property change event. */ public static final int PROP_WORKFLOW_VAILDATION_FINISHED = 0x400; /** Constant. */ public static final String COMPONENTNAMES_WITH_VERSION = " (%s)"; /** Key for show labels preference. */ public static final String SHOW_LABELS_PREFERENCE_KEY = "showConnections"; protected static final int DEFAULT_TOLERANCE = 10; private static final String REMOTEACCESS = "remoteaccess"; private static final Log LOGGER = LogFactory.getLog(WorkflowEditor.class); private static final String DRAG_STATE = "DRAG_STATE"; private static final char SELECTION_KEYCODE = 's'; // for ALT + s as shortcut private static final char CONNECTION_KEYCODE = 'd'; // for ALT + d as shortcut private static final char OPEN_CONNECTION_VIEW_KEYCODE = 'c'; // for ALT + c as shortcut private static final String MENU_LISTENER_MARKER = "MENU_LISTENER_MARKER"; private static final String TOOL_DEACTIVATE_LABEL = "Deactivate Tool..."; private static final String TOOL_EDIT_LABEL = "Edit Tool..."; private static final String TOOL_INTEGRATE_LABEL = "Integrate Tool..."; private static final String TOOLINTEGRATION_ITEM = "toolIntegrationItem"; private static final int MINUS_ONE = -1; private static final int UNDO_LIMIT = 10; private static final int TILE_OFFSET = 30; private static final int TILE_SIZE = 60; protected WorkflowDescription workflowDescription; protected final ServiceRegistryPublisherAccess serviceRegistryAccess; private boolean allLabelsShown = false; private TabbedPropertySheetPage tabbedPropertySheetPage; private GraphicalViewer viewer; private ZoomManager zoomManager; private PaletteRoot paletteRoot; private MenuItem toolIntegrationPaletteMenuItem; private MenuItem editToolPaletteMenuItem; private MenuItem deactivateToolPaletteMenuItem; private MenuItem documentationToolPaletteMenuItem; private PaletteViewer paletteViewer = null; private ConnectionCreationToolEntry connectionCreationToolEntry = null; private int mouseX; private int mouseY; private final ToolIntegrationContextRegistry toolIntegrationRegistry; private ResourceTracker resourceListener = new ResourceTracker(); public WorkflowEditor() { serviceRegistryAccess = ServiceRegistry.createPublisherAccessFor(this); toolIntegrationRegistry = serviceRegistryAccess.getService(ToolIntegrationContextRegistry.class); setEditDomain(new DefaultEditDomain(this)); } public WorkflowDescription getWorkflowDescription() { return workflowDescription; } // Switch activate tool in palette to the Draw Connection tool private void switchToConnectionTool() { if (connectionCreationToolEntry == null) { for (Object paletteGroupObject : paletteViewer.getPaletteRoot().getChildren()) { if (paletteGroupObject instanceof PaletteGroup) { PaletteGroup paletteGroup = (PaletteGroup) paletteGroupObject; for (Object paletteEntryObject : paletteGroup.getChildren()) { if (paletteEntryObject instanceof ConnectionCreationToolEntry) { ConnectionCreationToolEntry entry = (ConnectionCreationToolEntry) paletteEntryObject; connectionCreationToolEntry = entry; paletteViewer.setActiveTool(entry); } } } } } else { paletteViewer.setActiveTool(connectionCreationToolEntry); } } // Switch activate tool in palette to the Selection tool private void switchToSelectionTool() { paletteViewer.setActiveTool(paletteViewer.getPaletteRoot().getDefaultEntry()); } public PaletteViewer getPaletteViewer() { return paletteViewer; } public CommandStack getEditorsCommandStack() { return getCommandStack(); } private void openConnectionEditor() { OpenConnectionsViewHandler openConnectionViewHandler = new OpenConnectionsViewHandler(); try { openConnectionViewHandler.execute(new ExecutionEvent()); } catch (ExecutionException e1) { e1.printStackTrace(); } } @Override protected PaletteRoot getPaletteRoot() { final List<ComponentInstallation> componentInstallations = new ArrayList<ComponentInstallation>(); IProgressService service = (IProgressService) PlatformUI.getWorkbench() .getService(IProgressService.class); try { service.run(false, false, new IRunnableWithProgress() { @Override public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { try { monitor.beginTask(Messages.fetchingComponents, 3); monitor.worked(2); componentInstallations.addAll(getInitialComponentKnowledge().getAllInstallations()); monitor.worked(1); } finally { monitor.done(); } } }); } catch (InvocationTargetException e) { throw new RuntimeException(e); } catch (InterruptedException e) { throw new RuntimeException(e); } WorkflowPaletteFactory factory = new WorkflowPaletteFactory(); paletteRoot = factory.createPalette(componentInstallations); return paletteRoot; } @Override protected void initializeGraphicalViewer() { viewer = getGraphicalViewer(); viewer.setRootEditPart(new ScalableFreeformRootEditPart()); viewer.setEditPartFactory(new WorkflowEditorEditPartFactory()); getCommandStack().setUndoLimit(UNDO_LIMIT); viewer.getControl().addKeyListener(new WorkflowEditorKeyListener()); viewer.setContents(workflowDescription); viewer.addDropTargetListener(new TemplateTransferDropTargetListener( viewer)); ContextMenuProvider cmProvider = new WorkflowEditorContextMenuProvider( viewer, getActionRegistry()); viewer.setContextMenu(cmProvider); getSite().registerContextMenu(cmProvider, viewer); zoomManager = ((ScalableFreeformRootEditPart) getGraphicalViewer().getRootEditPart()).getZoomManager(); zoomManager.setZoomAnimationStyle(ZoomManager.ANIMATE_ZOOM_IN_OUT); EditorMouseWheelAndKeyListener editorMouseWheelKeyListener = new EditorMouseWheelAndKeyListener(zoomManager); viewer.getControl().addMouseWheelListener(editorMouseWheelKeyListener); viewer.getControl().addKeyListener(editorMouseWheelKeyListener); tabbedPropertySheetPage = new TabbedPropertySheetPage(this); registerChangeListeners(); viewer.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent selectionChangedEvent) { StructuredSelection structuredSelection = ((StructuredSelection) selectionChangedEvent.getSelection()); for (Object structuredSelectionObject : structuredSelection.toList()) { if (structuredSelectionObject instanceof ConnectionPart) { ConnectionPart connectionPart = ((ConnectionPart) structuredSelectionObject); if (viewer.getSelectedEditParts().contains(connectionPart)) { connectionPart.getConnectionFigure().setForegroundColor(ColorConstants.blue); connectionPart.showLabel(); } } if (structuredSelectionObject instanceof WorkflowNodePart) { WorkflowNodePart nodePart = (WorkflowNodePart) structuredSelectionObject; ComponentInterface ci = ((WorkflowNode) nodePart.getModel()).getComponentDescription().getComponentInstallation() .getComponentRevision() .getComponentInterface(); String id = ci.getIdentifier().substring(0, ci.getIdentifier().lastIndexOf(ComponentConstants.ID_SEPARATOR)); if (toolIntegrationRegistry.hasId(id)) { PlatformUI.getWorkbench().getHelpSystem().setHelp(viewer.getControl(), ToolIntegrationConstants.CONTEXTUAL_HELP_PLACEHOLDER_ID); } else { PlatformUI.getWorkbench().getHelpSystem().setHelp(viewer.getControl(), id); } } else { PlatformUI.getWorkbench().getHelpSystem().setHelp(viewer.getControl(), null); } } removeConnectionColorsAndLabel(); } }); viewer.getControl().setData(DRAG_STATE, false); viewer.getControl().addDragDetectListener(new DragDetectListener() { @Override public void dragDetected(DragDetectEvent arg0) { // mark control as currently dragging to prevent erroneous selection of connection viewer.getControl().setData(DRAG_STATE, true); } }); viewer.getControl().addMouseListener(new MouseListener() { @Override public void mouseUp(MouseEvent ev) { // only try to select connection when no dragging is active if (!((boolean) viewer.getControl().getData(DRAG_STATE))) { selectConnection(ev); } viewer.getControl().setData(DRAG_STATE, false); } @Override public void mouseDown(MouseEvent ev) { selectConnection(ev); mouseX = ev.x; mouseY = ev.y; } @Override public void mouseDoubleClick(MouseEvent ev) { // Open Connection Editor filtered to the selected connection ConnectionPart connectionPart = selectConnection(ev); if (connectionPart != null) { WorkflowNode source = null; WorkflowNode target = null; if (connectionPart.getSource().getModel() instanceof WorkflowNode) { source = (WorkflowNode) connectionPart.getSource().getModel(); } if (connectionPart.getTarget().getModel() instanceof WorkflowNode) { target = (WorkflowNode) connectionPart.getTarget().getModel(); } OpenConnectionEditorHandler openConnectionEditorHandler = new OpenConnectionEditorHandler(source, target); try { openConnectionEditorHandler.execute(new ExecutionEvent()); } catch (ExecutionException e1) { e1.printStackTrace(); } } } }); // Snap to grid and geometry actions, enable geometry automatically. getActionRegistry().registerAction(new ToggleGridAction(getGraphicalViewer())); getActionRegistry().registerAction(new ToggleSnapToGeometryAction(getGraphicalViewer())); getViewer().setProperty(SnapToGeometry.PROPERTY_SNAP_ENABLED, true); getViewer().setProperty(SnapToGrid.PROPERTY_GRID_SPACING, new Dimension((WorkflowNodePart.SMALL_WORKFLOW_NODE_WIDTH - 1) / 2, (WorkflowNodePart.SMALL_WORKFLOW_NODE_WIDTH - 1) / 2)); // register activate context for context sensitive key bindings IContextService contextService = (IContextService) getSite().getService(IContextService.class); contextService.activateContext("de.rcenvironment.rce.gui.workflow.editor.scope"); // preferences store - initialize labels not to be shown IPreferenceStore preferenceStore = Activator.getInstance().getPreferenceStore(); preferenceStore.setValue(WorkflowEditor.SHOW_LABELS_PREFERENCE_KEY, false); // remove unwanted menu entries from workflow editor's context menu ContextMenuItemRemover.removeUnwantedMenuEntries(viewer.getControl()); ResourcesPlugin.getWorkspace().addResourceChangeListener(resourceListener); } /** * Shows the number of channels for all connections. */ public void showAllConnectionLabels() { for (Object connectionPartObject : viewer.getEditPartRegistry().values()) { if (connectionPartObject instanceof ConnectionPart) { ((ConnectionPart) connectionPartObject).showLabel(); } } } /** * Hides the number of channel for all connections. */ public void hideUnselectedConnectionLabels() { for (Object connectionPartObject : viewer.getEditPartRegistry().values()) { if (connectionPartObject instanceof ConnectionPart) { ConnectionPart part = ((ConnectionPart) connectionPartObject); // only hide label if connection is not selected int selectedCode = 2; if (part.getSelected() != selectedCode) { part.hideLabel(); } } } } private void removeConnectionColorsAndLabel() { for (Object connectionPartObject : viewer.getEditPartRegistry().values()) { if (connectionPartObject instanceof ConnectionPart && !viewer.getSelectedEditParts().contains(connectionPartObject)) { ConnectionPart connectionPart = (ConnectionPart) connectionPartObject; connectionPart.getConnectionFigure().setForegroundColor(ColorConstants.black); IPreferenceStore prefs = Activator.getInstance().getPreferenceStore(); boolean labelsVisible = prefs.getBoolean(SHOW_LABELS_PREFERENCE_KEY); // reset color and selection only when not selected if (!labelsVisible) { connectionPart.hideLabel(); } } } } private ConnectionPart selectConnection(MouseEvent ev) { for (Object editPart : viewer.getEditPartRegistry().values()) { if (editPart instanceof ConnectionPart) { int offsetX = ((FigureCanvas) getViewer().getControl()).getViewport().getViewLocation().x; int offsetY = ((FigureCanvas) getViewer().getControl()).getViewport().getViewLocation().y; ConnectionPart connectionPart = ((ConnectionPart) editPart); PointList connectionPoints = connectionPart.getConnectionFigure().getPoints(); Rectangle toleranceRectangle = new Rectangle(ev.x + offsetX - DEFAULT_TOLERANCE / 2, ev.y + offsetY - DEFAULT_TOLERANCE / 2, DEFAULT_TOLERANCE, DEFAULT_TOLERANCE); if (connectionPoints.intersects(toleranceRectangle)) { viewer.select(connectionPart); viewer.reveal(connectionPart); return connectionPart; } } } return null; } @Override public void dispose() { serviceRegistryAccess.dispose(); super.dispose(); } @Override protected PaletteViewerProvider createPaletteViewerProvider() { return new PaletteViewerProvider(getEditDomain()) { @Override protected void configurePaletteViewer(final PaletteViewer v) { super.configurePaletteViewer(v); paletteViewer = v; v.getControl().addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { if (e.stateMask == SWT.ALT && e.keyCode == CONNECTION_KEYCODE) { switchToConnectionTool(); } else if (e.stateMask == SWT.ALT && e.keyCode == SELECTION_KEYCODE) { switchToSelectionTool(); } } }); // adds tool integration add, edit and deactivate wizards to palette's context menu v.getControl().addMenuDetectListener(new MenuDetectListener() { @Override public void menuDetected(MenuDetectEvent menuDetectEvent) { final Menu menu = ((Control) menuDetectEvent.widget).getMenu(); // prevents multiple listener registration if (menu.getData(MENU_LISTENER_MARKER) == null) { menu.setData(MENU_LISTENER_MARKER, true); menu.addMenuListener(new MenuAdapter() { @Override public void menuShown(MenuEvent menuEvent) { Object selection = ((StructuredSelection) v.getSelection()).getFirstElement(); if (selection instanceof EditPart) { String toolName = ((PaletteEntry) ((EditPart) selection).getModel()).getDescription(); if (toolName != null && getSelectedPaletteComponent(toolName) != null && getSelectedPaletteComponent(toolName).getInstallationId() .matches(ToolIntegrationConstants.CONTEXTUAL_HELP_PLACEHOLDER_ID)) { extendPaletteContextMenu(menu, getSelectedPaletteComponent(toolName).getInstallationId()); } } } private void extendPaletteContextMenu(Menu menu, String toolID) { // add separator MenuItem separator = new MenuItem(menu, SWT.SEPARATOR); separator.setData(TOOLINTEGRATION_ITEM, true); // add tool integration menu items addShowToolIntegrationWizard(menu); addShowEditToolIntegrationWizard(menu); addShowDeleteToolIntegrationWizard(menu); addGetDocumentation(menu, toolID); } }); } } }); v.getControl().addMouseListener(new MouseAdapter() { private final int offset = 20; @Override public void mouseDoubleClick(MouseEvent e) { if (v.getActiveTool().getLabel().equals(WorkflowLabel.PALETTE_ENTRY_NAME)) { WorkflowLabel label = new WorkflowLabel(WorkflowLabel.INITIAL_TEXT); WorkflowDescription model = (WorkflowDescription) viewer.getContents().getModel(); // Proper size is set within the command Rectangle rectangle = new Rectangle(TILE_OFFSET, TILE_OFFSET, MINUS_ONE, MINUS_ONE); WorkflowNodeLabelConnectionHelper helper = new WorkflowNodeLabelConnectionHelper(label, model, rectangle); WorkflowNodeLabelConnectionCreateCommand createCommand = helper.createCommand(); getEditorsCommandStack().execute(createCommand); getExistingPaletteGroups(); v.setActiveTool(v.getPaletteRoot().getDefaultEntry()); } WorkflowDescription model = (WorkflowDescription) viewer.getContents().getModel(); ComponentInstallation installation = getSelectedPaletteComponent(v.getActiveTool().getLabel()); // Set bounds of new component, if intersects with existing translate by // 30,30 Rectangle rectangle = new Rectangle(TILE_OFFSET, TILE_OFFSET, TILE_SIZE, TILE_SIZE); for (WorkflowNode node : model.getWorkflowNodes()) { Rectangle nodeRect = new Rectangle(node.getX(), node.getY(), TILE_SIZE, TILE_SIZE); if (nodeRect.intersects(rectangle)) { rectangle.translate(offset, offset); } } // if tool was found, add it if (installation != null) { ComponentDescription description = new ComponentDescription(installation); description.initializeWithDefaults(); WorkflowNode node = new WorkflowNode(description); WorkflowNodeLabelConnectionHelper helper = new WorkflowNodeLabelConnectionHelper(node, model, rectangle); WorkflowNodeLabelConnectionCreateCommand createCommand = helper.createCommand(); getEditorsCommandStack().execute(createCommand); // activate properties tab for added node for (Object editpart : viewer.getContents().getChildren()) { if (editpart instanceof EditPart && editpart instanceof WorkflowNodePart) { EditPart currentEditPart = (EditPart) editpart; if (((WorkflowNode) currentEditPart.getModel()).equals(node)) { viewer.select(currentEditPart); tabbedPropertySheetPage.selectionChanged(WorkflowEditor.this, viewer.getSelection()); break; } } } // set active tool to "select" when double click was performed. // getExistingPaletteGroups() has to be called, for whatever reason getExistingPaletteGroups(); v.setActiveTool(v.getPaletteRoot().getDefaultEntry()); } } }); v.addDragSourceListener(new TemplateTransferDragSourceListener(v)); } }; } private ComponentInstallation getSelectedPaletteComponent(final String label) { PlatformService platformService = serviceRegistryAccess.getService(PlatformService.class); LogicalNodeId localNode = platformService.getLocalDefaultLogicalNodeId(); Collection<ComponentInstallation> installations = getInitialComponentKnowledge().getAllInstallations(); installations = ComponentUtils.eliminateComponentInterfaceDuplicates(installations, localNode); ComponentInstallation installation = null; for (ComponentInstallation inst : installations) { String name = (inst.getComponentRevision().getComponentInterface().getDisplayName()); if (inst.getComponentRevision().getComponentInterface().getVersion() != null && (toolIntegrationRegistry.hasId(inst.getComponentRevision().getComponentInterface().getIdentifier()) || inst .getComponentRevision().getComponentInterface().getIdentifier() .startsWith(ComponentConstants.COMPONENT_IDENTIFIER_PREFIX + REMOTEACCESS))) { name = name + StringUtils.format(COMPONENTNAMES_WITH_VERSION, inst.getComponentRevision().getComponentInterface() .getVersion()); } if (name.equals(label)) { installation = inst; break; } } return installation; } @Override protected void configureGraphicalViewer() { super.configureGraphicalViewer(); getGraphicalControl().setVisible(false); } /** * Used in {@link #setInput(IEditorInput)}. Can be overridden. */ protected void loadWorkflowFromFile(final File wfFile, final GUIWorkflowDescriptionLoaderCallback wfdc) { if (wfFile != null) { Job job = new Job(Messages.openWorkflow) { @Override protected IStatus run(IProgressMonitor monitor) { try { monitor.beginTask(Messages.loadingComponents, 2); monitor.worked(1); WorkflowExecutionService workflowExecutionService = serviceRegistryAccess.getService(WorkflowExecutionService.class); workflowDescription = workflowExecutionService .loadWorkflowDescriptionFromFileConsideringUpdates(wfFile, wfdc); initializeWorkflowDescriptionListener(); monitor.worked(1); Display.getDefault().asyncExec(new Runnable() { @Override public void run() { if (viewer.getControl() != null) { viewer.setContents(workflowDescription); getGraphicalControl().setVisible(true); if (getEditorSite() != null) { setFocus(); } validateWorkflow(); firePropertyChange(PROP_FINAL_WORKFLOW_DESCRIPTION_SET); } } }); } catch (final WorkflowFileException e) { LogFactory.getLog(getClass()).error("Failed to open workflow: " + wfFile.getAbsolutePath(), e); Display.getDefault().asyncExec(new Runnable() { @Override public void run() { // do not use Display.getDefault().getActiveShell() as this might return // the progress monitor dialog closeEditorAndShowMessage(e.getMessage()); } }); } finally { monitor.done(); } return Status.OK_STATUS; }; }; job.setUser(true); job.schedule(); } } @Override protected void setInput(final IEditorInput input) { super.setInput(input); workflowDescription = new WorkflowDescription(""); GUIWorkflowDescriptionLoaderCallback workflowDescriptionLoader = null; final File wfFile; if (input instanceof FileEditorInput) { FileEditorInput fileEditorInput = (FileEditorInput) input; IFile workspaceWfFile = fileEditorInput.getFile(); workflowDescriptionLoader = new GUIWorkflowDescriptionLoaderCallback(workspaceWfFile); if (workspaceWfFile != null && workspaceWfFile.getRawLocation() != null) { setPartName(workspaceWfFile.getName()); wfFile = new File(workspaceWfFile.getLocation().toOSString()); } else { closeEditorAndShowMessage(StringUtils.format("Workflow file could not be found: %s", fileEditorInput.getFile())); wfFile = null; } } else if (input instanceof FileStoreEditorInput) { FileStoreEditorInput fileStoreEditorInput = (FileStoreEditorInput) input; wfFile = new File(fileStoreEditorInput.getURI()); setPartName(wfFile.getName()); workflowDescriptionLoader = new GUIWorkflowDescriptionLoaderCallback(); } else { // should not happen MessageDialog.openError(Display.getDefault().getActiveShell(), "Workflow File Error", "Failed to load workflow file for an unknown reason."); wfFile = null; } loadWorkflowFromFile(wfFile, workflowDescriptionLoader); } protected void closeEditorAndShowMessage(final String message) { MessageDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), "Workflow File Error", message); WorkflowEditor.this.getSite().getPage().closeEditor(WorkflowEditor.this, false); } /** * Makes the editor listen to changes in the underlying {@link WorkflowDescription}. */ protected void initializeWorkflowDescriptionListener() { workflowDescription.addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { WorkflowEditor.this.updateDirty(); } }); } protected void updateDirty() { firePropertyChange(IEditorPart.PROP_DIRTY); } @Override public void doSave(IProgressMonitor monitor) { try { if (getEditorInput() instanceof IFileEditorInput) { IFile file = ((IFileEditorInput) getEditorInput()).getFile(); if (file.exists()) { WorkflowDescriptionPersistenceHandler wdHandler = new WorkflowDescriptionPersistenceHandler(); workflowDescription = updateExecutionInformation(workflowDescription, wdHandler, file.getRawLocation().toFile()); file.setContents( new ByteArrayInputStream(wdHandler.writeWorkflowDescriptionToStream(workflowDescription).toByteArray()), true, // keep saving, even if IFile is out of sync with the Workspace false, // dont keep history monitor); // progress monitor workflowDescription.firePropertyChange(WorkflowDescription.PROPERTY_NODES); workflowDescription.firePropertyChange(WorkflowDescription.PROPERTY_LABEL); } else { doSaveAs(); } } else if (getEditorInput() instanceof FileStoreEditorInput) { File file = new File(((FileStoreEditorInput) getEditorInput()).getURI().getPath().replaceFirst("/", "")); WorkflowDescriptionPersistenceHandler wdHandler = new WorkflowDescriptionPersistenceHandler(); try (ByteArrayOutputStream outStream = wdHandler.writeWorkflowDescriptionToStream(workflowDescription);) { if (file.canWrite()) { FileUtils.writeByteArrayToFile(file, outStream.toByteArray()); } } } getCommandStack().markSaveLocation(); } catch (CoreException e) { throw new RuntimeException(e); } catch (IOException e) { throw new RuntimeException(e); } catch (OutOfMemoryError error) { showMemoryExceedingWarningMessage(); error.printStackTrace(); } // set the dirty state relative to the current command stack position getCommandStack().markSaveLocation(); validateWorkflow(); } // get the latest execution information (executing nodes for wf controller and components) from underlying .wf file and set this // information to the given workflow description needed to ensure that changes made by the workflow execution wizard regarding executing // nodes are not overwritten by the workflow editor which must not change those information at all (consequence of merging workflow and // execution information in one .wf file which is intended to be changed anyway) --seid_do private WorkflowDescription updateExecutionInformation(WorkflowDescription wd, WorkflowDescriptionPersistenceHandler wdHandler, File file) { try { try (FileInputStream fileInputStream = new FileInputStream(file)) { String workflowControllerNodeId = wdHandler.readWorkflowControllerNodeId(fileInputStream); wd.setControllerNode(NodeIdentifierUtils .parseArbitraryIdStringToLogicalNodeIdWithExceptionWrapping(workflowControllerNodeId)); } try (FileInputStream fileInputStream = new FileInputStream(file)) { Map<String, String> componentControllerNodeIds = wdHandler.readComponentControllerNodeIds(fileInputStream); for (WorkflowNode wn : wd.getWorkflowNodes()) { ComponentInstallationBuilder builder = ComponentInstallationBuilder.fromComponentInstallation(wn.getComponentDescription().getComponentInstallation()); if (componentControllerNodeIds.containsKey(wn.getIdentifier())) { // newly added components doesn't appear in the map String compNodeId = componentControllerNodeIds.get(wn.getIdentifier()); builder.setNodeId(NodeIdentifierUtils .parseArbitraryIdStringToLogicalNodeIdWithExceptionWrapping(compNodeId)); } wn.getComponentDescription().setComponentInstallation(builder.build()); } } } catch (IOException e) { LOGGER.error("Failed to consider stored execution information on workflow saving", e); } return wd; } private void validateWorkflow() { List<?> list = viewer.getRootEditPart().getChildren(); WorkflowDescriptionValidationUtils.validateWorkflowDescription(workflowDescription, false, true); for (Object object : list) { if (object instanceof WorkflowPart) { WorkflowPart workflowPart = (WorkflowPart) object; List<?> children = workflowPart.getChildren(); for (Object child : children) { if (child instanceof WorkflowNodePart) { WorkflowNodePart workflowNodePart = (WorkflowNodePart) child; if (!((WorkflowNode) workflowNodePart.getModel()).isValid()) { workflowNodePart.updateValid(); } } } } } firePropertyChange(PROP_WORKFLOW_VAILDATION_FINISHED); } private void cleanNewDescriptionOfDisabledAndNotAvailableNodes(WorkflowDescription newWorkflowDescription) { Set<WorkflowNode> nodesToDelete = new HashSet<>(); nodesToDelete.addAll(getDisabledNodes(newWorkflowDescription)); nodesToDelete.addAll(getNotAvailableNodes(newWorkflowDescription)); if (!nodesToDelete.isEmpty()) { new WorkflowNodeDeleteCommand(newWorkflowDescription, new ArrayList<WorkflowNode>(nodesToDelete)).execute(); } } private List<WorkflowNode> getInvalidWorkflowNodes(WorkflowDescription newWorkflowDescription) { List<WorkflowNode> result = new ArrayList<>(); for (WorkflowNode node : newWorkflowDescription.getWorkflowNodes()) { if (!node.isValid()) { result.add(node); } } return result; } private List<WorkflowNode> getNotAvailableNodes(WorkflowDescription newWorkflowDescription) { List<WorkflowNode> result = new ArrayList<>(); for (WorkflowNode node : newWorkflowDescription.getWorkflowNodes()) { if (!isNodeAvailable(node)) { result.add(node); } } return result; } private List<WorkflowNode> getDisabledNodes(WorkflowDescription newWorkflowDescription) { List<WorkflowNode> result = new ArrayList<>(); for (WorkflowNode node : newWorkflowDescription.getWorkflowNodes()) { if (!node.isEnabled()) { result.add(node); } } return result; } private boolean isNodeAvailable(WorkflowNode node) { return !node.getComponentDescription().getIdentifier().startsWith(ComponentUtils.MISSING_COMPONENT_PREFIX); } private void markTargetsOfInvalidOrDisabledOrNotAvailableNodesInvalid(WorkflowDescription newWorkflowDescription) { Set<WorkflowNode> nodesOfInterest = new HashSet<>(); nodesOfInterest.addAll(getInvalidWorkflowNodes(newWorkflowDescription)); nodesOfInterest.addAll(getNotAvailableNodes(newWorkflowDescription)); nodesOfInterest.addAll(getDisabledNodes(newWorkflowDescription)); for (WorkflowNode node : nodesOfInterest) { for (Connection connection : newWorkflowDescription.getConnections()) { if (connection.getSourceNode().equals(node) && connection.getTargetNode().isEnabled() && !nodesOfInterest.contains(connection.getTargetNode())) { EndpointDescription inputEp = connection.getInput(); EndpointDefinition.InputExecutionContraint exeConstraint = inputEp.getEndpointDefinition() .getDefaultInputExecutionConstraint(); if (inputEp.getMetaDataValue(ComponentConstants.INPUT_METADATA_KEY_INPUT_EXECUTION_CONSTRAINT) != null) { exeConstraint = EndpointDefinition.InputExecutionContraint.valueOf( inputEp.getMetaDataValue(ComponentConstants.INPUT_METADATA_KEY_INPUT_EXECUTION_CONSTRAINT)); } if (exeConstraint.equals(EndpointDefinition.InputExecutionContraint.Required)) { newWorkflowDescription.getWorkflowNode(connection.getTargetNode().getIdentifier()).setValid(false); // this triggers a visual update of the component in the editor later on workflowDescription.getWorkflowNode(connection.getTargetNode().getIdentifier()).setValid(false); } } } } } @Override public void doSaveAs() { FileDialog fd = new FileDialog(new Shell(), SWT.SAVE); fd.setText("Save As..."); String[] filterExt = { "*.wf" }; fd.setFilterExtensions(filterExt); fd.setFilterPath(ResourcesPlugin.getWorkspace().getRoot().getLocation().toString()); String selected = fd.open(); if (selected == null) { return; } if (!selected.substring(selected.lastIndexOf('.') + 1).toLowerCase().equals("wf")) { selected += ".wf"; } File file = null; try { file = new File(selected); FileWriter fw = new FileWriter(file); WorkflowDescriptionPersistenceHandler wdHandler = new WorkflowDescriptionPersistenceHandler(); byte[] stream = wdHandler.writeWorkflowDescriptionToStream(workflowDescription).toByteArray(); for (byte element : stream) { fw.append((char) element); // progress monitor } fw.flush(); fw.close(); this.getEditorSite().getPage().closeEditor(this, false); IWorkspace workspace = ResourcesPlugin.getWorkspace(); if (file.getAbsolutePath().startsWith(workspace.getRoot().getFullPath().toFile().getAbsolutePath())) { IFile[] ifile = workspace.getRoot().findFilesForLocationURI(file.toURI()); if (ifile.length == 1) { EditorsHelper.openFileInEditor(ifile[0]); } } else { EditorsHelper.openExternalFileInEditor(file); LOGGER.warn("Saved workflow openend as external file (not in workspace location). Executing the workflow might not work."); } } catch (IOException e) { throw new RuntimeException(e); } catch (OutOfMemoryError error) { if (file != null) { file.deleteOnExit(); } showMemoryExceedingWarningMessage(); error.printStackTrace(); } catch (PartInitException e) { LOGGER.warn("Could not open new file. ", e); } // Refresh current project try { ResourcesPlugin.getWorkspace().getRoot().refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor()); } catch (CoreException e) { LOGGER.warn("Could not refresh Project Explorer. ", e); } } private void showMemoryExceedingWarningMessage() { MessageBox messageBox = new MessageBox(viewer.getControl().getShell(), SWT.ICON_WARNING | SWT.OK); messageBox.setMessage(Messages.memoryExceededWarningMessage); messageBox.setText(Messages.memoryExceededWarningHeading); messageBox.open(); } @Override public void commandStackChanged(EventObject event) { firePropertyChange(IEditorPart.PROP_DIRTY); super.commandStackChanged(event); } @Override public String getContributorId() { return getSite().getId(); } @Override public Object getAdapter(@SuppressWarnings("rawtypes") Class type) { if (type == IPropertySheetPage.class) { if (tabbedPropertySheetPage == null || tabbedPropertySheetPage.getControl() == null || tabbedPropertySheetPage.getControl().isDisposed()) { tabbedPropertySheetPage = new TabbedPropertySheetPage(this); } return tabbedPropertySheetPage; } else if (type == IContextProvider.class) { return new WorkflowEditorHelpContextProvider(viewer); } else if (type == IContentOutlinePage.class) { return new OutlineView(getGraphicalViewer()); } return super.getAdapter(type); } @Override protected FlyoutPreferences getPalettePreferences() { FlyoutPreferences prefs = super.getPalettePreferences(); prefs.setPaletteState(FlyoutPaletteComposite.STATE_PINNED_OPEN); return prefs; } @Override public boolean isSaveAsAllowed() { return true; } public GraphicalViewer getViewer() { return viewer; } /** * Registers an event listener for network changes as an OSGi service (whiteboard pattern). * * @param display */ private void registerChangeListeners() { serviceRegistryAccess.registerService(DistributedComponentKnowledgeListener.class, this); } private List<String> getExistingPaletteGroups() { List<String> paletteGroups = new ArrayList<String>(); for (Object child : paletteRoot.getChildren()) { if (child instanceof PaletteDrawer) { paletteGroups.add(((PaletteDrawer) child).getLabel()); } } return paletteGroups; } private List<String> getExistingPaletteEntries() { List<String> paletteEntries = new ArrayList<String>(); for (Object child : paletteRoot.getChildren()) { if (child instanceof PaletteDrawer) { for (Object innerChild : ((PaletteDrawer) child).getChildren()) { if (innerChild instanceof PaletteEntry) { paletteEntries.add(((PaletteEntry) innerChild) .getLabel()); } } } } return paletteEntries; } private List<String> getExistingComponentNames(Collection<ComponentInstallation> cis) { List<String> existingComponentNames = new ArrayList<String>(); for (ComponentInstallation installation : cis) { String name = installation.getComponentRevision().getComponentInterface().getDisplayName(); if (installation.getComponentRevision().getComponentInterface().getVersion() != null && (toolIntegrationRegistry.hasId(installation.getComponentRevision().getComponentInterface().getIdentifier()) || installation.getComponentRevision().getComponentInterface().getIdentifier() .startsWith(ComponentConstants.COMPONENT_IDENTIFIER_PREFIX + "remoteaccess"))) { name = name + StringUtils.format(COMPONENTNAMES_WITH_VERSION, installation.getComponentRevision().getComponentInterface() .getVersion()); } existingComponentNames.add(name); } return existingComponentNames; } private CombinedTemplateCreationEntry createPaletteEntry(ComponentInstallation installation) { // set the default platform of the ComponendDescription // to null ComponentInterface componentInterface = installation.getComponentRevision().getComponentInterface(); // prepare the icon of the component ImageDescriptor imageDescriptor = null; Image image = ComponentImageManager.getInstance().getIcon16Image(componentInterface); if (image == null) { imageDescriptor = Activator.getInstance().getImageRegistry().getDescriptor(Activator.IMAGE_RCE_ICON_16); } else { imageDescriptor = ImageDescriptor.createFromImage(image); } String name = componentInterface.getDisplayName(); if (componentInterface.getVersion() != null && (toolIntegrationRegistry.hasId(componentInterface.getIdentifier()) || componentInterface .getIdentifier().startsWith(ComponentConstants.COMPONENT_IDENTIFIER_PREFIX + REMOTEACCESS))) { name = name + StringUtils.format(COMPONENTNAMES_WITH_VERSION, componentInterface.getVersion()); } // create the palette entry CombinedTemplateCreationEntry component = new CombinedTemplateCreationEntry(name, name, new WorkflowNodeFactory(installation), imageDescriptor, imageDescriptor); return component; } private void addComponentToGroup(CombinedTemplateCreationEntry component, String groupLabel) { for (Object group : paletteRoot.getChildren()) { if (group instanceof PaletteDrawer) { if (((PaletteDrawer) group).getLabel().equals(groupLabel)) { ((PaletteDrawer) group).add(getIndexForComponentToAdd((PaletteDrawer) group, component.getLabel()), component); } } } } private int getIndexForComponentToAdd(PaletteDrawer group, String componentLabel) { int index = 0; for (Object child : group.getChildren()) { if (child instanceof PaletteEntry) { if (((PaletteEntry) child).getLabel().compareToIgnoreCase(componentLabel) > 0) { return index; } } index++; } return index; } private PaletteDrawer createPaletteDrawer(String groupLabel) { PaletteDrawer group = new PaletteDrawer(groupLabel); group.setDescription(groupLabel); group.setInitialState(PaletteDrawer.INITIAL_STATE_CLOSED); paletteRoot.add(getIndexForGroupToAdd(groupLabel), group); return group; } private int getIndexForGroupToAdd(String groupLabel) { int index = 0; // if group starts with underscore, append it to the end. if (groupLabel.startsWith("_")) { return paletteRoot.getChildren().size(); } for (Object group : paletteRoot.getChildren()) { if (group instanceof PaletteDrawer) { if (((PaletteDrawer) group).getLabel().compareToIgnoreCase(groupLabel) > 0) { return index; } } index++; } return index; } private void removeComponentFromGroup(PaletteDrawer group, PaletteEntry entry) { group.remove(entry); if (group.getChildren().size() <= 0) { paletteRoot.remove(group); } } private synchronized void refreshPalette(Collection<ComponentInstallation> cis) { // create entry lists List<String> paletteEntries = getExistingPaletteEntries(); List<String> paletteGroups = getExistingPaletteGroups(); List<String> componentNames = getExistingComponentNames(cis); // check for every component entry if contained in current palette - if not : add for (ComponentInstallation installation : cis) { String name = (installation.getComponentRevision().getComponentInterface().getDisplayName()); if (installation.getComponentRevision().getComponentInterface().getVersion() != null && (toolIntegrationRegistry.hasId(installation.getComponentRevision().getComponentInterface().getIdentifier()) || installation.getComponentRevision().getComponentInterface().getIdentifier() .startsWith(ComponentConstants.COMPONENT_IDENTIFIER_PREFIX + REMOTEACCESS))) { name = name + StringUtils.format(COMPONENTNAMES_WITH_VERSION, installation.getComponentRevision().getComponentInterface() .getVersion()); } if (!paletteEntries.contains(name)) { CombinedTemplateCreationEntry component = createPaletteEntry(installation); paletteEntries.add(name); String group = installation.getComponentRevision().getComponentInterface().getGroupName(); if (!paletteGroups.contains(group)) { createPaletteDrawer(group); paletteGroups.add(group); } addComponentToGroup(component, group); } } // check for every palette entry if contained in existing components - // if not : remove Map<PaletteDrawer, List<PaletteEntry>> componentsToRemove = new HashMap<PaletteDrawer, List<PaletteEntry>>(); for (Object group : paletteRoot.getChildren()) { if (group instanceof PaletteDrawer) { for (Object component : ((PaletteDrawer) group).getChildren()) { if (component instanceof PaletteEntry) { if (!componentNames.contains(((PaletteEntry) component).getLabel())) { if (!componentsToRemove.containsKey(group)) { componentsToRemove.put((PaletteDrawer) group, new ArrayList<PaletteEntry>()); } componentsToRemove.get(group).add((PaletteEntry) component); } } } } } for (PaletteDrawer group : componentsToRemove.keySet()) { for (PaletteEntry entry : componentsToRemove.get(group)) { removeComponentFromGroup(group, entry); } } } @Override public void onDistributedComponentKnowledgeChanged(DistributedComponentKnowledge newState) { final Collection<ComponentInstallation> cis = newState.getAllInstallations(); if (PlatformUI.isWorkbenchRunning() && !PlatformUI.getWorkbench().getDisplay().isDisposed()) { PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { @Override public void run() { if (viewer != null && viewer.getControl() != null && !viewer.getControl().isDisposed()) { refreshPalette(cis); // TODO review: Seems not to be necessary to set the viewers content at this place and causes the editor to refresh // the view (https://mantis.sc.dlr.de/view.php?id=14697). Was added in revision 18983 for unknown reasons. // flink 2016/11/04 // viewer.setContents(workflowDescription); } else { LogFactory.getLog(getClass()).warn("Got callback (onDistributedComponentKnowledgeChanged)" + " but widget(s) already disposed; the listener might not be disposed properly"); } } }); } } public int getMouseX() { return mouseX; } public int getMouseY() { return mouseY; } // removed as it causes NPE on start up, if connection is not established, when workflow is // opened under some circumstances // @Override // public void onDistributedComponentKnowledgeChanged(DistributedComponentKnowledge newState) { // // final Collection<ComponentInstallation> componentInstallations = // newState.getAllInstallations(); // // refreshWorkflowDescription(componentInstallations); // // if (PlatformUI.isWorkbenchRunning() && !PlatformUI.getWorkbench().getDisplay().isDisposed()) // { // // PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { // // @Override // public void run() { // viewer.setContents(workflowDescription); // WorkflowPart wfPart = (WorkflowPart) viewer.getRootEditPart().getChildren().get(0); // EditPart contents = wfPart.getViewer().getContents(); // for (Object o : contents.getChildren()) { // ((WorkflowNodePart) o).refresh(); // } // refreshPalette(componentInstallations); // } // }); // } // } // // // should be moved to non-gui code // private void refreshWorkflowDescription(Collection<ComponentInstallation> // componentInstallations) { // for (WorkflowNode workflowNode : workflowDescription.getWorkflowNodes()) { // ComponentInstallation componentInstallation = // workflowNode.getComponentDescription().getComponentInstallation(); // ComponentInstallation alternativeComponentInstallation = null; // if (componentInstallation.getComponentRevision().getComponentInterface().getIdentifier() // .startsWith(ComponentUtils.MISSING_COMPONENT_PREFIX)) { // alternativeComponentInstallation = ComponentUtils.getComponentInstallation( // componentInstallation.getComponentRevision().getComponentInterface() // .getIdentifier().replace(ComponentUtils.MISSING_COMPONENT_PREFIX, ""), // componentInstallations); // } else if (!componentInstallations.contains(componentInstallation)) { // // if it is not an user-integrated component (the interface of a user-integrated component // might changed, which results in // // synchronization issues with the underlying wf file and the workflow description in the // editor) // if (!toolIntegrationRegistry.hasId(componentInstallation.getComponentRevision() // .getComponentInterface().getIdentifier())) { // alternativeComponentInstallation = ComponentUtils.getComponentInstallation( // componentInstallation.getComponentRevision().getComponentInterface() // .getIdentifier(), componentInstallations); // } // if (alternativeComponentInstallation == null) { // ComponentInterface componentInterface = // componentInstallation.getComponentRevision().getComponentInterface(); // alternativeComponentInstallation = ComponentUtils.createPlaceholderComponentInstallation( // componentInterface.getIdentifier(), // componentInterface.getVersion(), // componentInterface.getDisplayName(), // componentInstallation.getNodeId()); // } // } // if (alternativeComponentInstallation != null) { // workflowNode.getComponentDescription() // .setComponentInstallation(alternativeComponentInstallation); // } // } // } private DistributedComponentKnowledge getInitialComponentKnowledge() { DistributedComponentKnowledgeService registry = serviceRegistryAccess.getService(DistributedComponentKnowledgeService.class); return registry.getCurrentComponentKnowledge(); } private void addShowToolIntegrationWizard(Menu menu) { toolIntegrationPaletteMenuItem = new MenuItem(menu, SWT.NONE); toolIntegrationPaletteMenuItem.setText(TOOL_INTEGRATE_LABEL); toolIntegrationPaletteMenuItem.setData(TOOLINTEGRATION_ITEM, true); toolIntegrationPaletteMenuItem.setImage(ImageManager.getInstance().getSharedImage(StandardImages.INTEGRATION_NEW)); toolIntegrationPaletteMenuItem.addSelectionListener(new SelectionListener() { @Override public void widgetSelected(SelectionEvent selectionEvent) { ShowIntegrationWizardHandler handler = new ShowIntegrationWizardHandler(); try { handler.execute(new ExecutionEvent()); } catch (ExecutionException e) { LogFactory.getLog(getClass()).error("Opening Tool Integration wizard failed", e); } } @Override public void widgetDefaultSelected(SelectionEvent selectionEvent) { widgetSelected(selectionEvent); } }); } private void addShowEditToolIntegrationWizard(Menu menu) { editToolPaletteMenuItem = new MenuItem(menu, SWT.NONE); editToolPaletteMenuItem.setText(TOOL_EDIT_LABEL); editToolPaletteMenuItem.setData(TOOLINTEGRATION_ITEM, true); editToolPaletteMenuItem.setImage(ImageManager.getInstance().getSharedImage(StandardImages.INTEGRATION_EDIT)); editToolPaletteMenuItem.addSelectionListener(new SelectionListener() { @Override public void widgetSelected(SelectionEvent selectionEvent) { ShowIntegrationEditWizardHandler handler = new ShowIntegrationEditWizardHandler(); try { handler.execute(new ExecutionEvent()); } catch (ExecutionException e) { LogFactory.getLog(getClass()).error("Opening Tool Edit wizard failed", e); } } @Override public void widgetDefaultSelected(SelectionEvent selectionEvent) { widgetSelected(selectionEvent); } }); } private void addShowDeleteToolIntegrationWizard(Menu menu) { deactivateToolPaletteMenuItem = new MenuItem(menu, SWT.NONE); deactivateToolPaletteMenuItem.setText(TOOL_DEACTIVATE_LABEL); deactivateToolPaletteMenuItem.setData(TOOLINTEGRATION_ITEM, true); deactivateToolPaletteMenuItem.setImage(ImageManager.getInstance().getSharedImage(StandardImages.INTEGRATION_REMOVE)); deactivateToolPaletteMenuItem.addSelectionListener(new SelectionListener() { @Override public void widgetSelected(SelectionEvent selectionEvent) { ShowIntegrationRemoveHandler handler = new ShowIntegrationRemoveHandler(); try { handler.execute(new ExecutionEvent()); } catch (ExecutionException e) { LogFactory.getLog(getClass()).error("Opening Tool Deactivation wizard failed", e); } } @Override public void widgetDefaultSelected(SelectionEvent selectionEvent) { widgetSelected(selectionEvent); } }); } private void addGetDocumentation(Menu menu, final String toolID) { documentationToolPaletteMenuItem = new MenuItem(menu, SWT.NONE); documentationToolPaletteMenuItem.setText("Open Documentation"); documentationToolPaletteMenuItem.setData(TOOLINTEGRATION_ITEM, true); documentationToolPaletteMenuItem.addSelectionListener(new SelectionListener() { @Override public void widgetSelected(SelectionEvent selectionEvent) { ToolIntegrationDocumentationGUIHelper.getInstance().showComponentDocumentation(toolID); } @Override public void widgetDefaultSelected(SelectionEvent selectionEvent) { widgetSelected(selectionEvent); } }); } public boolean isAllLabelsShown() { return allLabelsShown; } public void setAllLabelsShown(boolean allLabelsShown) { this.allLabelsShown = allLabelsShown; } /** * Key listener that implements some shortcuts for the workflow editor. * * @author Oliver Seebach * @author Jascha Riedel(#0013977) moved selection and connection tool to ui.bindings */ private final class WorkflowEditorKeyListener implements KeyListener { @Override public void keyReleased(KeyEvent e) {} @Override public void keyPressed(KeyEvent e) { if (e.stateMask == SWT.ALT && e.keyCode == OPEN_CONNECTION_VIEW_KEYCODE) { openConnectionEditor(); } } } private void closeEditor(boolean save) { getSite().getPage().closeEditor(WorkflowEditor.this, save); } private void superSetInput(IEditorInput input) { if (getEditorInput() != null) { IFile file = ((IFileEditorInput) getEditorInput()).getFile(); file.getWorkspace().removeResourceChangeListener(resourceListener); } super.setInput(input); if (getEditorInput() != null) { IFile file = ((IFileEditorInput) getEditorInput()).getFile(); file.getWorkspace().addResourceChangeListener(resourceListener); setPartName(file.getName()); } } /** * This class listens to changes to the file system in the workspace, and makes changes accordingly. An open, saved file gets deleted = * close the editor. An open file gets renamed or moved = change the editor's input accordingly. * * @author Goekhan Guerkan */ private class ResourceTracker implements IResourceChangeListener, IResourceDeltaVisitor { @Override public void resourceChanged(IResourceChangeEvent event) { IResourceDelta delta = event.getDelta(); try { if (delta != null) { delta.accept(this); } } catch (CoreException exception) { throw new RuntimeException(exception); } } @Override public boolean visit(IResourceDelta delta) { if (delta == null || !(getEditorInput() instanceof IFileEditorInput) || !delta.getResource().equals(((IFileEditorInput) getEditorInput()).getFile())) { return true; } if (delta.getKind() == IResourceDelta.REMOVED) { Display display = getSite().getShell().getDisplay(); if ((IResourceDelta.MOVED_TO & delta.getFlags()) == 0) { // if the file was deleted display.asyncExec(new Runnable() { @Override public void run() { if (!isDirty()) { closeEditor(false); } } }); // moved or renamed } else { final IFile newFile = ResourcesPlugin.getWorkspace().getRoot().getFile(delta.getMovedToPath()); display.asyncExec(new Runnable() { @Override public void run() { superSetInput(new FileEditorInput(newFile)); } }); } } return false; } } }