http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/activities/dataflow/views/DataflowActivityViewFactory.java
----------------------------------------------------------------------
diff --git 
a/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/activities/dataflow/views/DataflowActivityViewFactory.java
 
b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/activities/dataflow/views/DataflowActivityViewFactory.java
new file mode 100644
index 0000000..e4a6ba0
--- /dev/null
+++ 
b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/activities/dataflow/views/DataflowActivityViewFactory.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program 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 for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ 
******************************************************************************/
+package org.apache.taverna.activities.dataflow.views;
+
+import java.util.Arrays;
+import java.util.List;
+
+import 
org.apache.taverna.activities.dataflow.servicedescriptions.DataflowTemplateService;
+import org.apache.taverna.servicedescriptions.ServiceDescriptionRegistry;
+import org.apache.taverna.ui.menu.MenuManager;
+import org.apache.taverna.workbench.activityicons.ActivityIconManager;
+import org.apache.taverna.workbench.configuration.colour.ColourManager;
+import 
org.apache.taverna.workbench.configuration.workbench.WorkbenchConfiguration;
+import org.apache.taverna.workbench.edits.EditManager;
+import org.apache.taverna.workbench.file.FileManager;
+import org.apache.taverna.workbench.selection.SelectionManager;
+import org.apache.taverna.workbench.ui.views.contextualviews.ContextualView;
+import 
org.apache.taverna.workbench.ui.views.contextualviews.activity.ContextualViewFactory;
+import org.apache.taverna.scufl2.api.activity.Activity;
+
+public class DataflowActivityViewFactory implements 
ContextualViewFactory<Activity> {
+
+       private EditManager editManager;
+       private FileManager fileManager;
+       private MenuManager menuManager;
+       private ColourManager colourManager;
+       private ActivityIconManager activityIconManager;
+       private WorkbenchConfiguration workbenchConfiguration;
+       private ServiceDescriptionRegistry serviceDescriptionRegistry;
+       private SelectionManager selectionManager;
+
+       public boolean canHandle(Object object) {
+               return object instanceof Activity
+                               && ((Activity) 
object).getType().equals(DataflowTemplateService.ACTIVITY_TYPE);
+       }
+
+       public List<ContextualView> getViews(Activity activity) {
+               return Arrays.asList(new ContextualView[] { new 
DataflowActivityContextualView(activity,
+                               editManager, fileManager, menuManager, 
activityIconManager, colourManager,
+                               serviceDescriptionRegistry, 
workbenchConfiguration, selectionManager) });
+       }
+
+       public void setEditManager(EditManager editManager) {
+               this.editManager = editManager;
+       }
+
+       public void setFileManager(FileManager fileManager) {
+               this.fileManager = fileManager;
+       }
+
+       public void setMenuManager(MenuManager menuManager) {
+               this.menuManager = menuManager;
+       }
+
+       public void setActivityIconManager(ActivityIconManager 
activityIconManager) {
+               this.activityIconManager = activityIconManager;
+       }
+
+       public void setColourManager(ColourManager colourManager) {
+               this.colourManager = colourManager;
+       }
+
+       public void setServiceDescriptionRegistry(ServiceDescriptionRegistry 
serviceDescriptionRegistry) {
+               this.serviceDescriptionRegistry = serviceDescriptionRegistry;
+       }
+
+       public void setWorkbenchConfiguration(WorkbenchConfiguration 
workbenchConfiguration) {
+               this.workbenchConfiguration = workbenchConfiguration;
+       }
+
+       public void setSelectionManager(SelectionManager selectionManager) {
+               this.selectionManager = selectionManager;
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/DataflowMerger.java
----------------------------------------------------------------------
diff --git 
a/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/DataflowMerger.java
 
b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/DataflowMerger.java
new file mode 100644
index 0000000..b1a839a
--- /dev/null
+++ 
b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/DataflowMerger.java
@@ -0,0 +1,124 @@
+package org.apache.taverna.workbench.file.importworkflow;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.taverna.workbench.edits.CompoundEdit;
+import org.apache.taverna.workbench.edits.Edit;
+import org.apache.taverna.workflow.edits.AddChildEdit;
+import org.apache.taverna.workflow.edits.AddDataLinkEdit;
+import org.apache.taverna.workflow.edits.AddProcessorEdit;
+import org.apache.taverna.workflow.edits.AddWorkflowInputPortEdit;
+import org.apache.taverna.workflow.edits.AddWorkflowOutputPortEdit;
+import org.apache.taverna.scufl2.api.common.AbstractCloneable;
+import org.apache.taverna.scufl2.api.container.WorkflowBundle;
+import org.apache.taverna.scufl2.api.core.ControlLink;
+import org.apache.taverna.scufl2.api.core.DataLink;
+import org.apache.taverna.scufl2.api.core.Processor;
+import org.apache.taverna.scufl2.api.core.Workflow;
+import org.apache.taverna.scufl2.api.port.InputWorkflowPort;
+import org.apache.taverna.scufl2.api.port.OutputWorkflowPort;
+
+/**
+ * A tool that allows merging of two workflow.
+ * <p>
+ * The merge is performed as a series of edit, inserting a copy of the source
+ * workflow into the destination workflow.
+ *
+ * @author Stian Soiland-Reyes
+ * @author David Withers
+ */
+public class DataflowMerger {
+
+       /**
+        * Make a copy of a workflow.
+        *
+        * @param source
+        *            workflow to copy
+        * @return A copy of the workflow.
+        */
+       public static Workflow copyWorkflow(Workflow source) {
+               WorkflowBundle workflowBundle = 
AbstractCloneable.cloneWorkflowBean(source.getParent());
+               return 
workflowBundle.getWorkflows().getByName(source.getName());
+       }
+
+       private final Workflow destinationWorkflow;
+
+       /**
+        * Construct a {@link DataflowMerger} for the given destination 
workflow.
+        *
+        * @param destinationWorkflow
+        *            Workflow to be merged into
+        */
+       public DataflowMerger(Workflow destinationWorkflow) {
+               this.destinationWorkflow = destinationWorkflow;
+       }
+
+       /**
+        * Make an {@link Edit} that when performed merges the given source 
dataflow
+        * into the destination dataflow.
+        * <p>
+        * Internally a copy is made of the source dataflow, to avoid modifying 
the
+        * links and processors.
+        *
+        * @param sourceDataflow
+        *            Dataflow to merge from
+        * @return An edit that can perform and undo the insertion of the 
components
+        *         from the source dataflow.
+        * @throws MergeException
+        *             If the merge cannot be performed.
+        */
+       public CompoundEdit getMergeEdit(Workflow sourceDataflow)
+                       throws MergeException {
+               return getMergeEdit(sourceDataflow, "");
+       }
+
+       /**
+        * Make an {@link Edit} that when performed merges the given source 
dataflow
+        * into the destination dataflow.
+        * <p>
+        * Internally a copy is made of the source dataflow, to avoid modifying 
the
+        * links and processors.
+        *
+        * @param sourceWorkflow
+        *            Dataflow to merge from
+        * @param prefix
+        *            A prefix which will be inserted in front of the names for 
the
+        *            merged workflow components.
+        * @return An edit that can perform and undo the insertion of the 
components
+        *         from the source dataflow.
+        * @throws MergeException
+        *             If the merge cannot be performed.
+        */
+       public CompoundEdit getMergeEdit(Workflow sourceWorkflow, String prefix)
+                       throws MergeException {
+               List<Edit<?>> compoundEdit = new ArrayList<>();
+
+               Workflow workflow = copyWorkflow(sourceWorkflow);
+
+               for (InputWorkflowPort input : workflow.getInputPorts()) {
+                       
destinationWorkflow.getInputPorts().addWithUniqueName(input);
+                       destinationWorkflow.getInputPorts().remove(input);
+                       compoundEdit.add(new 
AddWorkflowInputPortEdit(destinationWorkflow, input));
+               }
+               for (OutputWorkflowPort output : workflow.getOutputPorts()) {
+                       
destinationWorkflow.getOutputPorts().addWithUniqueName(output);
+                       destinationWorkflow.getOutputPorts().remove(output);
+                       compoundEdit.add(new 
AddWorkflowOutputPortEdit(destinationWorkflow, output));
+               }
+               for (Processor processor : workflow.getProcessors()) {
+                       processor.setName(prefix + processor.getName());
+                       compoundEdit.add(new 
AddProcessorEdit(destinationWorkflow, processor));
+               }
+               for (DataLink dataLink : workflow.getDataLinks()) {
+                       compoundEdit.add(new 
AddDataLinkEdit(destinationWorkflow, dataLink));
+               }
+               for (ControlLink controlLink : workflow.getControlLinks()) {
+                       compoundEdit.add(new 
AddChildEdit<Workflow>(destinationWorkflow, controlLink));
+               }
+
+               return new CompoundEdit(compoundEdit);
+
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/MergeException.java
----------------------------------------------------------------------
diff --git 
a/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/MergeException.java
 
b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/MergeException.java
new file mode 100644
index 0000000..889ebde
--- /dev/null
+++ 
b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/MergeException.java
@@ -0,0 +1,22 @@
+package org.apache.taverna.workbench.file.importworkflow;
+
+public class MergeException extends Exception {
+       private static final long serialVersionUID = 6018700359518335402L;
+
+       public MergeException() {
+               super();
+       }
+
+       public MergeException(String message, Throwable cause) {
+               super(message, cause);
+       }
+
+       public MergeException(String message) {
+               super(message);
+       }
+
+       public MergeException(Throwable cause) {
+               super(cause);
+       }
+       
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/AddNestedWorkflowAction.java
----------------------------------------------------------------------
diff --git 
a/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/AddNestedWorkflowAction.java
 
b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/AddNestedWorkflowAction.java
new file mode 100644
index 0000000..1286c71
--- /dev/null
+++ 
b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/AddNestedWorkflowAction.java
@@ -0,0 +1,59 @@
+package org.apache.taverna.workbench.file.importworkflow.actions;
+
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+
+import javax.swing.AbstractAction;
+
+import 
org.apache.taverna.activities.dataflow.servicedescriptions.DataflowActivityIcon;
+import org.apache.taverna.ui.menu.MenuManager;
+import org.apache.taverna.workbench.configuration.colour.ColourManager;
+import 
org.apache.taverna.workbench.configuration.workbench.WorkbenchConfiguration;
+import org.apache.taverna.workbench.edits.EditManager;
+import org.apache.taverna.workbench.file.FileManager;
+import 
org.apache.taverna.workbench.file.importworkflow.gui.ImportWorkflowWizard;
+import org.apache.taverna.workbench.selection.SelectionManager;
+import org.apache.taverna.workbench.ui.Utils;
+
+/**
+ * An action for adding a nested workflow.
+ *
+ * @author Stian Soiland-Reyes
+ *
+ */
+public class AddNestedWorkflowAction extends AbstractAction {
+       private static final long serialVersionUID = -2242979457902699028L;
+       private final EditManager editManager;
+       private final FileManager fileManager;
+       private final MenuManager menuManager;
+       private final ColourManager colourManager;
+       private final WorkbenchConfiguration workbenchConfiguration;
+       private final SelectionManager selectionManager;
+
+       public AddNestedWorkflowAction(EditManager editManager, FileManager 
fileManager,
+                       MenuManager menuManager, ColourManager colourManager,
+                       WorkbenchConfiguration workbenchConfiguration, 
SelectionManager selectionManager) {
+               super("Add nested workflow", 
DataflowActivityIcon.getDataflowIcon());
+               this.editManager = editManager;
+               this.fileManager = fileManager;
+               this.menuManager = menuManager;
+               this.colourManager = colourManager;
+               this.workbenchConfiguration = workbenchConfiguration;
+               this.selectionManager = selectionManager;
+       }
+
+       public void actionPerformed(ActionEvent e) {
+               final Component parentComponent;
+               if (e.getSource() instanceof Component) {
+                       parentComponent = (Component) e.getSource();
+               } else {
+                       parentComponent = null;
+               }
+               ImportWorkflowWizard wizard = new ImportWorkflowWizard(
+                               Utils.getParentFrame(parentComponent), 
editManager, fileManager, menuManager,
+                               colourManager, workbenchConfiguration, 
selectionManager);
+               wizard.setMergeEnabled(false);
+               wizard.setVisible(true);
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/ImportWorkflowAction.java
----------------------------------------------------------------------
diff --git 
a/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/ImportWorkflowAction.java
 
b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/ImportWorkflowAction.java
new file mode 100644
index 0000000..81774b3
--- /dev/null
+++ 
b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/ImportWorkflowAction.java
@@ -0,0 +1,59 @@
+package org.apache.taverna.workbench.file.importworkflow.actions;
+
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+
+import javax.swing.AbstractAction;
+
+import 
org.apache.taverna.activities.dataflow.servicedescriptions.DataflowActivityIcon;
+import org.apache.taverna.ui.menu.MenuManager;
+import org.apache.taverna.workbench.configuration.colour.ColourManager;
+import 
org.apache.taverna.workbench.configuration.workbench.WorkbenchConfiguration;
+import org.apache.taverna.workbench.edits.EditManager;
+import org.apache.taverna.workbench.file.FileManager;
+import 
org.apache.taverna.workbench.file.importworkflow.gui.ImportWorkflowWizard;
+import org.apache.taverna.workbench.selection.SelectionManager;
+import org.apache.taverna.workbench.ui.Utils;
+
+/**
+ * A general version of {@link AddNestedWorkflowAction} and {@link 
MergeWorkflowAction} that allows
+ * the user to choose which action to perform.
+ *
+ * @author Stian Soiland-Reyes
+ *
+ */
+public class ImportWorkflowAction extends AbstractAction {
+       private static final long serialVersionUID = -2242979457902699028L;
+       private final EditManager editManager;
+       private final FileManager fileManager;
+       private final MenuManager menuManager;
+       private final ColourManager colourManager;
+       private final WorkbenchConfiguration workbenchConfiguration;
+       private final SelectionManager selectionManager;
+
+       public ImportWorkflowAction(EditManager editManager, FileManager 
fileManager,
+                       MenuManager menuManager, ColourManager colourManager,
+                       WorkbenchConfiguration workbenchConfiguration, 
SelectionManager selectionManager) {
+               super("Import workflow", 
DataflowActivityIcon.getDataflowIcon());
+               this.editManager = editManager;
+               this.fileManager = fileManager;
+               this.menuManager = menuManager;
+               this.colourManager = colourManager;
+               this.workbenchConfiguration = workbenchConfiguration;
+               this.selectionManager = selectionManager;
+       }
+
+       public void actionPerformed(ActionEvent e) {
+               final Component parentComponent;
+               if (e.getSource() instanceof Component) {
+                       parentComponent = (Component) e.getSource();
+               } else {
+                       parentComponent = null;
+               }
+               ImportWorkflowWizard wizard = new ImportWorkflowWizard(
+                               Utils.getParentFrame(parentComponent), 
editManager, fileManager, menuManager,
+                               colourManager, workbenchConfiguration, 
selectionManager);
+               wizard.setVisible(true);
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/MergeWorkflowAction.java
----------------------------------------------------------------------
diff --git 
a/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/MergeWorkflowAction.java
 
b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/MergeWorkflowAction.java
new file mode 100644
index 0000000..136490b
--- /dev/null
+++ 
b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/MergeWorkflowAction.java
@@ -0,0 +1,58 @@
+package org.apache.taverna.workbench.file.importworkflow.actions;
+
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+
+import javax.swing.AbstractAction;
+
+import org.apache.taverna.ui.menu.MenuManager;
+import org.apache.taverna.workbench.configuration.colour.ColourManager;
+import 
org.apache.taverna.workbench.configuration.workbench.WorkbenchConfiguration;
+import org.apache.taverna.workbench.edits.EditManager;
+import org.apache.taverna.workbench.file.FileManager;
+import 
org.apache.taverna.workbench.file.importworkflow.gui.ImportWorkflowWizard;
+import org.apache.taverna.workbench.selection.SelectionManager;
+import org.apache.taverna.workbench.ui.Utils;
+
+/**
+ * An action for merging two workflows
+ *
+ * @author Stian Soiland-Reyes
+ *
+ */
+public class MergeWorkflowAction extends AbstractAction {
+       private static final long serialVersionUID = -2242979457902699028L;
+       private final EditManager editManager;
+       private final FileManager fileManager;
+       private final MenuManager menuManager;
+       private final ColourManager colourManager;
+       private final WorkbenchConfiguration workbenchConfiguration;
+       private final SelectionManager selectionManager;
+
+       public MergeWorkflowAction(EditManager editManager, FileManager 
fileManager,
+                       MenuManager menuManager, ColourManager colourManager,
+                       WorkbenchConfiguration workbenchConfiguration, 
SelectionManager selectionManager) {
+               super("Merge workflow");
+               this.editManager = editManager;
+               this.fileManager = fileManager;
+               this.menuManager = menuManager;
+               this.colourManager = colourManager;
+               this.workbenchConfiguration = workbenchConfiguration;
+               this.selectionManager = selectionManager;
+       }
+
+       public void actionPerformed(ActionEvent e) {
+               final Component parentComponent;
+               if (e.getSource() instanceof Component) {
+                       parentComponent = (Component) e.getSource();
+               } else {
+                       parentComponent = null;
+               }
+               ImportWorkflowWizard wizard = new ImportWorkflowWizard(
+                               Utils.getParentFrame(parentComponent), 
editManager, fileManager, menuManager,
+                               colourManager, workbenchConfiguration, 
selectionManager);
+               wizard.setNestedEnabled(false);
+               wizard.setVisible(true);
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/OpenSourceWorkflowAction.java
----------------------------------------------------------------------
diff --git 
a/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/OpenSourceWorkflowAction.java
 
b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/OpenSourceWorkflowAction.java
new file mode 100644
index 0000000..d3a110b
--- /dev/null
+++ 
b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/OpenSourceWorkflowAction.java
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * Copyright (C) 2013 The University of Manchester
+ *
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program 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 for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ 
******************************************************************************/
+package org.apache.taverna.workbench.file.importworkflow.actions;
+
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.io.File;
+import java.util.Arrays;
+import java.util.List;
+import java.util.prefs.Preferences;
+
+import javax.swing.AbstractAction;
+import javax.swing.JFileChooser;
+import javax.swing.JOptionPane;
+import javax.swing.filechooser.FileFilter;
+
+import org.apache.taverna.workbench.file.FileManager;
+import org.apache.taverna.workbench.icons.WorkbenchIcons;
+
+import org.apache.log4j.Logger;
+
+/**
+ * @author David Withers
+ */
+@SuppressWarnings("serial")
+public abstract class OpenSourceWorkflowAction extends AbstractAction {
+
+       private static Logger logger = 
Logger.getLogger(OpenSourceWorkflowAction.class);
+
+       private static final String OPEN_WORKFLOW = "Open workflow...";
+
+       protected FileManager fileManager;
+
+       public OpenSourceWorkflowAction(FileManager fileManager) {
+               super(OPEN_WORKFLOW, WorkbenchIcons.openIcon);
+               this.fileManager = fileManager;
+       }
+
+       public void actionPerformed(ActionEvent e) {
+               final Component parentComponent;
+               if (e.getSource() instanceof Component) {
+                       parentComponent = (Component) e.getSource();
+               } else {
+                       parentComponent = null;
+               }
+               openWorkflows(parentComponent);
+       }
+
+       public abstract void openWorkflows(Component parentComponent, File[] 
files);
+
+       /**
+        * Pop up an Open-dialogue to select one or more workflow files to open.
+        *
+        * @param parentComponent
+        *            The UI parent component to use for pop up dialogues
+        * @param openCallback
+        *            An {@link OpenCallback} to be called during the file 
opening.
+        *            The callback will be invoked for each file that has been
+        *            opened, as file opening happens in a separate thread that
+        *            might execute after the return of this method.
+        * @return <code>false</code> if no files were selected or the dialogue 
was
+        *         cancelled, or <code>true</code> if the process of opening 
one or
+        *         more files has been started.
+        */
+       public boolean openWorkflows(final Component parentComponent) {
+               JFileChooser fileChooser = new JFileChooser();
+               Preferences prefs = Preferences.userNodeForPackage(getClass());
+               String curDir = prefs.get("currentDir", 
System.getProperty("user.home"));
+               fileChooser.setDialogTitle(OPEN_WORKFLOW);
+
+               fileChooser.resetChoosableFileFilters();
+               fileChooser.setAcceptAllFileFilterUsed(false);
+               List<FileFilter> fileFilters = fileManager.getOpenFileFilters();
+               if (fileFilters.isEmpty()) {
+                       logger.warn("No file types found for opening workflow");
+                       JOptionPane
+                                       .showMessageDialog(parentComponent,
+                                                       "No file types found 
for opening workflow.", "Error",
+                                                       
JOptionPane.ERROR_MESSAGE);
+                       return false;
+               }
+               for (FileFilter fileFilter : fileFilters) {
+                       fileChooser.addChoosableFileFilter(fileFilter);
+               }
+
+               fileChooser.setFileFilter(fileFilters.get(0));
+
+               fileChooser.setCurrentDirectory(new File(curDir));
+               fileChooser.setMultiSelectionEnabled(true);
+
+               int returnVal = fileChooser.showOpenDialog(parentComponent);
+               if (returnVal == JFileChooser.APPROVE_OPTION) {
+                       prefs.put("currentDir", 
fileChooser.getCurrentDirectory().toString());
+                       final File[] selectedFiles = 
fileChooser.getSelectedFiles();
+                       if (selectedFiles.length == 0) {
+                               logger.warn("No files selected");
+                               return false;
+                       }
+                       new FileOpenerThread(parentComponent, 
selectedFiles).start();
+                       return true;
+               }
+               return false;
+       }
+
+       private final class FileOpenerThread extends Thread {
+               private final File[] files;
+               private final Component parentComponent;
+
+               private FileOpenerThread(Component parentComponent, File[] 
selectedFiles) {
+                       super("Opening workflows(s) " + 
Arrays.asList(selectedFiles));
+                       this.parentComponent = parentComponent;
+                       this.files = selectedFiles;
+               }
+
+               @Override
+               public void run() {
+                       openWorkflows(parentComponent, files);
+               }
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/ReplaceNestedWorkflowAction.java
----------------------------------------------------------------------
diff --git 
a/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/ReplaceNestedWorkflowAction.java
 
b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/ReplaceNestedWorkflowAction.java
new file mode 100644
index 0000000..7209ce7
--- /dev/null
+++ 
b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/ReplaceNestedWorkflowAction.java
@@ -0,0 +1,84 @@
+package org.apache.taverna.workbench.file.importworkflow.actions;
+
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+
+import org.apache.taverna.servicedescriptions.ServiceDescriptionRegistry;
+import org.apache.taverna.ui.menu.MenuManager;
+import org.apache.taverna.workbench.activityicons.ActivityIconManager;
+import org.apache.taverna.workbench.configuration.colour.ColourManager;
+import 
org.apache.taverna.workbench.configuration.workbench.WorkbenchConfiguration;
+import org.apache.taverna.workbench.edits.Edit;
+import org.apache.taverna.workbench.edits.EditManager;
+import org.apache.taverna.workbench.file.FileManager;
+import 
org.apache.taverna.workbench.file.importworkflow.gui.ImportWorkflowWizard;
+import org.apache.taverna.workbench.selection.SelectionManager;
+import org.apache.taverna.workbench.ui.Utils;
+import 
org.apache.taverna.workbench.ui.actions.activity.ActivityConfigurationAction;
+import org.apache.taverna.workflow.edits.ConfigureEdit;
+import org.apache.taverna.scufl2.api.activity.Activity;
+import org.apache.taverna.scufl2.api.configurations.Configuration;
+import org.apache.taverna.scufl2.api.core.Workflow;
+
+public class ReplaceNestedWorkflowAction extends ActivityConfigurationAction {
+       private static final long serialVersionUID = 1L;
+
+       private final EditManager editManager;
+       private final FileManager fileManager;
+       private final MenuManager menuManager;
+
+       private final ColourManager colourManager;
+
+       private final WorkbenchConfiguration workbenchConfiguration;
+
+       private final SelectionManager selectionManager;
+
+       public ReplaceNestedWorkflowAction(Activity activity, EditManager 
editManager,
+                       FileManager fileManager, MenuManager menuManager,
+                       ActivityIconManager activityIconManager, ColourManager 
colourManager,
+                       ServiceDescriptionRegistry serviceDescriptionRegistry,
+                       WorkbenchConfiguration workbenchConfiguration, 
SelectionManager selectionManager) {
+               super(activity, activityIconManager, 
serviceDescriptionRegistry);
+               this.editManager = editManager;
+               this.fileManager = fileManager;
+               this.menuManager = menuManager;
+               this.colourManager = colourManager;
+               this.workbenchConfiguration = workbenchConfiguration;
+               this.selectionManager = selectionManager;
+               putValue(NAME, "Replace nested workflow");
+       }
+
+       public void actionPerformed(ActionEvent e) {
+               final Component parentComponent;
+               if (e.getSource() instanceof Component) {
+                       parentComponent = (Component) e.getSource();
+               } else {
+                       parentComponent = null;
+               }
+               ImportWorkflowWizard wizard = new ImportWorkflowWizard(
+                               Utils.getParentFrame(parentComponent), 
editManager, fileManager, menuManager,
+                               colourManager, workbenchConfiguration, 
selectionManager) {
+                       private static final long serialVersionUID = 1L;
+
+//                     @Override
+//                     protected Edit<?> makeInsertNestedWorkflowEdit(Workflow 
nestedFlow, String name) {
+//                             Configuration configuration = new 
Configuration();
+//                             configuration.setType(null);
+//                             // TODO use service registry
+//                             return new 
ConfigureEdit<Activity>(getActivity(), null, configuration);
+//                     }
+
+//                     @Override
+//                     protected Activity getInsertedActivity() {
+//                             return getActivity();
+//                     }
+               };
+
+               wizard.setMergeEnabled(false);
+//             
wizard.setCustomDestinationDataflow(fileManager.getCurrentDataflow(),
+//                             "Existing nested workflow");
+//             wizard.setDestinationEnabled(false);
+               wizard.setVisible(true);
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/gui/ImportWorkflowWizard.java
----------------------------------------------------------------------
diff --git 
a/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/gui/ImportWorkflowWizard.java
 
b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/gui/ImportWorkflowWizard.java
new file mode 100644
index 0000000..6bf4cab
--- /dev/null
+++ 
b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/gui/ImportWorkflowWizard.java
@@ -0,0 +1,1272 @@
+package org.apache.taverna.workbench.file.importworkflow.gui;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Frame;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusAdapter;
+import java.awt.event.FocusEvent;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.io.File;
+import java.lang.reflect.InvocationTargetException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.swing.AbstractAction;
+import javax.swing.BorderFactory;
+import javax.swing.ButtonGroup;
+import javax.swing.ButtonModel;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.JTextField;
+import javax.swing.ProgressMonitor;
+import javax.swing.SwingUtilities;
+
+import 
org.apache.taverna.activities.dataflow.servicedescriptions.DataflowTemplateService;
+import org.apache.taverna.ui.menu.MenuManager;
+import org.apache.taverna.workbench.MainWindow;
+import org.apache.taverna.workbench.configuration.colour.ColourManager;
+import 
org.apache.taverna.workbench.configuration.workbench.WorkbenchConfiguration;
+import org.apache.taverna.workbench.edits.CompoundEdit;
+import org.apache.taverna.workbench.edits.Edit;
+import org.apache.taverna.workbench.edits.EditException;
+import org.apache.taverna.workbench.edits.EditManager;
+import org.apache.taverna.workbench.file.DataflowInfo;
+import org.apache.taverna.workbench.file.FileManager;
+import org.apache.taverna.workbench.file.exceptions.OpenException;
+import org.apache.taverna.workbench.file.importworkflow.DataflowMerger;
+import org.apache.taverna.workbench.file.importworkflow.MergeException;
+import 
org.apache.taverna.workbench.file.importworkflow.actions.OpenSourceWorkflowAction;
+import org.apache.taverna.workbench.helper.HelpEnabledDialog;
+import net.sf.taverna.t2.workbench.models.graph.svg.SVGGraphController;
+import org.apache.taverna.workbench.selection.SelectionManager;
+import org.apache.taverna.workflow.edits.AddChildEdit;
+import org.apache.taverna.workflow.edits.AddProcessorEdit;
+
+import org.apache.batik.swing.JSVGCanvas;
+import org.apache.log4j.Logger;
+
+import org.apache.taverna.scufl2.api.activity.Activity;
+import org.apache.taverna.scufl2.api.common.Scufl2Tools;
+import org.apache.taverna.scufl2.api.configurations.Configuration;
+import org.apache.taverna.scufl2.api.container.WorkflowBundle;
+import org.apache.taverna.scufl2.api.core.Processor;
+import org.apache.taverna.scufl2.api.core.Workflow;
+import org.apache.taverna.scufl2.api.iterationstrategy.CrossProduct;
+import org.apache.taverna.scufl2.api.port.InputActivityPort;
+import org.apache.taverna.scufl2.api.port.InputProcessorPort;
+import org.apache.taverna.scufl2.api.port.InputWorkflowPort;
+import org.apache.taverna.scufl2.api.port.OutputActivityPort;
+import org.apache.taverna.scufl2.api.port.OutputProcessorPort;
+import org.apache.taverna.scufl2.api.port.OutputWorkflowPort;
+import org.apache.taverna.scufl2.api.profiles.ProcessorBinding;
+import org.apache.taverna.scufl2.api.profiles.ProcessorInputPortBinding;
+import org.apache.taverna.scufl2.api.profiles.ProcessorOutputPortBinding;
+import org.apache.taverna.scufl2.api.profiles.Profile;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+@SuppressWarnings("serial")
+public class ImportWorkflowWizard extends HelpEnabledDialog {
+
+       private static Logger logger = 
Logger.getLogger(ImportWorkflowWizard.class);
+
+       private Scufl2Tools scufl2Tools = new Scufl2Tools();
+
+       protected BrowseFileOnClick browseFileOnClick = new BrowseFileOnClick();
+       protected JButton buttonBrowse;
+       protected JComboBox chooseDataflow;
+       protected DataflowOpenerThread dataflowOpenerThread;
+
+       private WorkflowBundle destinationWorkflowBundle;
+       private Workflow destinationWorkflow;
+       private Profile destinationProfile;
+       private Workflow sourceWorkflow;
+
+       protected JTextField fieldFile;
+
+       protected JTextField fieldUrl;
+       protected boolean mergeEnabled = true;
+       protected boolean nestedEnabled = true;
+       protected JSVGCanvas previewSource = new JSVGCanvas(null, false, false);
+       protected JSVGCanvas previewDestination = new JSVGCanvas(null, false, 
false);
+       protected JTextField prefixField;
+       protected JRadioButton radioFile;
+       protected JRadioButton radioNew;
+       protected JRadioButton radioOpened;
+       protected JRadioButton radioUrl;
+       protected ButtonGroup sourceSelection;
+       protected ActionListener updateChosenListener = new 
UpdateChosenListener();
+       protected Thread updatePreviewsThread;
+       protected Component sourceSelectionPanel;
+       protected JLabel prefixLabel;
+       protected JLabel prefixHelp;
+//     protected JPanel destinationSelectionPanel;
+//     protected ButtonGroup destinationSelection;
+//     protected JRadioButton radioNewDestination;
+//     protected JRadioButton radioOpenDestination;
+//     protected JComboBox destinationAlreadyOpen;
+       protected JPanel introductionPanel;
+       protected ButtonGroup actionSelection;
+       protected JRadioButton actionNested;
+       protected JRadioButton actionMerge;
+       protected JRadioButton radioCustomSource;
+       protected JRadioButton radioCustomDestination;
+
+       private final EditManager editManager;
+       private final FileManager fileManager;
+       private final MenuManager menuManager;
+       private final ColourManager colourManager;
+       private final WorkbenchConfiguration workbenchConfiguration;
+       private final SelectionManager selectionManager;
+
+       private WorkflowBundle customSourceDataFlow = null;
+//     private Workflow customDestinationDataflow = null;
+       private String customSourceName = "";
+//     private String customDestinationName = "";
+
+       private boolean sourceEnabled = true;
+//     private boolean destinationEnabled = true;
+       private Activity insertedActivity;
+
+       public ImportWorkflowWizard(Frame parentFrame, EditManager editManager,
+                       FileManager fileManager, MenuManager menuManager, 
ColourManager colourManager,
+                       WorkbenchConfiguration workbenchConfiguration, 
SelectionManager selectionManager) {
+               super(parentFrame, "Import workflow", true, null);
+               this.selectionManager = selectionManager;
+               destinationWorkflow = selectionManager.getSelectedWorkflow();
+               destinationProfile = selectionManager.getSelectedProfile();
+               destinationWorkflowBundle = 
selectionManager.getSelectedWorkflowBundle();
+
+               this.editManager = editManager;
+               this.fileManager = fileManager;
+               this.menuManager = menuManager;
+               this.colourManager = colourManager;
+               this.workbenchConfiguration = workbenchConfiguration;
+
+               setSize(600, 600);
+               add(makeContentPane(), BorderLayout.CENTER);
+               // Add some space
+               add(new JPanel(), BorderLayout.WEST);
+               add(new JPanel(), BorderLayout.NORTH);
+               add(new JPanel(), BorderLayout.SOUTH);
+               add(new JPanel(), BorderLayout.EAST);
+               findChosenDataflow(this, true);
+               updateAll();
+       }
+
+       public void setMergeEnabled(boolean importEnabled) {
+               this.mergeEnabled = importEnabled;
+               updateAll();
+       }
+
+       public void setNestedEnabled(boolean nestedEnabled) {
+               this.nestedEnabled = nestedEnabled;
+               updateAll();
+       }
+
+       /**
+        * Silly workaround to avoid "Cannot call invokeAndWait from the event 
dispatcher thread"
+        * exception.
+        *
+        * @param runnable
+        */
+       public static void invokeAndWait(Runnable runnable) {
+               if (SwingUtilities.isEventDispatchThread()) {
+                       runnable.run();
+                       return;
+               }
+               try {
+                       SwingUtilities.invokeAndWait(runnable);
+               } catch (InterruptedException ex) {
+                       // logger.warn("Runnable " + runnable + " was 
interrupted " + runnable, ex);
+               } catch (InvocationTargetException e) {
+                       logger.warn("Can't invoke " + runnable, e);
+               }
+       }
+
+       protected Component makeWorkflowImage() {
+               JPanel workflowImages = new JPanel(new GridBagLayout());
+               GridBagConstraints gbc = new GridBagConstraints();
+               gbc.gridy = 0;
+               gbc.fill = GridBagConstraints.BOTH;
+               gbc.weighty = 0.1;
+
+               gbc.weightx = 0.1;
+               workflowImages.add(new JPanel(), gbc);// filler
+
+               gbc.weightx = 0.0;
+               previewSource.setBackground(workflowImages.getBackground());
+               workflowImages.add(previewSource, gbc);
+
+               JLabel arrow = new JLabel("\u2192");
+               arrow.setFont(arrow.getFont().deriveFont(48f));
+               workflowImages.add(arrow, gbc);
+
+               
previewDestination.setBackground(workflowImages.getBackground());
+               workflowImages.add(previewDestination, gbc);
+
+               gbc.weightx = 0.1;
+               workflowImages.add(new JPanel(), gbc);
+               gbc.weightx = 0.0;
+
+               return workflowImages;
+       }
+
+       protected void updateAll() {
+               updatePreviews(); // will go in separate thread anyway, do it 
first
+               updateHeader();
+               updateSourceSection();
+//             updateDestinationSection();
+               updateFooter();
+       }
+
+//     protected void updateDestinationSection() {
+//
+//             radioNewDestination.setVisible(false);
+//
+//             radioCustomDestination.setText(customDestinationName);
+//             radioCustomDestination.setVisible(customDestinationDataflow != 
null);
+//
+//             // radioNewDestination.setVisible(nestedEnabled);
+//             // radioNewDestination.setEnabled(actionNested.isSelected());
+//
+//             destinationSelectionPanel.setVisible(destinationEnabled);
+//
+//     }
+
+       protected synchronized void updatePreviews() {
+               if (updatePreviewsThread != null && 
updatePreviewsThread.isAlive()) {
+                       updatePreviewsThread.interrupt();
+               }
+               updatePreviewsThread = new UpdatePreviewsThread();
+               updatePreviewsThread.start();
+       }
+
+       protected void updateDestinationPreview() {
+               updateWorkflowGraphic(previewDestination, destinationWorkflow, 
destinationProfile);
+       }
+
+       protected void updateSourcePreview() {
+               Profile sourceProfile = null;
+               if (sourceWorkflow != null) {
+                       sourceProfile = 
sourceWorkflow.getParent().getMainProfile();
+               }
+               updateWorkflowGraphic(previewSource, sourceWorkflow, 
sourceProfile);
+       }
+
+       protected void updateFooter() {
+               prefixField.setVisible(mergeEnabled);
+               prefixLabel.setVisible(mergeEnabled);
+               prefixHelp.setVisible(mergeEnabled);
+
+               prefixField.setEnabled(actionMerge.isSelected());
+               prefixLabel.setEnabled(actionMerge.isSelected());
+               prefixHelp.setEnabled(actionMerge.isSelected());
+               if (actionMerge.isSelected()) {
+                       prefixHelp.setForeground(prefixLabel.getForeground());
+               } else {
+                       // Work around
+                       // 
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4303706
+                       // and assume gray is the 'disabled' colour in our Look 
n Feel
+                       prefixHelp.setForeground(Color.gray);
+               }
+
+       }
+
+       protected void updateHeader() {
+               makeIntroductionPanel();
+       }
+
+       protected void updateSourceSection() {
+               radioCustomSource.setText(customSourceName);
+               radioCustomSource.setVisible(customSourceDataFlow != null);
+
+               radioNew.setVisible(nestedEnabled);
+               radioNew.setEnabled(actionNested.isSelected());
+
+               if (actionNested.isSelected() && sourceSelection.getSelection() 
== null) {
+                       // Preselect the new workflow
+                       radioNew.setSelected(true);
+               }
+
+               sourceSelectionPanel.setVisible(sourceEnabled);
+       }
+
+       /**
+        * Create a PNG image of the workflow and place inside an ImageIcon
+        *
+        * @param dataflow
+        * @return
+        * @throws InvocationTargetException
+        * @throws InterruptedException
+        */
+       protected void updateWorkflowGraphic(final JSVGCanvas svgCanvas, final 
Workflow workflow, final Profile profile) {
+               try {
+                       SwingUtilities.invokeAndWait(new Runnable() {
+                               public void run() {
+                                       // Set it to blank while reloading
+                                       svgCanvas.setSVGDocument(null);
+                                       if (workflow != null) {
+                                               SVGGraphController 
currentWfGraphController = new SVGGraphController(
+                                                               workflow, 
profile, false, svgCanvas,
+                                                               editManager, 
menuManager, colourManager, workbenchConfiguration);
+                                       }
+                               }
+                       });
+               } catch (InterruptedException e) {
+                       // logger.error(e);
+               } catch (InvocationTargetException e) {
+                       // logger.error(e);
+               }
+       }
+
+       /**
+        * Open the selected source and destination workflows. If background is 
true, this method will
+        * return immediately while a {@link DataflowOpenerThread} performs the 
updates. If a
+        * DataflowOpenerThread is already running, it will be interrupted and 
stopped.
+        *
+        * @param parentComponent
+        *            The parent component for showing dialogues
+        * @param background
+        *            If true, will run in separate thread.
+        * @return <code>false</code> if running in the background, or if a 
dialogue was shown and the
+        *         operation is aborted by the user, or <code>true</code> if 
not running in the
+        *         background and the method completed without user 
interruption.
+        */
+       protected synchronized boolean findChosenDataflow(Component 
parentComponent, boolean background) {
+               if (dataflowOpenerThread != null && 
dataflowOpenerThread.isAlive()) {
+                       if (background) {
+                               // We've changed our mind
+                               dataflowOpenerThread.interrupt();
+                       } else {
+                               // We'll let it finish, we don't need to do it 
again
+                               try {
+                                       dataflowOpenerThread.join();
+                               } catch (InterruptedException e) {
+                                       Thread.currentThread().interrupt();
+                               }
+                               return !dataflowOpenerThread.shownWarning;
+                       }
+               }
+               dataflowOpenerThread = new 
DataflowOpenerThread(parentComponent, background);
+
+               if (background) {
+                       dataflowOpenerThread.start();
+                       return false;
+               } else {
+                       dataflowOpenerThread.run();
+                       return !dataflowOpenerThread.shownWarning;
+               }
+
+       }
+
+       protected Container makeContentPane() {
+               JPanel panel = new JPanel(new GridBagLayout());
+               GridBagConstraints gbc = new GridBagConstraints();
+
+               gbc.ipadx = 5;
+               gbc.ipady = 5;
+
+               gbc.gridx = 0;
+               gbc.weightx = 0.1;
+               gbc.fill = GridBagConstraints.BOTH;
+
+               introductionPanel = makeIntroductionPanel();
+               panel.add(introductionPanel, gbc);
+
+               sourceSelectionPanel = makeSourceSelectionPanel();
+               panel.add(sourceSelectionPanel, gbc);
+
+//             destinationSelectionPanel = makeDestinationSelectionPanel();
+//             panel.add(destinationSelectionPanel, gbc);
+
+               gbc.weighty = 0.1;
+               panel.add(makeImportStylePanel(), gbc);
+
+               return panel;
+       }
+
+       protected JPanel makeIntroductionPanel() {
+               if (introductionPanel == null) {
+                       introductionPanel = new JPanel(new GridBagLayout());
+               } else {
+                       introductionPanel.removeAll();
+               }
+               boolean bothEnabled = mergeEnabled && nestedEnabled;
+               if (bothEnabled) {
+                       
introductionPanel.setBorder(BorderFactory.createTitledBorder("Import method"));
+               } else {
+                       
introductionPanel.setBorder(BorderFactory.createEmptyBorder());
+               }
+               GridBagConstraints gbc = new GridBagConstraints();
+               gbc.gridx = 0;
+               // gbc.gridy = 0;
+               gbc.weightx = 0.1;
+               gbc.fill = GridBagConstraints.BOTH;
+               gbc.anchor = GridBagConstraints.FIRST_LINE_START;
+
+               StringBuilder nestedHelp = new StringBuilder();
+               nestedHelp.append("<html><small>");
+               nestedHelp.append("Add a <strong>nested workflow</strong> ");
+               nestedHelp.append("into the ");
+               nestedHelp.append("destination workflow as a single service. ");
+               nestedHelp.append("The nested workflow ");
+               nestedHelp.append("can be <em>edited separately</em>, but is 
shown ");
+               nestedHelp.append("expanded in the diagram of the parent  ");
+               nestedHelp.append("workflow. In the parent workflow you can ");
+               nestedHelp.append("connect to the input and output ports of the 
nested ");
+               nestedHelp.append("workflow. ");
+               nestedHelp.append("</small></html>");
+
+               StringBuilder mergeHelp = new StringBuilder();
+               mergeHelp.append("<html><small>");
+               mergeHelp.append("<strong>Merge</strong> a workflow ");
+               mergeHelp.append("by copying all services, ports and links ");
+               mergeHelp.append("directly into the destination workflow. This 
can be  ");
+               mergeHelp.append("useful for merging smaller workflow 
fragments. For ");
+               mergeHelp.append("inclusion of larger workflows you might find 
using ");
+               mergeHelp.append("<em>nested workflows</em> more beneficial.");
+               mergeHelp.append("</small></html>");
+
+               actionSelection = new ButtonGroup();
+               actionNested = new JRadioButton(nestedHelp.toString());
+               ActionListener updateListener = new ActionListener() {
+                       public void actionPerformed(ActionEvent e) {
+                               updateSourceSection();
+//                             updateDestinationSection();
+                               updateFooter();
+                       }
+               };
+               actionNested.addActionListener(updateListener);
+               actionSelection.add(actionNested);
+
+               actionMerge = new JRadioButton(mergeHelp.toString());
+               actionMerge.addActionListener(updateListener);
+               actionSelection.add(actionMerge);
+
+               if (bothEnabled) {
+                       introductionPanel.add(actionNested, gbc);
+                       introductionPanel.add(actionMerge, gbc);
+                       actionNested.setSelected(true);
+               } else if (nestedEnabled) {
+                       introductionPanel.add(new 
JLabel(nestedHelp.toString()), gbc);
+                       actionNested.setSelected(true);
+               } else if (mergeEnabled) {
+                       introductionPanel.add(new JLabel(mergeHelp.toString()), 
gbc);
+                       actionMerge.setSelected(true);
+               }
+               return introductionPanel;
+       }
+
+//     protected JPanel makeDestinationSelectionPanel() {
+//             JPanel j = new JPanel(new GridBagLayout());
+//             j.setBorder(BorderFactory.createTitledBorder("Workflow 
destination"));
+//
+//             GridBagConstraints gbc = new GridBagConstraints();
+//             gbc.gridx = 0;
+//             gbc.gridy = 0;
+//             gbc.fill = GridBagConstraints.BOTH;
+//
+//             destinationSelection = new ButtonGroup();
+//             radioNewDestination = new JRadioButton("New workflow");
+//             gbc.gridy = 0;
+//             j.add(radioNewDestination, gbc);
+//             destinationSelection.add(radioNewDestination);
+//             radioNewDestination.addActionListener(updateChosenListener);
+//
+//             radioOpenDestination = new JRadioButton("Already opened 
workflow");
+//             gbc.gridy = 2;
+//             j.add(radioOpenDestination, gbc);
+//             destinationSelection.add(radioOpenDestination);
+//             radioOpenDestination.addActionListener(updateChosenListener);
+//             gbc.weightx = 0.1;
+//             gbc.gridx = 1;
+//             destinationAlreadyOpen = makeSelectOpenWorkflowComboBox(true);
+//             j.add(destinationAlreadyOpen, gbc);
+//
+//             radioCustomDestination = new 
JRadioButton(customDestinationName);
+//             radioCustomDestination.setVisible(customDestinationName != 
null);
+//             gbc.gridx = 0;
+//             gbc.gridy = 3;
+//             gbc.gridwidth = 2;
+//             j.add(radioCustomDestination, gbc);
+//             destinationSelection.add(radioCustomDestination);
+//             radioCustomDestination.addActionListener(updateChosenListener);
+//             gbc.gridwidth = 1;
+//
+//             radioOpenDestination.setSelected(true);
+//             return j;
+//     }
+
+       protected Component makeImportStylePanel() {
+               JPanel j = new JPanel(new GridBagLayout());
+               GridBagConstraints gbc = new GridBagConstraints();
+               gbc.gridx = 0;
+               gbc.gridy = 0;
+               gbc.fill = GridBagConstraints.BOTH;
+
+               j.setBorder(BorderFactory.createTitledBorder("Import"));
+
+               prefixLabel = new JLabel("Prefix");
+               j.add(prefixLabel, gbc);
+               gbc.weightx = 0.1;
+               gbc.gridx = 1;
+
+               prefixField = new JTextField(10);
+               prefixLabel.setLabelFor(prefixField);
+               j.add(prefixField, gbc);
+
+               gbc.gridx = 0;
+               gbc.gridy = 1;
+               gbc.gridwidth = 2;
+
+               prefixHelp = new JLabel(
+                               "<html><small>Optional prefix to be prepended 
to the name of the "
+                                               + "inserted services and 
workflow ports. Even if no prefix is given, duplicate names will be "
+                                               + "resolved by adding numbers, 
for instance <code>my_service_2</code> if <code>my_service</code> already "
+                                               + "existed." + 
"</small></html>");
+               prefixHelp.setLabelFor(prefixField);
+               j.add(prefixHelp, gbc);
+
+               gbc.gridy = 2;
+               gbc.weightx = 0.1;
+               gbc.weighty = 0.1;
+
+               j.add(makeWorkflowImage(), gbc);
+
+               gbc.gridy = 3;
+               gbc.weighty = 0.0;
+               j.add(new JPanel(), gbc);
+
+               gbc.gridy = 4;
+               gbc.fill = GridBagConstraints.NONE;
+               JButton comp = new JButton(new ImportWorkflowAction());
+               j.add(comp, gbc);
+               return j;
+
+       }
+
+       protected Component makeSelectFile() {
+               JPanel j = new JPanel(new GridBagLayout());
+               j.setBorder(BorderFactory.createEtchedBorder());
+
+               GridBagConstraints gbc = new GridBagConstraints();
+               gbc.gridx = 0;
+               gbc.gridy = 0;
+               gbc.fill = GridBagConstraints.BOTH;
+               gbc.weightx = 0.1;
+
+               fieldFile = new JTextField(20);
+               fieldFile.setEditable(false);
+               fieldFile.addFocusListener(new FocusAdapter() {
+                       public void focusGained(FocusEvent e) {
+                               radioFile.setSelected(true);
+                       }
+
+                       @Override
+                       public void focusLost(FocusEvent e) {
+                               findChosenDataflow(e.getComponent(), true);
+                       }
+               });
+               j.add(fieldFile, gbc);
+               radioFile.addItemListener(new ItemListener() {
+
+                       public void itemStateChanged(ItemEvent e) {
+                               if (e.getStateChange() == ItemEvent.SELECTED) {
+                                       browseFileOnClick.checkEmptyFile();
+                               }
+                       }
+               });
+
+               gbc.gridx = 1;
+               gbc.weightx = 0.0;
+               gbc.fill = GridBagConstraints.NONE;
+               buttonBrowse = new JButton(new 
OpenSourceWorkflowAction(fileManager) {
+                       @Override
+                       public void openWorkflows(Component parentComponent, 
File[] files) {
+                               if (files.length == 0) {
+                                       radioFile.setSelected(false);
+                                       fieldFile.setText("");
+                                       radioFile.requestFocus();
+                                       return;
+                               }
+                               fieldFile.setText(files[0].getPath());
+                               if (!radioFile.isSelected()) {
+                                       radioFile.setSelected(true);
+                               }
+                               findChosenDataflow(parentComponent, true);
+                       }
+               });
+               buttonBrowse.setText("Browse");
+               j.add(buttonBrowse, gbc);
+
+               // This just duplicates things - we already have actions on
+               // the radioFile and fieldFile that will handle the events
+               // radioFile.addActionListener(browseFileOnClick);
+               // fieldFile.addActionListener(browseFileOnClick);
+               return j;
+       }
+
+       protected JComboBox makeSelectOpenWorkflowComboBox(boolean 
selectCurrent) {
+               List<DataflowSelection> openDataflows = new 
ArrayList<DataflowSelection>();
+               DataflowSelection current = null;
+               for (WorkflowBundle df : fileManager.getOpenDataflows()) {
+                       String name = df.getMainWorkflow().getName();
+                       boolean isCurrent = 
df.equals(fileManager.getCurrentDataflow());
+                       if (isCurrent) {
+                               // Wrapping as HTML causes weird drop-down box 
under MAC, so
+                               // we just use normal text
+                               // name = "<html><body>" + name
+                               // + " <i>(current)</i></body></html>";
+                               name = name + " (current)";
+                       }
+                       DataflowSelection selection = new DataflowSelection(df, 
name);
+                       openDataflows.add(selection);
+                       if (isCurrent) {
+                               current = selection;
+                       }
+               }
+               JComboBox chooseDataflow = new 
JComboBox(openDataflows.toArray());
+               if (selectCurrent) {
+                       chooseDataflow.setSelectedItem(current);
+               }
+               chooseDataflow.addActionListener(updateChosenListener);
+               return chooseDataflow;
+
+       }
+
+       protected Component makeSourceSelectionPanel() {
+               JPanel j = new JPanel(new GridBagLayout());
+               j.setBorder(BorderFactory.createTitledBorder("Workflow 
source"));
+
+               GridBagConstraints gbc = new GridBagConstraints();
+               gbc.gridx = 0;
+               gbc.gridy = 0;
+               gbc.fill = GridBagConstraints.BOTH;
+
+               sourceSelection = new ButtonGroup();
+               radioNew = new JRadioButton("New workflow");
+               gbc.gridy = 0;
+               j.add(radioNew, gbc);
+               sourceSelection.add(radioNew);
+
+               radioNew.addActionListener(updateChosenListener);
+
+               radioFile = new JRadioButton("Import from file");
+               gbc.gridy = 1;
+               j.add(radioFile, gbc);
+               sourceSelection.add(radioFile);
+               radioFile.addActionListener(updateChosenListener);
+
+               radioUrl = new JRadioButton("Import from URL");
+               gbc.gridy = 2;
+               j.add(radioUrl, gbc);
+               sourceSelection.add(radioUrl);
+               radioUrl.addActionListener(updateChosenListener);
+
+               radioOpened = new JRadioButton("Already opened workflow");
+               gbc.gridy = 3;
+               j.add(radioOpened, gbc);
+               sourceSelection.add(radioOpened);
+               radioOpened.addActionListener(updateChosenListener);
+
+               radioCustomSource = new JRadioButton(customSourceName);
+               radioCustomSource.setVisible(customSourceDataFlow != null);
+               gbc.gridy = 4;
+               gbc.gridwidth = 2;
+               j.add(radioCustomSource, gbc);
+               sourceSelection.add(radioCustomSource);
+               radioCustomSource.addActionListener(updateChosenListener);
+               gbc.gridwidth = 1;
+
+               gbc.gridx = 1;
+               gbc.gridy = 1;
+               gbc.weightx = 0.1;
+               j.add(makeSelectFile(), gbc);
+
+               gbc.gridy = 2;
+               fieldUrl = new JTextField(20);
+               j.add(fieldUrl, gbc);
+               fieldUrl.addFocusListener(new FocusAdapter() {
+                       @Override
+                       public void focusGained(FocusEvent e) {
+                               radioUrl.setSelected(true);
+                       }
+
+                       @Override
+                       public void focusLost(FocusEvent e) {
+                               findChosenDataflow(e.getComponent(), true);
+                       }
+               });
+
+               gbc.gridy = 3;
+               chooseDataflow = makeSelectOpenWorkflowComboBox(false);
+               chooseDataflow.addFocusListener(new FocusAdapter() {
+                       @Override
+                       public void focusGained(FocusEvent e) {
+                               radioOpened.setSelected(true);
+                       }
+               });
+               j.add(chooseDataflow, gbc);
+
+               return j;
+       }
+
+       protected Edit<?> makeInsertNestedWorkflowEdit(Workflow nestedFlow) {
+               Processor processor = new Processor();
+               processor.setName("nestedWorkflow");
+
+               CrossProduct crossProduct = new CrossProduct();
+               crossProduct.setParent(processor.getIterationStrategyStack());
+
+               Activity activity = new Activity();
+               activity.setType(DataflowTemplateService.ACTIVITY_TYPE);
+               Configuration configuration = new Configuration();
+               
configuration.setType(DataflowTemplateService.ACTIVITY_TYPE.resolve("#Config"));
+               
destinationWorkflowBundle.getWorkflows().addWithUniqueName(nestedFlow);
+               ((ObjectNode) configuration.getJson()).put("nestedWorkflow", 
nestedFlow.getName());
+               destinationWorkflowBundle.getWorkflows().remove(nestedFlow);
+               configuration.setConfigures(activity);
+
+               ProcessorBinding processorBinding = new ProcessorBinding();
+               processorBinding.setBoundProcessor(processor);
+               processorBinding.setBoundActivity(activity);
+
+               for (InputWorkflowPort workflowPort : 
nestedFlow.getInputPorts()) {
+                       InputActivityPort activityPort = new 
InputActivityPort(activity, workflowPort.getName());
+                       activityPort.setDepth(workflowPort.getDepth());
+                       // create processor port
+                       InputProcessorPort processorPort = new 
InputProcessorPort(processor, activityPort.getName());
+                       processorPort.setDepth(activityPort.getDepth());
+                       // add a new port binding
+                       new ProcessorInputPortBinding(processorBinding, 
processorPort, activityPort);
+               }
+               for (OutputWorkflowPort workflowPort : 
nestedFlow.getOutputPorts()) {
+                       OutputActivityPort activityPort = new 
OutputActivityPort(activity, workflowPort.getName());
+                       // TODO calculate output depth
+                       activityPort.setDepth(0);
+                       activityPort.setGranularDepth(0);
+                       // create processor port
+                       OutputProcessorPort processorPort = new 
OutputProcessorPort(processor, activityPort.getName());
+                       processorPort.setDepth(activityPort.getDepth());
+                       
processorPort.setGranularDepth(activityPort.getGranularDepth());
+                       // add a new port binding
+                       new ProcessorOutputPortBinding(processorBinding, 
activityPort, processorPort);
+               }
+
+               List<Edit<?>> editList = new ArrayList<Edit<?>>();
+               editList.add(new AddChildEdit<Profile>(destinationProfile, 
activity));
+               editList.add(new AddChildEdit<Profile>(destinationProfile, 
configuration));
+               editList.add(new AddChildEdit<Profile>(destinationProfile, 
processorBinding));
+               editList.add(new AddProcessorEdit(destinationWorkflow, 
processor));
+
+               editList.add(makeInsertWorkflowEdit(nestedFlow, 
nestedFlow.getParent().getMainProfile()));
+
+               return new CompoundEdit(editList);
+       }
+
+       protected Edit<?> makeInsertWorkflowEdit(Workflow nestedFlow, Profile 
profile) {
+               return makeInsertWorkflowEdit(nestedFlow, profile, new 
HashSet<>());
+       }
+
+       protected Edit<?> makeInsertWorkflowEdit(Workflow nestedFlow, Profile 
profile, Set<Object> seen) {
+               List<Edit<?>> editList = new ArrayList<Edit<?>>();
+               // add the nested workflow to the workflow bundle
+               editList.add(new 
AddChildEdit<WorkflowBundle>(destinationWorkflowBundle, nestedFlow));
+               seen.add(nestedFlow);
+               for (Processor processor : nestedFlow.getProcessors()) {
+                       // add processor bindings to the profile
+                       List<ProcessorBinding> processorBindings = 
scufl2Tools.processorBindingsForProcessor(processor, profile);
+                       for (ProcessorBinding processorBinding : 
processorBindings) {
+                               editList.add(new 
AddChildEdit<Profile>(destinationProfile, processorBinding));
+                               // add activity to the profile
+                               Activity activity = 
processorBinding.getBoundActivity();
+                               if (!seen.contains(activity)) {
+                                       editList.add(new 
AddChildEdit<Profile>(destinationProfile, activity));
+                                       // add activity configurations to the 
profile
+                                       for (Configuration configuration : 
scufl2Tools.configurationsFor(activity, profile)) {
+                                               editList.add(new 
AddChildEdit<Profile>(destinationProfile, configuration));
+                                       }
+                                       seen.add(activity);
+                               }
+                       }
+                       // add processor configurations to the profile
+                       List<Configuration> configurations = 
scufl2Tools.configurationsFor(processor, profile);
+                       for (Configuration configuration : configurations) {
+                               editList.add(new 
AddChildEdit<Profile>(destinationProfile, configuration));
+                       }
+
+                       for (Workflow workflow : 
scufl2Tools.nestedWorkflowsForProcessor(processor, profile)) {
+                               if (!seen.contains(workflow)) {
+                                       // recursively add nested workflows
+                                       
editList.add(makeInsertWorkflowEdit(workflow, profile, seen));
+                               }
+                       }
+               }
+               return new CompoundEdit(editList);
+       }
+
+//     protected Activity getInsertedActivity() {
+//             return insertedActivity;
+//     }
+
+       protected class ImportWorkflowAction extends AbstractAction implements 
Runnable {
+               private static final String VALID_NAME_REGEX = 
"[\\p{L}\\p{Digit}_.]+";
+               private Component parentComponent;
+               private ProgressMonitor progressMonitor;
+
+               protected ImportWorkflowAction() {
+                       super("Import workflow");
+               }
+
+               public void actionPerformed(ActionEvent e) {
+                       /*
+                        * if (e.getSource() instanceof Component) { 
parentComponent = (Component)
+                        * e.getSource(); } else { parentComponent = null; }
+                        */
+                       parentComponent = MainWindow.getMainWindow();
+                       Thread t = new Thread(this, "Import workflow");
+                       progressMonitor = new ProgressMonitor(parentComponent, 
"Importing workflow", "", 0, 100);
+                       progressMonitor.setMillisToDecideToPopup(200);
+                       progressMonitor.setProgress(5);
+                       t.start();
+                       setVisible(false);
+               }
+
+               protected void nested() {
+                       if (progressMonitor.isCanceled()) {
+                               return;
+                       }
+                       progressMonitor.setProgress(15);
+                       
selectionManager.setSelectedWorkflowBundle(destinationWorkflowBundle);
+                       if (progressMonitor.isCanceled()) {
+                               return;
+                       }
+
+                       progressMonitor.setNote("Copying source workflow");
+                       Workflow nestedFlow;
+                       try {
+                               nestedFlow = 
DataflowMerger.copyWorkflow(sourceWorkflow);
+                       } catch (Exception ex) {
+                               logger.warn("Could not copy nested workflow", 
ex);
+                               progressMonitor.setProgress(100);
+                               JOptionPane.showMessageDialog(parentComponent,
+                                               "An error occured while copying 
workflow:\n" + ex.getLocalizedMessage(),
+                                               "Could not copy nested 
workflow", JOptionPane.WARNING_MESSAGE);
+                               return;
+                       }
+                       if (progressMonitor.isCanceled()) {
+                               return;
+                       }
+
+                       progressMonitor.setNote("Creating nested workflow");
+                       progressMonitor.setProgress(45);
+
+                       Edit<?> edit = makeInsertNestedWorkflowEdit(nestedFlow);
+                       if (progressMonitor.isCanceled()) {
+                               return;
+                       }
+
+                       progressMonitor.setNote("Inserting nested workflow");
+                       progressMonitor.setProgress(65);
+
+                       try {
+                               
editManager.doDataflowEdit(destinationWorkflowBundle, edit);
+                       } catch (EditException e) {
+                               progressMonitor.setProgress(100);
+                               logger.warn("Could not import nested workflow", 
e);
+                               JOptionPane.showMessageDialog(parentComponent,
+                                               "An error occured while 
importing workflow:\n" + e.getLocalizedMessage(),
+                                               "Could not import workflows", 
JOptionPane.WARNING_MESSAGE);
+                               return;
+                       }
+
+                       if (radioNew.isSelected()) {
+                               progressMonitor.setNote("Opening new nested 
workflow for editing");
+                               progressMonitor.setProgress(90);
+                               
selectionManager.setSelectedWorkflow(nestedFlow);
+                       }
+                       progressMonitor.setProgress(100);
+               }
+
+               protected void merge() {
+                       progressMonitor.setProgress(10);
+                       DataflowMerger merger = new 
DataflowMerger(destinationWorkflow);
+                       progressMonitor.setProgress(25);
+                       progressMonitor.setNote("Planning workflow merging");
+
+                       String prefix = prefixField.getText();
+                       if (!prefix.equals("")) {
+                               if (!prefix.matches("[_.]$")) {
+                                       prefix = prefix + "_";
+                               }
+                               if (!prefix.matches(VALID_NAME_REGEX)) {
+                                       progressMonitor.setProgress(100);
+                                       final String wrongPrefix = prefix;
+                                       SwingUtilities.invokeLater(new 
Runnable() {
+                                               public void run() {
+                                                       
JOptionPane.showMessageDialog(parentComponent, "The merge prefix '"
+                                                                       + 
wrongPrefix + "' is not valid. Try "
+                                                                       + 
"using only letters, numbers, " + "underscore and dot.",
+                                                                       
"Invalid merge prefix", JOptionPane.ERROR_MESSAGE);
+                                                       
prefixField.requestFocus();
+                                                       
ImportWorkflowWizard.this.setVisible(true);
+                                               }
+                                       });
+                                       return;
+                               }
+                       }
+
+                       CompoundEdit mergeEdit;
+                       try {
+                               mergeEdit = 
merger.getMergeEdit(ImportWorkflowWizard.this.sourceWorkflow, prefix);
+                       } catch (MergeException e1) {
+                               progressMonitor.setProgress(100);
+                               logger.warn("Could not merge workflow", e1);
+                               JOptionPane.showMessageDialog(parentComponent,
+                                               "An error occured while merging 
workflows:\n" + e1.getLocalizedMessage(),
+                                               "Could not merge workflows", 
JOptionPane.WARNING_MESSAGE);
+                               return;
+                       }
+
+                       progressMonitor.setProgress(55);
+                       
selectionManager.setSelectedWorkflowBundle(destinationWorkflowBundle);
+
+                       progressMonitor.setNote("Merging workflows");
+                       progressMonitor.setProgress(75);
+
+                       if (progressMonitor.isCanceled()) {
+                               return;
+                       }
+
+                       try {
+                               
editManager.doDataflowEdit(destinationWorkflowBundle, mergeEdit);
+                       } catch (EditException e1) {
+                               progressMonitor.setProgress(100);
+                               JOptionPane.showMessageDialog(parentComponent,
+                                               "An error occured while merging 
workflows:\n" + e1.getLocalizedMessage(),
+                                               "Could not merge workflows", 
JOptionPane.WARNING_MESSAGE);
+                               return;
+                       }
+                       progressMonitor.setProgress(100);
+
+               }
+
+               public void run() {
+                       boolean completed = findChosenDataflow(parentComponent, 
false);
+                       if (!completed) {
+                               return;
+                       }
+                       if (actionMerge.isSelected()) {
+                               merge();
+                       } else if (actionNested.isSelected()) {
+                               nested();
+                       }
+               }
+       }
+
+       protected class UpdatePreviewsThread extends Thread {
+               protected UpdatePreviewsThread() {
+                       super("Updating destination previews");
+               }
+
+               public void run() {
+                       if (Thread.interrupted()) {
+                               return;
+                       }
+                       updateSourcePreview();
+
+                       if (Thread.interrupted()) {
+                               return;
+                       }
+                       updateDestinationPreview();
+               }
+       }
+
+       protected class BrowseFileOnClick implements ActionListener {
+               public void actionPerformed(ActionEvent e) {
+                       checkEmptyFile();
+               }
+
+               public void checkEmptyFile() {
+                       if (radioFile.isSelected() && 
fieldFile.getText().equals("")) {
+                               // On first label click pop up Browse dialogue.
+                               buttonBrowse.doClick();
+                       }
+               }
+       }
+
+       protected class DataflowOpenerThread extends Thread {
+               private final boolean background;
+               private final Component parentComponent;
+               private boolean shouldStop = false;
+               private boolean shownWarning = false;
+
+               protected DataflowOpenerThread(Component parentComponent, 
boolean background) {
+                       super("Inspecting selected workflow");
+                       this.parentComponent = parentComponent;
+                       this.background = background;
+               }
+
+               @Override
+               public void interrupt() {
+                       this.shouldStop = true;
+                       super.interrupt();
+               }
+
+               public void run() {
+                       updateSource();
+//                     updateDestination();
+               }
+
+//             public void updateDestination() {
+//                     ButtonModel selection = 
destinationSelection.getSelection();
+//                     Workflow chosenDataflow = null;
+//                     if (selection == null) {
+//                             chosenDataflow = null;
+//                     } else if 
(selection.equals(radioNewDestination.getModel())) {
+//                             chosenDataflow = new Workflow();
+//                     } else if 
(selection.equals(radioOpenDestination.getModel())) {
+//                             DataflowSelection chosen = (DataflowSelection) 
destinationAlreadyOpen
+//                                             .getSelectedItem();
+//                             chosenDataflow = chosen.getDataflow();
+//                     } else if 
(selection.equals(radioCustomDestination.getModel())) {
+//                             chosenDataflow = customDestinationDataflow;
+//                     } else {
+//                             logger.error("Unknown selection " + selection);
+//                     }
+//
+//                     if (chosenDataflow == null) {
+//                             if (!background && !shownWarning) {
+//                                     shownWarning = true;
+//                                     SwingUtilities.invokeLater(new 
Runnable() {
+//                                             public void run() {
+//                                                     
JOptionPane.showMessageDialog(parentComponent,
+//                                                                     "You 
need to choose a destination workflow",
+//                                                                     "No 
destination workflow chosen", JOptionPane.ERROR_MESSAGE);
+//                                                     setVisible(true);
+//                                             }
+//                                     });
+//                                     return;
+//                             }
+//                     }
+//                     if (checkInterrupted()) {
+//                             return;
+//                     }
+//                     if (chosenDataflow != 
ImportWorkflowWizard.this.destinationDataflow) {
+//                             updateWorkflowGraphic(previewDestination, 
chosenDataflow);
+//                             if (checkInterrupted()) {
+//                                     return;
+//                             }
+//                             ImportWorkflowWizard.this.destinationDataflow = 
chosenDataflow;
+//                     }
+//
+//             }
+
+               public void updateSource() {
+                       ButtonModel selection = sourceSelection.getSelection();
+                       Workflow chosenDataflow = null;
+                       if (selection == null) {
+                               chosenDataflow = null;
+                       } else if (selection.equals(radioNew.getModel())) {
+                               WorkflowBundle workflowBundle = new 
WorkflowBundle();
+                               workflowBundle.setMainWorkflow(new Workflow());
+                               
workflowBundle.getMainWorkflow().setName(fileManager.getDefaultWorkflowName());
+                               workflowBundle.setMainProfile(new Profile());
+                               scufl2Tools.setParents(workflowBundle);
+                               chosenDataflow = 
workflowBundle.getMainWorkflow();
+                       } else if (selection.equals(radioFile.getModel())) {
+                               final String filePath = fieldFile.getText();
+                               try {
+                                       DataflowInfo opened = fileManager
+                                                       
.openDataflowSilently(null, new File(filePath));
+                                       if (checkInterrupted()) {
+                                               return;
+                                       }
+                                       chosenDataflow = 
opened.getDataflow().getMainWorkflow();
+                               } catch (final OpenException e1) {
+                                       if (!background && !shownWarning) {
+                                               shownWarning = true;
+                                               logger.warn("Could not open 
workflow for merging: " + filePath, e1);
+                                               SwingUtilities.invokeLater(new 
Runnable() {
+                                                       public void run() {
+                                                               
radioFile.requestFocus();
+                                                               
JOptionPane.showMessageDialog(parentComponent,
+                                                                               
"An error occured while trying to open " + filePath + "\n"
+                                                                               
                + e1.getMessage(), "Could not open workflow",
+                                                                               
JOptionPane.WARNING_MESSAGE);
+                                                               
setVisible(true);
+                                                       }
+                                               });
+                                       }
+                               }
+                       } else if (selection.equals(radioUrl.getModel())) {
+                               final String url = fieldUrl.getText();
+                               try {
+                                       DataflowInfo opened = 
fileManager.openDataflowSilently(null, new URL(url));
+                                       if (checkInterrupted()) {
+                                               return;
+                                       }
+                                       chosenDataflow = 
opened.getDataflow().getMainWorkflow();
+                               } catch (final OpenException e1) {
+                                       if (!background && !shownWarning) {
+                                               logger.warn("Could not open 
source workflow: " + url, e1);
+                                               shownWarning = true;
+                                               SwingUtilities.invokeLater(new 
Runnable() {
+                                                       public void run() {
+                                                               
fieldUrl.requestFocus();
+                                                               
JOptionPane.showMessageDialog(
+                                                                               
parentComponent,
+                                                                               
"An error occured while trying to open " + url + "\n"
+                                                                               
                + e1.getMessage(), "Could not open workflow",
+                                                                               
JOptionPane.WARNING_MESSAGE);
+                                                               
setVisible(true);
+                                                       }
+                                               });
+
+                                       }
+                                       if (checkInterrupted()) {
+                                               return;
+                                       }
+                               } catch (final MalformedURLException e1) {
+                                       if (!background && !shownWarning) {
+                                               logger.warn("Invalid workflow 
URL: " + url, e1);
+                                               shownWarning = true;
+                                               SwingUtilities.invokeLater(new 
Runnable() {
+                                                       public void run() {
+                                                               
fieldUrl.requestFocus();
+                                                               
JOptionPane.showMessageDialog(
+                                                                               
parentComponent,
+                                                                               
"The workflow location " + url + " is invalid\n"
+                                                                               
                + e1.getLocalizedMessage(), "Invalid URL",
+                                                                               
JOptionPane.ERROR_MESSAGE);
+                                                               
setVisible(true);
+                                                       }
+                                               });
+                                       }
+                                       if (checkInterrupted()) {
+                                               return;
+                                       }
+                               }
+                       } else if (selection.equals(radioOpened.getModel())) {
+                               DataflowSelection chosen = (DataflowSelection) 
chooseDataflow.getSelectedItem();
+                               chosenDataflow = 
chosen.getDataflow().getMainWorkflow();
+                       } else if 
(selection.equals(radioCustomSource.getModel())) {
+                               chosenDataflow = 
customSourceDataFlow.getMainWorkflow();
+                       } else {
+                               logger.error("Unknown selection " + selection);
+                       }
+                       if (checkInterrupted()) {
+                               return;
+                       }
+                       if (chosenDataflow != 
ImportWorkflowWizard.this.sourceWorkflow) {
+                               Profile chosenProfile = null;
+                               if (chosenDataflow != null) {
+                                       chosenProfile = 
chosenDataflow.getParent().getMainProfile();
+                               }
+                               updateWorkflowGraphic(previewSource, 
chosenDataflow, chosenProfile);
+                               if (checkInterrupted()) {
+                                       return;
+                               }
+                               ImportWorkflowWizard.this.sourceWorkflow = 
chosenDataflow;
+                       }
+                       if (chosenDataflow == null) {
+                               if (!background && !shownWarning) {
+                                       shownWarning = true;
+                                       SwingUtilities.invokeLater(new 
Runnable() {
+                                               public void run() {
+                                                       
JOptionPane.showMessageDialog(parentComponent,
+                                                                       "You 
need to choose a workflow for merging",
+                                                                       "No 
workflow chosen", JOptionPane.ERROR_MESSAGE);
+                                                       setVisible(true);
+                                               }
+                                       });
+                               }
+                       }
+               }
+
+               private boolean checkInterrupted() {
+                       if (Thread.interrupted() || this.shouldStop) {
+                               // ImportWorkflowWizard.this.chosenDataflow = 
null;
+                               return true;
+                       }
+                       return false;
+               }
+       }
+
+       public static class DataflowSelection {
+               private final WorkflowBundle dataflow;
+               private final String name;
+
+               public DataflowSelection(WorkflowBundle dataflow, String name) {
+                       this.dataflow = dataflow;
+                       this.name = name;
+               }
+
+               public WorkflowBundle getDataflow() {
+                       return dataflow;
+               }
+
+               public String getName() {
+                       return name;
+               }
+
+               @Override
+               public String toString() {
+                       return name;
+               }
+
+       }
+
+       protected class UpdateChosenListener implements ActionListener {
+               public void actionPerformed(ActionEvent e) {
+                       Component parentComponent;
+                       if (e.getSource() instanceof Component) {
+                               parentComponent = (Component) e.getSource();
+                       } else {
+                               parentComponent = null;
+                       }
+                       findChosenDataflow(parentComponent, true);
+
+               }
+       }
+
+       public void setCustomSourceDataflow(WorkflowBundle sourceDataflow, 
String label) {
+               this.customSourceDataFlow = sourceDataflow;
+               this.customSourceName = label;
+               updateSourceSection();
+               radioCustomSource.doClick();
+       }
+
+//     public void setCustomDestinationDataflow(Workflow destinationDataflow, 
String label) {
+//             this.customDestinationDataflow = destinationDataflow;
+//             this.customDestinationName = label;
+//             updateDestinationSection();
+//             radioCustomDestination.doClick();
+//     }
+
+//     public void setDestinationEnabled(boolean destinationEnabled) {
+//             this.destinationEnabled = destinationEnabled;
+//             updateDestinationSection();
+//     }
+
+       public void setSourceEnabled(boolean sourceEnabled) {
+               this.sourceEnabled = sourceEnabled;
+               updateSourceSection();
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/menu/AddNestedWorkflowMenuAction.java
----------------------------------------------------------------------
diff --git 
a/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/menu/AddNestedWorkflowMenuAction.java
 
b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/menu/AddNestedWorkflowMenuAction.java
new file mode 100644
index 0000000..759d24a
--- /dev/null
+++ 
b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/menu/AddNestedWorkflowMenuAction.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright (C) 2007-2009 The University of Manchester
+ *
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program 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 for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ 
******************************************************************************/
+package org.apache.taverna.workbench.file.importworkflow.menu;
+
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.net.URI;
+
+import javax.swing.Action;
+import javax.swing.KeyStroke;
+
+import org.apache.taverna.ui.menu.AbstractMenuAction;
+import org.apache.taverna.ui.menu.MenuManager;
+import org.apache.taverna.workbench.configuration.colour.ColourManager;
+import 
org.apache.taverna.workbench.configuration.workbench.WorkbenchConfiguration;
+import org.apache.taverna.workbench.edits.EditManager;
+import org.apache.taverna.workbench.file.FileManager;
+import 
org.apache.taverna.workbench.file.importworkflow.actions.AddNestedWorkflowAction;
+import org.apache.taverna.workbench.selection.SelectionManager;
+import net.sf.taverna.t2.workbench.views.graph.menu.InsertMenu;
+
+/**
+ * An action to add a nested workflow activity + a wrapping processor to the
+ * workflow.
+ *
+ * @author Alex Nenadic
+ * @author Stian Soiland-Reyes
+ *
+ */
+public class AddNestedWorkflowMenuAction extends AbstractMenuAction {
+
+       private static final String ADD_NESTED_WORKFLOW = "Nested workflow";
+
+       private static final URI ADD_NESTED_WORKFLOW_URI = URI
+                       
.create("http://taverna.sf.net/2008/t2workbench/menu#graphMenuAddNestedWorkflow";);
+
+       private EditManager editManager;
+       private FileManager fileManager;
+       private MenuManager menuManager;
+       private ColourManager colourManager;
+       private WorkbenchConfiguration workbenchConfiguration;
+       private SelectionManager selectionManager;
+
+       public AddNestedWorkflowMenuAction() {
+               super(InsertMenu.INSERT, 400, ADD_NESTED_WORKFLOW_URI);
+       }
+
+       @Override
+       protected Action createAction() {
+               AddNestedWorkflowAction a = new 
AddNestedWorkflowAction(editManager, fileManager,
+                               menuManager, colourManager, 
workbenchConfiguration, selectionManager);
+               // Override name to avoid "Add "
+               a.putValue(Action.NAME, ADD_NESTED_WORKFLOW);
+               a.putValue(Action.SHORT_DESCRIPTION, ADD_NESTED_WORKFLOW);
+               a.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(
+                               KeyEvent.VK_N, InputEvent.SHIFT_DOWN_MASK
+                                               | InputEvent.ALT_DOWN_MASK));
+               return a;
+
+       }
+
+       public void setEditManager(EditManager editManager) {
+               this.editManager = editManager;
+       }
+
+       public void setFileManager(FileManager fileManager) {
+               this.fileManager = fileManager;
+       }
+
+       public void setMenuManager(MenuManager menuManager) {
+               this.menuManager = menuManager;
+       }
+
+       public void setColourManager(ColourManager colourManager) {
+               this.colourManager = colourManager;
+       }
+
+       public void setWorkbenchConfiguration(WorkbenchConfiguration 
workbenchConfiguration) {
+               this.workbenchConfiguration = workbenchConfiguration;
+       }
+
+       public void setSelectionManager(SelectionManager selectionManager) {
+               this.selectionManager = selectionManager;
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/menu/ImportWorkflowMenuAction.java
----------------------------------------------------------------------
diff --git 
a/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/menu/ImportWorkflowMenuAction.java
 
b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/menu/ImportWorkflowMenuAction.java
new file mode 100644
index 0000000..48870ca
--- /dev/null
+++ 
b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/menu/ImportWorkflowMenuAction.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (C) 2007-2009 The University of Manchester
+ *
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program 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 for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ 
******************************************************************************/
+package org.apache.taverna.workbench.file.importworkflow.menu;
+
+import java.net.URI;
+
+import javax.swing.Action;
+
+import org.apache.taverna.ui.menu.AbstractContextualMenuAction;
+import org.apache.taverna.ui.menu.MenuManager;
+import org.apache.taverna.workbench.configuration.colour.ColourManager;
+import 
org.apache.taverna.workbench.configuration.workbench.WorkbenchConfiguration;
+import org.apache.taverna.workbench.edits.EditManager;
+import org.apache.taverna.workbench.file.FileManager;
+import 
org.apache.taverna.workbench.file.importworkflow.actions.ImportWorkflowAction;
+import org.apache.taverna.workbench.selection.SelectionManager;
+import org.apache.taverna.scufl2.api.core.Workflow;
+
+/**
+ * An action to import nested/merged workflows.
+ *
+ * @author Alex Nenadic
+ * @author Stian Soiland-Reyes
+ *
+ */
+public class ImportWorkflowMenuAction extends AbstractContextualMenuAction {
+
+       private static final URI insertSection = URI
+                       
.create("http://taverna.sf.net/2009/contextMenu/insert";);
+
+       private EditManager editManager;
+       private FileManager fileManager;
+       private MenuManager menuManager;
+       private ColourManager colourManager;
+       private WorkbenchConfiguration workbenchConfiguration;
+       private SelectionManager selectionManager;
+
+       public ImportWorkflowMenuAction() {
+               super(insertSection, 400);
+       }
+
+       @Override
+       public boolean isEnabled() {
+               return super.isEnabled() && 
getContextualSelection().getSelection() instanceof Workflow;
+       }
+
+       @Override
+       protected Action createAction() {
+               ImportWorkflowAction myAction = new 
ImportWorkflowAction(editManager, fileManager,
+                               menuManager, colourManager, 
workbenchConfiguration, selectionManager);
+               // Just "Workflow" as we go under the "Insert" menu
+               myAction.putValue(Action.NAME, "Nested workflow");
+               return myAction;
+       }
+
+       public void setEditManager(EditManager editManager) {
+               this.editManager = editManager;
+       }
+
+       public void setFileManager(FileManager fileManager) {
+               this.fileManager = fileManager;
+       }
+
+       public void setMenuManager(MenuManager menuManager) {
+               this.menuManager = menuManager;
+       }
+
+       public void setColourManager(ColourManager colourManager) {
+               this.colourManager = colourManager;
+       }
+
+       public void setWorkbenchConfiguration(WorkbenchConfiguration 
workbenchConfiguration) {
+               this.workbenchConfiguration = workbenchConfiguration;
+       }
+
+       public void setSelectionManager(SelectionManager selectionManager) {
+               this.selectionManager = selectionManager;
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/menu/MergeWorkflowMenuAction.java
----------------------------------------------------------------------
diff --git 
a/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/menu/MergeWorkflowMenuAction.java
 
b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/menu/MergeWorkflowMenuAction.java
new file mode 100644
index 0000000..05cf1f5
--- /dev/null
+++ 
b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/menu/MergeWorkflowMenuAction.java
@@ -0,0 +1,65 @@
+package org.apache.taverna.workbench.file.importworkflow.menu;
+
+import java.net.URI;
+
+import javax.swing.Action;
+
+import org.apache.taverna.ui.menu.AbstractMenuAction;
+import org.apache.taverna.ui.menu.MenuManager;
+import org.apache.taverna.workbench.configuration.colour.ColourManager;
+import 
org.apache.taverna.workbench.configuration.workbench.WorkbenchConfiguration;
+import org.apache.taverna.workbench.edits.EditManager;
+import org.apache.taverna.workbench.file.FileManager;
+import 
org.apache.taverna.workbench.file.importworkflow.actions.MergeWorkflowAction;
+import org.apache.taverna.workbench.selection.SelectionManager;
+
+public class MergeWorkflowMenuAction extends AbstractMenuAction {
+
+       public static final URI INSERT_URI = URI
+                       
.create("http://taverna.sf.net/2008/t2workbench/menu#insert";);
+
+       public static final URI IMPORT_URI = URI
+                       
.create("http://taverna.sf.net/2008/t2workbench/menu#insert";);
+
+       private EditManager editManager;
+       private FileManager fileManager;
+       private MenuManager menuManager;
+       private ColourManager colourManager;
+       private WorkbenchConfiguration workbenchConfiguration;
+       private SelectionManager selectionManager;
+
+       public MergeWorkflowMenuAction() {
+               super(INSERT_URI, 2000, IMPORT_URI);
+       }
+
+       @Override
+       protected Action createAction() {
+               return new MergeWorkflowAction(editManager, fileManager, 
menuManager, colourManager,
+                               workbenchConfiguration, selectionManager);
+       }
+
+       public void setEditManager(EditManager editManager) {
+               this.editManager = editManager;
+       }
+
+       public void setFileManager(FileManager fileManager) {
+               this.fileManager = fileManager;
+       }
+
+       public void setMenuManager(MenuManager menuManager) {
+               this.menuManager = menuManager;
+       }
+
+       public void setColourManager(ColourManager colourManager) {
+               this.colourManager = colourManager;
+       }
+
+       public void setWorkbenchConfiguration(WorkbenchConfiguration 
workbenchConfiguration) {
+               this.workbenchConfiguration = workbenchConfiguration;
+       }
+
+       public void setSelectionManager(SelectionManager selectionManager) {
+               this.selectionManager = selectionManager;
+       }
+
+}

Reply via email to