You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@taverna.apache.org by re...@apache.org on 2015/03/26 19:52:17 UTC

[28/51] [partial] incubator-taverna-workbench git commit: all packages are moved to org.apache.taverna.*

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;
+	}
+
+}