You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@taverna.apache.org by st...@apache.org on 2015/03/20 15:22:51 UTC

[37/51] [abbrv] [partial] incubator-taverna-workbench git commit: taverna-workbench-* -> taverna-*

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/ChangeJsonEdit.java
----------------------------------------------------------------------
diff --git a/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/ChangeJsonEdit.java b/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/ChangeJsonEdit.java
new file mode 100644
index 0000000..2c79ff3
--- /dev/null
+++ b/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/ChangeJsonEdit.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (C) 2012 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 net.sf.taverna.t2.workflow.edits;
+
+import uk.org.taverna.scufl2.api.configurations.Configuration;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+/**
+ * Changes the JSON of a configuration.
+ * 
+ * @author David Withers
+ */
+public class ChangeJsonEdit extends AbstractEdit<Configuration> {
+	private JsonNode oldJson, newJson;
+
+	public ChangeJsonEdit(Configuration configuration, JsonNode newJson) {
+		super(configuration);
+		this.newJson = newJson;
+		newJson = configuration.getJson();
+	}
+
+	@Override
+	protected void doEditAction(Configuration configuration) {
+		configuration.setJson(newJson);
+	}
+
+	@Override
+	protected void undoEditAction(Configuration configuration) {
+		configuration.setJson(oldJson);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/ClearIterationStrategyStackEdit.java
----------------------------------------------------------------------
diff --git a/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/ClearIterationStrategyStackEdit.java b/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/ClearIterationStrategyStackEdit.java
new file mode 100644
index 0000000..956857c
--- /dev/null
+++ b/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/ClearIterationStrategyStackEdit.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (C) 2011 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 net.sf.taverna.t2.workflow.edits;
+
+import uk.org.taverna.scufl2.api.iterationstrategy.IterationStrategyStack;
+
+/**
+ * Removes all the iteration strategies from an iteration strategy stack.
+ * 
+ * @author David Withers
+ */
+public class ClearIterationStrategyStackEdit extends
+		AbstractEdit<IterationStrategyStack> {
+	private IterationStrategyStack oldIterationStrategyStack;
+
+	public ClearIterationStrategyStackEdit(
+			IterationStrategyStack iterationStrategyStack) {
+		super(iterationStrategyStack);
+	}
+
+	@Override
+	protected void doEditAction(IterationStrategyStack iterationStrategyStack) {
+		oldIterationStrategyStack = new IterationStrategyStack();
+		oldIterationStrategyStack.addAll(iterationStrategyStack);
+		iterationStrategyStack.clear();
+	}
+
+	@Override
+	public void undoEditAction(IterationStrategyStack iterationStrategyStack) {
+		iterationStrategyStack.addAll(oldIterationStrategyStack);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/ConfigureEdit.java
----------------------------------------------------------------------
diff --git a/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/ConfigureEdit.java b/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/ConfigureEdit.java
new file mode 100644
index 0000000..f4274b0
--- /dev/null
+++ b/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/ConfigureEdit.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (C) 2012 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 net.sf.taverna.t2.workflow.edits;
+
+import uk.org.taverna.scufl2.api.common.Configurable;
+import uk.org.taverna.scufl2.api.configurations.Configuration;
+
+/**
+ * An Edit that configures a {@link Configurable} with a given
+ * {@link Configuration}.
+ * 
+ * @author David Withers
+ */
+public class ConfigureEdit<ConfigurableType extends Configurable> extends
+		AbstractEdit<ConfigurableType> {
+	private final Configuration oldConfiguration;
+	private final Configuration newConfiguration;
+
+	public ConfigureEdit(ConfigurableType configurable,
+			Configuration oldConfiguration, Configuration newConfiguration) {
+		super(configurable);
+		this.oldConfiguration = oldConfiguration;
+		this.newConfiguration = newConfiguration;
+	}
+
+	@Override
+	protected void doEditAction(ConfigurableType configurable) {
+		oldConfiguration.setConfigures(null);
+		newConfiguration.setConfigures(configurable);
+	}
+
+	@Override
+	protected void undoEditAction(ConfigurableType configurable) {
+		oldConfiguration.setConfigures(configurable);
+		newConfiguration.setConfigures(null);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveActivityEdit.java
----------------------------------------------------------------------
diff --git a/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveActivityEdit.java b/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveActivityEdit.java
new file mode 100644
index 0000000..1350d88
--- /dev/null
+++ b/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveActivityEdit.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * 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 net.sf.taverna.t2.workflow.edits;
+
+import uk.org.taverna.scufl2.api.activity.Activity;
+import uk.org.taverna.scufl2.api.core.Processor;
+import uk.org.taverna.scufl2.api.profiles.ProcessorBinding;
+
+/**
+ * Remove an Activity from a Processor.
+ *
+ * @author alanrw
+ */
+public class RemoveActivityEdit extends AbstractEdit<Processor> {
+	private Activity activityToRemove;
+	private ProcessorBinding removedProcessorBinding;
+
+	public RemoveActivityEdit(Processor processor, Activity activity) {
+		super(processor);
+		this.activityToRemove = activity;
+	}
+
+	@Override
+	protected void doEditAction(Processor processor) {
+		for (ProcessorBinding binding : scufl2Tools
+				.processorBindingsToActivity(activityToRemove))
+			if (binding.getBoundProcessor().equals(processor)) {
+				removedProcessorBinding = binding;
+				removedProcessorBinding.setParent(null);
+			}
+	}
+
+	@Override
+	protected void undoEditAction(Processor processor) {
+		removedProcessorBinding.setParent(activityToRemove.getParent());
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveActivityInputPortMappingEdit.java
----------------------------------------------------------------------
diff --git a/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveActivityInputPortMappingEdit.java b/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveActivityInputPortMappingEdit.java
new file mode 100644
index 0000000..ce058bf
--- /dev/null
+++ b/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveActivityInputPortMappingEdit.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * 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 net.sf.taverna.t2.workflow.edits;
+
+import uk.org.taverna.scufl2.api.activity.Activity;
+import uk.org.taverna.scufl2.api.port.InputActivityPort;
+import uk.org.taverna.scufl2.api.profiles.ProcessorBinding;
+import uk.org.taverna.scufl2.api.profiles.ProcessorInputPortBinding;
+
+public class RemoveActivityInputPortMappingEdit extends AbstractEdit<Activity> {
+	private final InputActivityPort inputActivityPort;
+	private ProcessorInputPortBinding removedPortBinding;
+	private ProcessorBinding processorBinding;
+
+	public RemoveActivityInputPortMappingEdit(Activity activity,
+			InputActivityPort inputActivityPort) {
+		super(activity);
+		this.inputActivityPort = inputActivityPort;
+	}
+
+	@Override
+	protected void doEditAction(Activity activity) {
+		removedPortBinding = scufl2Tools.processorPortBindingForPort(
+				inputActivityPort, activity.getParent());
+		processorBinding = removedPortBinding.getParent();
+		removedPortBinding.setParent(null);
+	}
+
+	@Override
+	protected void undoEditAction(Activity activity) {
+		removedPortBinding.setParent(processorBinding);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveActivityOutputPortMappingEdit.java
----------------------------------------------------------------------
diff --git a/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveActivityOutputPortMappingEdit.java b/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveActivityOutputPortMappingEdit.java
new file mode 100644
index 0000000..8639dbd
--- /dev/null
+++ b/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveActivityOutputPortMappingEdit.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * 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 net.sf.taverna.t2.workflow.edits;
+
+import uk.org.taverna.scufl2.api.activity.Activity;
+import uk.org.taverna.scufl2.api.port.OutputActivityPort;
+import uk.org.taverna.scufl2.api.profiles.ProcessorBinding;
+import uk.org.taverna.scufl2.api.profiles.ProcessorOutputPortBinding;
+
+public class RemoveActivityOutputPortMappingEdit extends AbstractEdit<Activity> {
+	private final OutputActivityPort outputActivityPort;
+	private ProcessorOutputPortBinding removedPortBinding;
+	private ProcessorBinding processorBinding;
+
+	public RemoveActivityOutputPortMappingEdit(Activity activity,
+			OutputActivityPort outputActivityPort) {
+		super(activity);
+		this.outputActivityPort = outputActivityPort;
+	}
+
+	@Override
+	protected void doEditAction(Activity activity) {
+		removedPortBinding = scufl2Tools.processorPortBindingForPort(
+				outputActivityPort, activity.getParent());
+		processorBinding = removedPortBinding.getParent();
+		removedPortBinding.setParent(null);
+	}
+
+	@Override
+	protected void undoEditAction(Activity activity) {
+		removedPortBinding.setParent(processorBinding);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveChildEdit.java
----------------------------------------------------------------------
diff --git a/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveChildEdit.java b/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveChildEdit.java
new file mode 100644
index 0000000..1b9d5d2
--- /dev/null
+++ b/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveChildEdit.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (C) 2012 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 net.sf.taverna.t2.workflow.edits;
+
+import uk.org.taverna.scufl2.api.common.Child;
+import uk.org.taverna.scufl2.api.common.WorkflowBean;
+
+/**
+ * Removes a child from a parent.
+ * 
+ * @author David Withers
+ */
+public class RemoveChildEdit<T extends WorkflowBean> extends AbstractEdit<T> {
+	private Child<T> child;
+
+	public RemoveChildEdit(T parent, Child<T> child) {
+		super(parent);
+		this.child = child;
+	}
+
+	@Override
+	protected void doEditAction(T parent) {
+		child.setParent(null);
+	}
+
+	@Override
+	protected void undoEditAction(T parent) {
+		child.setParent(parent);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveDataLinkEdit.java
----------------------------------------------------------------------
diff --git a/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveDataLinkEdit.java b/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveDataLinkEdit.java
new file mode 100644
index 0000000..9f8d243
--- /dev/null
+++ b/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveDataLinkEdit.java
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * 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 net.sf.taverna.t2.workflow.edits;
+
+import java.util.List;
+
+import uk.org.taverna.scufl2.api.core.DataLink;
+import uk.org.taverna.scufl2.api.core.Workflow;
+import uk.org.taverna.scufl2.api.iterationstrategy.IterationStrategyNode;
+import uk.org.taverna.scufl2.api.iterationstrategy.IterationStrategyParent;
+import uk.org.taverna.scufl2.api.iterationstrategy.IterationStrategyTopNode;
+import uk.org.taverna.scufl2.api.iterationstrategy.PortNode;
+import uk.org.taverna.scufl2.api.port.InputProcessorPort;
+import uk.org.taverna.scufl2.api.port.ReceiverPort;
+
+/**
+ * Remove a DataLink from a Workflow.
+ * <p>
+ * Handles setting the merge position of all dataLinks with the same receiver port.
+ *
+ * @author David Withers
+ */
+public class RemoveDataLinkEdit extends AbstractEdit<Workflow> {
+	private final DataLink dataLink;
+	private PortNode portNode;
+	private int portPosition;
+	private IterationStrategyTopNode parent;
+
+	public RemoveDataLinkEdit(Workflow workflow, DataLink dataLink) {
+		super(workflow);
+		this.dataLink = dataLink;
+	}
+
+	@Override
+	protected void doEditAction(Workflow workflow) {
+		dataLink.setParent(null);
+		ReceiverPort sink = dataLink.getSendsTo();
+		List<DataLink> datalinksTo = scufl2Tools.datalinksTo(sink);
+		if (datalinksTo.isEmpty()) {
+			if (sink instanceof InputProcessorPort) {
+				InputProcessorPort port = (InputProcessorPort) sink;
+				for (IterationStrategyTopNode topNode : port.getParent().getIterationStrategyStack()) {
+					portNode = findPortNode(topNode, port);
+					if (portNode != null) {
+						IterationStrategyParent parentNode = portNode.getParent();
+						if (parentNode instanceof IterationStrategyTopNode) {
+							parent = (IterationStrategyTopNode) parentNode;
+							portPosition = parent.indexOf(portNode);
+							parent.remove(portNode);
+						}
+						break;
+					}
+				}
+			}
+		} else if (datalinksTo.size() == 1) {
+			datalinksTo.get(0).setMergePosition(null);
+		} else {
+			for (int i = 0; i < datalinksTo.size(); i++)
+				datalinksTo.get(i).setMergePosition(i);
+		}
+	}
+
+	@Override
+	protected void undoEditAction(Workflow workflow) {
+		ReceiverPort sink = dataLink.getSendsTo();
+		List<DataLink> datalinksTo = scufl2Tools.datalinksTo(sink);
+		if (dataLink.getMergePosition() != null)
+			for (int i = dataLink.getMergePosition(); i < datalinksTo.size(); i++)
+				datalinksTo.get(i).setMergePosition(i + 1);
+		if (portNode != null) {
+			parent.add(portPosition, portNode);
+			portNode.setParent(parent);
+		}
+		dataLink.setParent(workflow);
+	}
+
+	private PortNode findPortNode(IterationStrategyTopNode topNode,
+			InputProcessorPort port) {
+		for (IterationStrategyNode node : topNode) {
+			if (node instanceof PortNode) {
+				PortNode portNode = (PortNode) node;
+				if (port.equals(portNode.getInputProcessorPort()))
+					return portNode;
+			} else if (node instanceof IterationStrategyTopNode) {
+				IterationStrategyTopNode iterationStrategyTopNode = (IterationStrategyTopNode) node;
+				PortNode result = findPortNode(iterationStrategyTopNode, port);
+				if (result != null)
+					return result;
+			}
+		}
+		return null;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveProcessorInputPortEdit.java
----------------------------------------------------------------------
diff --git a/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveProcessorInputPortEdit.java b/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveProcessorInputPortEdit.java
new file mode 100644
index 0000000..497f700
--- /dev/null
+++ b/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveProcessorInputPortEdit.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * 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 net.sf.taverna.t2.workflow.edits;
+
+import uk.org.taverna.scufl2.api.core.Processor;
+import uk.org.taverna.scufl2.api.port.InputProcessorPort;
+
+public class RemoveProcessorInputPortEdit extends RemoveChildEdit<Processor> {
+	public RemoveProcessorInputPortEdit(Processor processor,
+			InputProcessorPort port) {
+		super(processor, port);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveProcessorOutputPortEdit.java
----------------------------------------------------------------------
diff --git a/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveProcessorOutputPortEdit.java b/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveProcessorOutputPortEdit.java
new file mode 100644
index 0000000..72a1238
--- /dev/null
+++ b/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveProcessorOutputPortEdit.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * 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 net.sf.taverna.t2.workflow.edits;
+
+import uk.org.taverna.scufl2.api.core.Processor;
+import uk.org.taverna.scufl2.api.port.OutputProcessorPort;
+
+public class RemoveProcessorOutputPortEdit extends RemoveChildEdit<Processor> {
+	public RemoveProcessorOutputPortEdit(Processor processor,
+			OutputProcessorPort port) {
+		super(processor, port);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveWorkflowInputPortEdit.java
----------------------------------------------------------------------
diff --git a/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveWorkflowInputPortEdit.java b/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveWorkflowInputPortEdit.java
new file mode 100644
index 0000000..a6ac8e4
--- /dev/null
+++ b/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveWorkflowInputPortEdit.java
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * 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 net.sf.taverna.t2.workflow.edits;
+
+import static uk.org.taverna.scufl2.api.common.Scufl2Tools.NESTED_WORKFLOW;
+
+import java.util.List;
+
+import net.sf.taverna.t2.workbench.edits.CompoundEdit;
+import net.sf.taverna.t2.workbench.edits.Edit;
+import net.sf.taverna.t2.workbench.edits.EditException;
+import uk.org.taverna.scufl2.api.activity.Activity;
+import uk.org.taverna.scufl2.api.configurations.Configuration;
+import uk.org.taverna.scufl2.api.container.WorkflowBundle;
+import uk.org.taverna.scufl2.api.core.Processor;
+import uk.org.taverna.scufl2.api.core.Workflow;
+import uk.org.taverna.scufl2.api.port.InputActivityPort;
+import uk.org.taverna.scufl2.api.port.InputProcessorPort;
+import uk.org.taverna.scufl2.api.port.InputWorkflowPort;
+import uk.org.taverna.scufl2.api.profiles.ProcessorBinding;
+import uk.org.taverna.scufl2.api.profiles.ProcessorInputPortBinding;
+import uk.org.taverna.scufl2.api.profiles.Profile;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+/**
+ * Removes an input port from a workflow.
+ *
+ * @author David Withers
+ */
+public class RemoveWorkflowInputPortEdit extends AbstractEdit<Workflow> {
+	private final InputWorkflowPort port;
+	private final CompoundEdit nestedPortEdit = new CompoundEdit();
+
+	public RemoveWorkflowInputPortEdit(Workflow workflow, InputWorkflowPort port) {
+		super(workflow);
+		this.port = port;
+		WorkflowBundle workflowBundle = workflow.getParent();
+		if (workflowBundle != null)
+			for (Profile profile : workflowBundle.getProfiles())
+				for (Activity activity : profile.getActivities())
+					if (activity.getType().equals(NESTED_WORKFLOW))
+						for (Configuration c : scufl2Tools.configurationsFor(
+								activity, profile))
+							defineEditsForConfiguration(workflow, port,
+									workflowBundle, activity, c);
+	}
+
+	private void defineEditsForConfiguration(Workflow workflow,
+			InputWorkflowPort port, WorkflowBundle workflowBundle,
+			Activity activity, Configuration c) {
+		List<Edit<?>> edits = nestedPortEdit.getChildEdits();
+		JsonNode nested = c.getJson().get("nestedWorkflow");
+		Workflow nestedWorkflow = workflowBundle.getWorkflows().getByName(
+				nested.asText());
+		if (nestedWorkflow != workflow)
+			return;
+
+		InputActivityPort activityPort = activity.getInputPorts().getByName(
+				port.getName());
+		edits.add(new RemoveChildEdit<>(activity, activityPort));
+
+		for (ProcessorBinding binding : scufl2Tools
+				.processorBindingsToActivity(activity)) {
+			Processor processor = binding.getBoundProcessor();
+			for (ProcessorInputPortBinding portBinding : binding
+					.getInputPortBindings())
+				if (portBinding.getBoundActivityPort() == activityPort) {
+					InputProcessorPort processorPort = portBinding
+							.getBoundProcessorPort();
+					edits.add(new RemoveProcessorInputPortEdit(processor,
+							processorPort));
+					edits.add(new RemoveChildEdit<>(binding, portBinding));
+				}
+		}
+	}
+
+	@Override
+	protected void doEditAction(Workflow workflow) throws EditException {
+		port.setParent(null);
+		nestedPortEdit.doEdit();
+	}
+
+	@Override
+	protected void undoEditAction(Workflow workflow) {
+		port.setParent(workflow);
+		nestedPortEdit.undo();
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveWorkflowOutputPortEdit.java
----------------------------------------------------------------------
diff --git a/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveWorkflowOutputPortEdit.java b/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveWorkflowOutputPortEdit.java
new file mode 100644
index 0000000..2c71da6
--- /dev/null
+++ b/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveWorkflowOutputPortEdit.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * 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 net.sf.taverna.t2.workflow.edits;
+
+import static uk.org.taverna.scufl2.api.common.Scufl2Tools.NESTED_WORKFLOW;
+
+import java.util.List;
+
+import net.sf.taverna.t2.workbench.edits.CompoundEdit;
+import net.sf.taverna.t2.workbench.edits.Edit;
+import net.sf.taverna.t2.workbench.edits.EditException;
+import uk.org.taverna.scufl2.api.activity.Activity;
+import uk.org.taverna.scufl2.api.configurations.Configuration;
+import uk.org.taverna.scufl2.api.container.WorkflowBundle;
+import uk.org.taverna.scufl2.api.core.Workflow;
+import uk.org.taverna.scufl2.api.port.OutputActivityPort;
+import uk.org.taverna.scufl2.api.port.OutputProcessorPort;
+import uk.org.taverna.scufl2.api.port.OutputWorkflowPort;
+import uk.org.taverna.scufl2.api.profiles.ProcessorBinding;
+import uk.org.taverna.scufl2.api.profiles.ProcessorOutputPortBinding;
+import uk.org.taverna.scufl2.api.profiles.Profile;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+/**
+ * Removes an output port from a workflow.
+ *
+ * @author David Withers
+ */
+public class RemoveWorkflowOutputPortEdit extends AbstractEdit<Workflow> {
+	private final OutputWorkflowPort port;
+	private final CompoundEdit nestedPortEdit = new CompoundEdit();
+
+	public RemoveWorkflowOutputPortEdit(Workflow workflow,
+			OutputWorkflowPort port) {
+		super(workflow);
+		this.port = port;
+		WorkflowBundle workflowBundle = workflow.getParent();
+		if (workflowBundle != null)
+			for (Profile profile : workflowBundle.getProfiles())
+				for (Activity activity : profile.getActivities())
+					if (activity.getType().equals(NESTED_WORKFLOW))
+						for (Configuration c : scufl2Tools.configurationsFor(
+								activity, profile))
+							defineEditsForConfiguration(workflow, port,
+									workflowBundle, activity, c);
+	}
+
+	private void defineEditsForConfiguration(Workflow workflow,
+			OutputWorkflowPort port, WorkflowBundle workflowBundle,
+			Activity activity, Configuration c) {
+		List<Edit<?>> edits = nestedPortEdit.getChildEdits();
+		JsonNode nested = c.getJson().get("nestedWorkflow");
+		Workflow nestedWorkflow = workflowBundle.getWorkflows().getByName(
+				nested.asText());
+		if (nestedWorkflow != workflow)
+			return;
+
+		OutputActivityPort activityPort = activity.getOutputPorts().getByName(
+				port.getName());
+		edits.add(new RemoveChildEdit<>(activity, activityPort));
+		for (ProcessorBinding processorBinding : scufl2Tools
+				.processorBindingsToActivity(activity))
+			for (ProcessorOutputPortBinding portBinding : processorBinding
+					.getOutputPortBindings())
+				if (portBinding.getBoundActivityPort() == activityPort) {
+					OutputProcessorPort processorPort = portBinding
+							.getBoundProcessorPort();
+					edits.add(new RemoveProcessorOutputPortEdit(
+							processorBinding.getBoundProcessor(), processorPort));
+					edits.add(new RemoveChildEdit<>(processorBinding,
+							portBinding));
+				}
+	}
+
+	@Override
+	protected void doEditAction(Workflow workflow) throws EditException {
+		port.setParent(null);
+		nestedPortEdit.doEdit();
+	}
+
+	@Override
+	protected void undoEditAction(Workflow workflow) {
+		port.setParent(workflow);
+		nestedPortEdit.undo();
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RenameEdit.java
----------------------------------------------------------------------
diff --git a/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RenameEdit.java b/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RenameEdit.java
new file mode 100644
index 0000000..beb4913
--- /dev/null
+++ b/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RenameEdit.java
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * Copyright (C) 2012 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 net.sf.taverna.t2.workflow.edits;
+
+import static uk.org.taverna.scufl2.api.common.Scufl2Tools.NESTED_WORKFLOW;
+import uk.org.taverna.scufl2.api.activity.Activity;
+import uk.org.taverna.scufl2.api.common.Named;
+import uk.org.taverna.scufl2.api.configurations.Configuration;
+import uk.org.taverna.scufl2.api.container.WorkflowBundle;
+import uk.org.taverna.scufl2.api.core.Workflow;
+import uk.org.taverna.scufl2.api.port.ActivityPort;
+import uk.org.taverna.scufl2.api.port.InputPort;
+import uk.org.taverna.scufl2.api.port.ProcessorPort;
+import uk.org.taverna.scufl2.api.port.WorkflowPort;
+import uk.org.taverna.scufl2.api.profiles.ProcessorBinding;
+import uk.org.taverna.scufl2.api.profiles.ProcessorInputPortBinding;
+import uk.org.taverna.scufl2.api.profiles.ProcessorOutputPortBinding;
+import uk.org.taverna.scufl2.api.profiles.Profile;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+/**
+ * Renames a Named WorkflowBean.
+ *
+ * @author David Withers
+ */
+public class RenameEdit<T extends Named> extends AbstractEdit<T> {
+	private String oldName, newName;
+
+	public RenameEdit(T named, String newName) {
+		super(named);
+		this.newName = newName;
+		oldName = named.getName();
+	}
+
+	@Override
+	protected void doEditAction(T named) {
+		named.setName(newName);
+		if (named instanceof WorkflowPort)
+			checkNestedPortNames((WorkflowPort) named, oldName, newName);
+	}
+
+	@Override
+	protected void undoEditAction(T named) {
+		named.setName(oldName);
+		if (named instanceof WorkflowPort)
+			checkNestedPortNames((WorkflowPort) named, newName, oldName);
+	}
+
+	private void checkNestedPortNames(WorkflowPort workflowPort, String oldName, String newName) {
+		Workflow workflow = workflowPort.getParent();
+		if (workflow == null)
+			return;
+		WorkflowBundle workflowBundle = workflow.getParent();
+		if (workflowBundle == null)
+			return;
+		for (Profile profile : workflowBundle.getProfiles())
+			for (Activity activity : profile.getActivities())
+				if (activity.getType().equals(NESTED_WORKFLOW))
+					for (Configuration c : scufl2Tools.configurationsFor(activity, profile))
+						changeActivityPortName(workflowPort, oldName,
+								newName, workflow, workflowBundle, activity, c);
+	}
+
+	private void changeActivityPortName(WorkflowPort workflowPort,
+			String oldName, String newName, Workflow workflow,
+			WorkflowBundle workflowBundle, Activity activity, Configuration c) {
+		JsonNode nested = c.getJson().get("nestedWorkflow");
+		Workflow nestedWorkflow = workflowBundle.getWorkflows().getByName(
+				nested.asText());
+		if (nestedWorkflow != workflow)
+			return;
+
+		ActivityPort activityPort;
+		if (workflowPort instanceof InputPort) {
+			activityPort = activity.getInputPorts().getByName(oldName);
+			changeProcessorInputPortName(oldName, newName, activity,
+					activityPort);
+		} else {
+			activityPort = activity.getOutputPorts().getByName(oldName);
+			changeProcessorOutputPortName(oldName, newName, activity,
+					activityPort);
+		}
+		activityPort.setName(newName);
+	}
+
+	private void changeProcessorInputPortName(String oldName, String newName,
+			Activity activity, ActivityPort activityPort) {
+		bindings: for (ProcessorBinding binding : scufl2Tools
+				.processorBindingsToActivity(activity))
+			for (ProcessorInputPortBinding portBinding : binding
+					.getInputPortBindings())
+				if (portBinding.getBoundActivityPort() == activityPort) {
+					ProcessorPort processorPort = portBinding
+							.getBoundProcessorPort();
+					if (processorPort.getName().equals(oldName)) {
+						processorPort.setName(newName);
+						continue bindings;
+					}
+				}
+	}
+
+	private void changeProcessorOutputPortName(String oldName, String newName,
+			Activity activity, ActivityPort activityPort) {
+		bindings: for (ProcessorBinding binding : scufl2Tools
+				.processorBindingsToActivity(activity))
+			for (ProcessorOutputPortBinding portBinding : binding
+					.getOutputPortBindings())
+				if (portBinding.getBoundActivityPort() == activityPort) {
+					ProcessorPort processorPort = portBinding
+							.getBoundProcessorPort();
+					if (processorPort.getName().equals(oldName)) {
+						processorPort.setName(newName);
+						continue bindings;
+					}
+				}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/ReorderMergePositionsEdit.java
----------------------------------------------------------------------
diff --git a/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/ReorderMergePositionsEdit.java b/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/ReorderMergePositionsEdit.java
new file mode 100644
index 0000000..49caa32
--- /dev/null
+++ b/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/ReorderMergePositionsEdit.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (C) 2012 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 net.sf.taverna.t2.workflow.edits;
+
+import java.util.List;
+
+import net.sf.taverna.t2.workbench.edits.EditException;
+import uk.org.taverna.scufl2.api.core.DataLink;
+import uk.org.taverna.scufl2.api.port.ReceiverPort;
+
+/**
+ * Change datalink merge positions based on ordered list of data links.
+ * 
+ * @author David Withers
+ * @author Stian Soiland-Reyes
+ */
+public class ReorderMergePositionsEdit extends AbstractEdit<ReceiverPort> {
+	private List<DataLink> newMergePositions;
+	private final List<DataLink> oldMergePositions;
+
+	public ReorderMergePositionsEdit(List<DataLink> dataLinks,
+			List<DataLink> newMergePositions) {
+		super(dataLinks.get(0).getSendsTo());
+		this.oldMergePositions = dataLinks;
+		this.newMergePositions = newMergePositions;
+	}
+
+	@Override
+	protected void doEditAction(ReceiverPort subject) throws EditException {
+		for (int i = 0; i < newMergePositions.size(); i++)
+			newMergePositions.get(i).setMergePosition(i);
+	}
+
+	@Override
+	protected void undoEditAction(ReceiverPort subject) {
+		for (int i = 0; i < oldMergePositions.size(); i++)
+			oldMergePositions.get(i).setMergePosition(i);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/SetIterationStrategyStackEdit.java
----------------------------------------------------------------------
diff --git a/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/SetIterationStrategyStackEdit.java b/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/SetIterationStrategyStackEdit.java
new file mode 100644
index 0000000..e16b95f
--- /dev/null
+++ b/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/SetIterationStrategyStackEdit.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * 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 net.sf.taverna.t2.workflow.edits;
+
+import uk.org.taverna.scufl2.api.core.Processor;
+import uk.org.taverna.scufl2.api.iterationstrategy.IterationStrategyStack;
+
+/**
+ * Set the iteration strategy
+ * 
+ * @author Stian Soiland-Reyes
+ */
+public class SetIterationStrategyStackEdit extends AbstractEdit<Processor> {
+	private final IterationStrategyStack iterationStrategyStack;
+	private IterationStrategyStack oldStrategyStack;
+
+	public SetIterationStrategyStackEdit(Processor processor,
+			IterationStrategyStack iterationStrategyStack) {
+		super(processor);
+		this.iterationStrategyStack = iterationStrategyStack;
+	}
+
+	@Override
+	protected void doEditAction(Processor processor) {
+		oldStrategyStack = processor.getIterationStrategyStack();
+		processor.setIterationStrategyStack(iterationStrategyStack);
+	}
+
+	@Override
+	protected void undoEditAction(Processor processor) {
+		processor.setIterationStrategyStack(oldStrategyStack);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/UpdateDataflowInternalIdentifierEdit.java
----------------------------------------------------------------------
diff --git a/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/UpdateDataflowInternalIdentifierEdit.java b/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/UpdateDataflowInternalIdentifierEdit.java
new file mode 100644
index 0000000..f246d60
--- /dev/null
+++ b/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/UpdateDataflowInternalIdentifierEdit.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * 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 net.sf.taverna.t2.workflow.edits;
+
+import java.net.URI;
+
+import uk.org.taverna.scufl2.api.container.WorkflowBundle;
+
+public class UpdateDataflowInternalIdentifierEdit extends
+		AbstractEdit<WorkflowBundle> {
+	private URI newId;
+	private URI oldId;
+
+	public UpdateDataflowInternalIdentifierEdit(WorkflowBundle dataflow,
+			URI newId) {
+		super(dataflow);
+		this.newId = newId;
+		this.oldId = dataflow.getGlobalBaseURI();
+	}
+
+	@Override
+	protected void doEditAction(WorkflowBundle dataflow) {
+		dataflow.setGlobalBaseURI(newId);
+	}
+
+	@Override
+	protected void undoEditAction(WorkflowBundle dataflow) {
+		dataflow.setGlobalBaseURI(oldId);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-edits-impl/pom.xml
----------------------------------------------------------------------
diff --git a/taverna-edits-impl/pom.xml b/taverna-edits-impl/pom.xml
new file mode 100644
index 0000000..98b9026
--- /dev/null
+++ b/taverna-edits-impl/pom.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>org.apache.taverna.workbench</groupId>
+		<artifactId>taverna-workbench</artifactId>
+		<version>3.1.0-incubating-SNAPSHOT</version>
+	</parent>
+	<artifactId>taverna-edits-impl</artifactId>
+	<packaging>bundle</packaging>
+	<name>Edits implementation</name>
+	<description>
+		Implementation for doing workflow edits and undo.
+	</description>
+	<dependencies>
+		<dependency>
+			<groupId>${project.parent.groupId}</groupId>
+			<artifactId>taverna-edits-api</artifactId>
+			<version>${project.parent.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>${project.parent.groupId}</groupId>
+			<artifactId>taverna-menu-api</artifactId>
+			<version>${project.parent.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>${project.parent.groupId}</groupId>
+			<artifactId>taverna-selection-api</artifactId>
+			<version>${project.parent.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>${project.parent.groupId}</groupId>
+			<artifactId>taverna-ui</artifactId>
+			<version>${project.parent.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.taverna.language</groupId>
+			<artifactId>taverna-scufl2-api</artifactId>
+			<version>${taverna.language.version}</version>
+		</dependency>
+
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-edits-impl/src/main/java/net/sf/taverna/t2/workbench/edits/impl/EditManagerImpl.java
----------------------------------------------------------------------
diff --git a/taverna-edits-impl/src/main/java/net/sf/taverna/t2/workbench/edits/impl/EditManagerImpl.java b/taverna-edits-impl/src/main/java/net/sf/taverna/t2/workbench/edits/impl/EditManagerImpl.java
new file mode 100644
index 0000000..f97d36c
--- /dev/null
+++ b/taverna-edits-impl/src/main/java/net/sf/taverna/t2/workbench/edits/impl/EditManagerImpl.java
@@ -0,0 +1,285 @@
+/*******************************************************************************
+ * 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 net.sf.taverna.t2.workbench.edits.impl;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.sf.taverna.t2.lang.observer.MultiCaster;
+import net.sf.taverna.t2.lang.observer.Observer;
+import net.sf.taverna.t2.workbench.edits.Edit;
+import net.sf.taverna.t2.workbench.edits.EditException;
+import net.sf.taverna.t2.workbench.edits.EditManager;
+
+import org.apache.log4j.Logger;
+
+import uk.org.taverna.scufl2.api.container.WorkflowBundle;
+
+/**
+ * Implementation of {@link EditManager}.
+ *
+ * @author Stian Soiland-Reyes
+ */
+public class EditManagerImpl implements EditManager {
+	private static Logger logger = Logger.getLogger(EditManagerImpl.class);
+
+	private MultiCaster<EditManagerEvent> multiCaster = new MultiCaster<>(this);
+	private Map<WorkflowBundle, DataflowEdits> editsForDataflow = new HashMap<>();
+
+	@Override
+	public void addObserver(Observer<EditManagerEvent> observer) {
+		multiCaster.addObserver(observer);
+	}
+
+	@Override
+	public boolean canRedoDataflowEdit(WorkflowBundle dataflow) {
+		DataflowEdits edits = getEditsForDataflow(dataflow);
+		return edits.canRedo();
+	}
+
+	@Override
+	public boolean canUndoDataflowEdit(WorkflowBundle dataflow) {
+		DataflowEdits edits = getEditsForDataflow(dataflow);
+		return edits.canUndo();
+	}
+
+	@Override
+	public void doDataflowEdit(WorkflowBundle dataflow, Edit<?> edit)
+			throws EditException {
+		// We do the edit before we notify the observers
+		DataflowEdits edits = getEditsForDataflow(dataflow);
+		synchronized (edits) {
+			// Make sure the edits are in the order they were performed
+			edit.doEdit();
+			edits.addEdit(edit);
+		}
+		multiCaster.notify(new DataflowEditEvent(dataflow, edit));
+	}
+
+	@Override
+	public List<Observer<EditManagerEvent>> getObservers() {
+		return multiCaster.getObservers();
+	}
+
+	@Override
+	public void redoDataflowEdit(WorkflowBundle dataflow) throws EditException {
+		DataflowEdits edits = getEditsForDataflow(dataflow);
+		Edit<?> edit;
+		synchronized (edits) {
+			if (!edits.canRedo())
+				return;
+			edit = edits.getLastUndo();
+			edit.doEdit();
+			edits.addRedo(edit);
+		}
+		multiCaster.notify(new DataFlowRedoEvent(dataflow, edit));
+	}
+
+	@Override
+	public void removeObserver(Observer<EditManagerEvent> observer) {
+		multiCaster.removeObserver(observer);
+	}
+
+	@Override
+	public void undoDataflowEdit(WorkflowBundle dataflow) {
+		DataflowEdits edits = getEditsForDataflow(dataflow);
+		Edit<?> edit;
+		synchronized (edits) {
+			if (!edits.canUndo())
+				return;
+			edit = edits.getLastEdit();
+			edit.undo();
+			edits.addUndo(edit);
+		}
+		logger.info("Undoing an edit");
+		multiCaster.notify(new DataFlowUndoEvent(dataflow, edit));
+	}
+
+	/**
+	 * Get the set of edits for a given dataflow, creating if neccessary.
+	 *
+	 * @param dataflow
+	 *            Dataflow the edits relate to
+	 * @return A {@link DataflowEdits} instance to keep edits for the given
+	 *         dataflow
+	 */
+	protected synchronized DataflowEdits getEditsForDataflow(WorkflowBundle dataflow) {
+		DataflowEdits edits = editsForDataflow.get(dataflow);
+		if (edits == null) {
+			edits = new DataflowEdits();
+			editsForDataflow.put(dataflow, edits);
+		}
+		return edits;
+	}
+
+	/**
+	 * A set of edits and undoes for a {@link Dataflow}
+	 *
+	 * @author Stian Soiland-Reyes
+	 *
+	 */
+	public class DataflowEdits {
+		/**
+		 * List of edits that have been performed and can be undone.
+		 */
+		private List<Edit<?>> edits = new ArrayList<>();
+		/**
+		 * List of edits that have been undone and can be redone
+		 */
+		private List<Edit<?>> undoes = new ArrayList<>();
+
+		/**
+		 * Add an {@link Edit} that has been done by the EditManager.
+		 * <p>
+		 * This can later be retrieved using {@link #getLastEdit()}. After
+		 * calling this {@link #canRedo()} will be false.
+		 *
+		 * @param edit
+		 *            {@link Edit} that has been undone
+		 */
+		public synchronized void addEdit(Edit<?> edit) {
+			addEditOrRedo(edit, false);
+		}
+
+		/**
+		 * Add an {@link Edit} that has been redone by the EditManager.
+		 * <p>
+		 * The {@link Edit} must be the same as the last undo returned through
+		 * {@link #getLastUndo()}.
+		 * <p>
+		 * This method works like {@link #addEdit(Edit)} except that instead of
+		 * removing all possible redoes, only the given {@link Edit} is removed.
+		 *
+		 * @param edit
+		 *            {@link Edit} that has been redone
+		 */
+		public synchronized void addRedo(Edit<?> edit) {
+			addEditOrRedo(edit, true);
+		}
+
+		/**
+		 * Add an {@link Edit} that has been undone by the EditManager.
+		 * <p>
+		 * After calling this method {@link #canRedo()} will be true, and the
+		 * edit can be retrieved using {@link #getLastUndo()}.
+		 * </p>
+		 * <p>
+		 * The {@link Edit} must be the last edit returned from
+		 * {@link #getLastEdit()}, after calling this method
+		 * {@link #getLastEdit()} will return the previous edit or
+		 * {@link #canUndo()} will be false if there are no more edits.
+		 *
+		 * @param edit
+		 *            {@link Edit} that has been undone
+		 */
+		public synchronized void addUndo(Edit<?> edit) {
+			int lastIndex = edits.size() - 1;
+			if (lastIndex < 0 || !edits.get(lastIndex).equals(edit))
+				throw new IllegalArgumentException("Can't undo unknown edit "
+						+ edit);
+			undoes.add(edit);
+			edits.remove(lastIndex);
+		}
+
+		/**
+		 * True if there are undone events that can be redone.
+		 *
+		 * @return <code>true</code> if there are undone events
+		 */
+		public boolean canRedo() {
+			return !undoes.isEmpty();
+		}
+
+		/**
+		 * True if there are edits that can be undone and later added with
+		 * {@link #addUndo(Edit)}.
+		 *
+		 * @return <code>true</code> if there are edits that can be undone
+		 */
+		public boolean canUndo() {
+			return !edits.isEmpty();
+		}
+
+		/**
+		 * Get the last edit that can be undone. This edit was the last one to
+		 * be added with {@link #addEdit(Edit)} or {@link #addRedo(Edit)}.
+		 *
+		 * @return The last added {@link Edit}
+		 * @throws IllegalStateException
+		 *             If there are no more edits (Check with {@link #canUndo()}
+		 *             first)
+		 *
+		 */
+		public synchronized Edit<?> getLastEdit() throws IllegalStateException {
+			if (edits.isEmpty())
+				throw new IllegalStateException("No more edits");
+			int lastEdit = edits.size() - 1;
+			return edits.get(lastEdit);
+		}
+
+		/**
+		 * Get the last edit that can be redone. This edit was the last one to
+		 * be added with {@link #addUndo(Edit)}.
+		 *
+		 * @return The last undone {@link Edit}
+		 * @throws IllegalStateException
+		 *             If there are no more edits (Check with {@link #canRedo()}
+		 *             first)
+		 *
+		 */
+		public synchronized Edit<?> getLastUndo() throws IllegalStateException {
+			if (undoes.isEmpty())
+				throw new IllegalStateException("No more undoes");
+			int lastUndo = undoes.size() - 1;
+			return undoes.get(lastUndo);
+		}
+
+		/**
+		 * Add an edit or redo. Common functionallity called by
+		 * {@link #addEdit(Edit)} and {@link #addRedo(Edit)}.
+		 *
+		 * @see #addEdit(Edit)
+		 * @see #addRedo(Edit)
+		 * @param edit
+		 *            The {@link Edit} to add
+		 * @param isRedo
+		 *            True if this is a redo
+		 */
+		protected void addEditOrRedo(Edit<?> edit, boolean isRedo) {
+			edits.add(edit);
+			if (undoes.isEmpty())
+				return;
+			if (isRedo) {
+				// It's a redo, remove only the last one
+				int lastUndoIndex = undoes.size() - 1;
+				Edit<?> lastUndo = undoes.get(lastUndoIndex);
+				if (!edit.equals(lastUndo))
+					throw new IllegalArgumentException(
+							"Can only redo last undo");
+				undoes.remove(lastUndoIndex);
+			} else
+				// It's a new edit, remove all redos
+				undoes.clear();
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-edits-impl/src/main/java/net/sf/taverna/t2/workbench/edits/impl/menu/AbstractUndoAction.java
----------------------------------------------------------------------
diff --git a/taverna-edits-impl/src/main/java/net/sf/taverna/t2/workbench/edits/impl/menu/AbstractUndoAction.java b/taverna-edits-impl/src/main/java/net/sf/taverna/t2/workbench/edits/impl/menu/AbstractUndoAction.java
new file mode 100644
index 0000000..97d14a6
--- /dev/null
+++ b/taverna-edits-impl/src/main/java/net/sf/taverna/t2/workbench/edits/impl/menu/AbstractUndoAction.java
@@ -0,0 +1,166 @@
+/*******************************************************************************
+ * Copyright (C) 2012 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 net.sf.taverna.t2.workbench.edits.impl.menu;
+
+import static java.awt.Toolkit.getDefaultToolkit;
+import static java.awt.event.KeyEvent.VK_Y;
+import static java.awt.event.KeyEvent.VK_Z;
+import static javax.swing.KeyStroke.getKeyStroke;
+import static net.sf.taverna.t2.workbench.icons.WorkbenchIcons.redoIcon;
+import static net.sf.taverna.t2.workbench.icons.WorkbenchIcons.undoIcon;
+
+import java.awt.event.ActionEvent;
+
+import javax.swing.AbstractAction;
+
+import net.sf.taverna.t2.lang.observer.Observable;
+import net.sf.taverna.t2.lang.observer.Observer;
+import net.sf.taverna.t2.lang.observer.SwingAwareObserver;
+import net.sf.taverna.t2.workbench.edits.EditManager;
+import net.sf.taverna.t2.workbench.edits.EditManager.AbstractDataflowEditEvent;
+import net.sf.taverna.t2.workbench.edits.EditManager.EditManagerEvent;
+import net.sf.taverna.t2.workbench.selection.SelectionManager;
+import net.sf.taverna.t2.workbench.selection.events.PerspectiveSelectionEvent;
+import net.sf.taverna.t2.workbench.selection.events.SelectionManagerEvent;
+import net.sf.taverna.t2.workbench.selection.events.WorkflowBundleSelectionEvent;
+import uk.org.taverna.scufl2.api.container.WorkflowBundle;
+
+/**
+ * @author David Withers
+ */
+@SuppressWarnings("serial")
+public abstract class AbstractUndoAction extends AbstractAction {
+	protected EditManager editManager;
+	private SelectionManager selectionManager;
+
+	public AbstractUndoAction(String label, EditManager editManager) {
+		super(label);
+		this.editManager = editManager;
+		if (label.equals("Undo")) {
+			this.putValue(SMALL_ICON, undoIcon);
+			this.putValue(SHORT_DESCRIPTION, "Undo an action");
+			putValue(
+					ACCELERATOR_KEY,
+					getKeyStroke(VK_Z, getDefaultToolkit()
+							.getMenuShortcutKeyMask()));
+		} else if (label.equals("Redo")) {
+			this.putValue(SMALL_ICON, redoIcon);
+			this.putValue(SHORT_DESCRIPTION, "Redo an action");
+			putValue(
+					ACCELERATOR_KEY,
+					getKeyStroke(VK_Y, getDefaultToolkit()
+							.getMenuShortcutKeyMask()));
+		}
+		editManager.addObserver(new EditManagerObserver());
+		updateStatus();
+	}
+
+	@Override
+	public void actionPerformed(ActionEvent e) {
+		WorkflowBundle workflowBundle = getCurrentDataflow();
+		if (workflowBundle != null)
+			performUndoOrRedo(workflowBundle);
+	}
+
+	/**
+	 * Check if action should be enabled or disabled and update its status.
+	 */
+	public void updateStatus() {
+		WorkflowBundle workflowBundle = getCurrentDataflow();
+		if (workflowBundle == null)
+			setEnabled(false);
+		setEnabled(isActive(workflowBundle));
+	}
+
+	/**
+	 * Retrieve the current dataflow from the {@link ModelMap}, or
+	 * <code>null</code> if no workflow is active.
+	 * 
+	 * @return The current {@link Dataflow}
+	 */
+	protected WorkflowBundle getCurrentDataflow() {
+		if (selectionManager == null)
+			return null;
+		return selectionManager.getSelectedWorkflowBundle();
+	}
+
+	/**
+	 * Return <code>true</code> if the action should be enabled when the given
+	 * {@link Dataflow} is the current, ie. if it's undoable or redoable.
+	 * 
+	 * @param dataflow
+	 *            Current {@link Dataflow}
+	 * @return <code>true</code> if the action should be enabled.
+	 */
+	protected abstract boolean isActive(WorkflowBundle workflowBundle);
+
+	/**
+	 * Called by {@link #actionPerformed(ActionEvent)} when the current dataflow
+	 * is not <code>null</code>.
+	 * 
+	 * @param dataflow
+	 *            {@link Dataflow} on which to undo or redo
+	 */
+	protected abstract void performUndoOrRedo(WorkflowBundle workflowBundle);
+
+	public void setSelectionManager(SelectionManager selectionManager) {
+		this.selectionManager = selectionManager;
+		if (selectionManager != null)
+			selectionManager.addObserver(new SelectionManagerObserver());
+	}
+
+	/**
+	 * Update the status if there's been an edit done on the current workflow.
+	 * 
+	 */
+	protected class EditManagerObserver implements Observer<EditManagerEvent> {
+		@Override
+		public void notify(Observable<EditManagerEvent> sender,
+				EditManagerEvent message) throws Exception {
+			if (!(message instanceof AbstractDataflowEditEvent))
+				return;
+			AbstractDataflowEditEvent dataflowEdit = (AbstractDataflowEditEvent) message;
+			if (dataflowEdit.getDataFlow().equals(dataflowEdit.getDataFlow()))
+				// It's an edit that could effect our undoability
+				updateStatus();
+		}
+	}
+
+	private final class SelectionManagerObserver extends
+			SwingAwareObserver<SelectionManagerEvent> {
+		private static final String DESIGN_PERSPECTIVE_ID = "net.sf.taverna.t2.ui.perspectives.design.DesignPerspective";
+
+		@Override
+		public void notifySwing(Observable<SelectionManagerEvent> sender,
+				SelectionManagerEvent message) {
+			if (message instanceof WorkflowBundleSelectionEvent)
+				updateStatus();
+			else if (message instanceof PerspectiveSelectionEvent) {
+				PerspectiveSelectionEvent perspectiveSelectionEvent = (PerspectiveSelectionEvent) message;
+				if (DESIGN_PERSPECTIVE_ID.equals(perspectiveSelectionEvent
+						.getSelectedPerspective().getID()))
+					updateStatus();
+				else
+					setEnabled(false);
+			}
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-edits-impl/src/main/java/net/sf/taverna/t2/workbench/edits/impl/menu/RedoMenuAction.java
----------------------------------------------------------------------
diff --git a/taverna-edits-impl/src/main/java/net/sf/taverna/t2/workbench/edits/impl/menu/RedoMenuAction.java b/taverna-edits-impl/src/main/java/net/sf/taverna/t2/workbench/edits/impl/menu/RedoMenuAction.java
new file mode 100644
index 0000000..2abc139
--- /dev/null
+++ b/taverna-edits-impl/src/main/java/net/sf/taverna/t2/workbench/edits/impl/menu/RedoMenuAction.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * 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 net.sf.taverna.t2.workbench.edits.impl.menu;
+
+import static javax.swing.JOptionPane.ERROR_MESSAGE;
+import static javax.swing.JOptionPane.showMessageDialog;
+import static net.sf.taverna.t2.workbench.edits.impl.menu.UndoMenuSection.UNDO_SECTION_URI;
+
+import javax.swing.Action;
+
+import net.sf.taverna.t2.ui.menu.AbstractMenuAction;
+import net.sf.taverna.t2.workbench.edits.Edit;
+import net.sf.taverna.t2.workbench.edits.EditException;
+import net.sf.taverna.t2.workbench.edits.EditManager;
+import net.sf.taverna.t2.workbench.selection.SelectionManager;
+
+import org.apache.log4j.Logger;
+
+import uk.org.taverna.scufl2.api.container.WorkflowBundle;
+
+/**
+ * Redo the previous {@link Edit} done on the current workflow using the
+ * {@link EditManager}.
+ *
+ * @author Stian Soiland-Reyes
+ */
+public class RedoMenuAction extends AbstractMenuAction {
+	private static Logger logger = Logger.getLogger(RedoMenuAction.class);
+	private final EditManager editManager;
+	private SelectionManager selectionManager;
+	private AbstractUndoAction undoAction;
+
+	public RedoMenuAction(EditManager editManager) {
+		super(UNDO_SECTION_URI, 20);
+		this.editManager = editManager;
+	}
+
+	@SuppressWarnings("serial")
+	@Override
+	protected Action createAction() {
+		undoAction = new AbstractUndoAction("Redo", editManager) {
+			@Override
+			protected boolean isActive(WorkflowBundle workflowBundle) {
+				return editManager.canRedoDataflowEdit(workflowBundle);
+			}
+
+			@Override
+			protected void performUndoOrRedo(WorkflowBundle workflowBundle) {
+				try {
+					editManager.redoDataflowEdit(workflowBundle);
+				} catch (EditException | RuntimeException e) {
+					logger.warn("Could not redo for " + workflowBundle, e);
+					showMessageDialog(null, "Could not redo for workflow "
+							+ workflowBundle + ":\n" + e, "Could not redo",
+							ERROR_MESSAGE);
+				}
+			}
+		};
+		undoAction.setSelectionManager(selectionManager);
+		return undoAction;
+	}
+
+	public void setSelectionManager(SelectionManager selectionManager) {
+		this.selectionManager = selectionManager;
+		if (undoAction != null)
+			undoAction.setSelectionManager(selectionManager);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-edits-impl/src/main/java/net/sf/taverna/t2/workbench/edits/impl/menu/UndoMenuAction.java
----------------------------------------------------------------------
diff --git a/taverna-edits-impl/src/main/java/net/sf/taverna/t2/workbench/edits/impl/menu/UndoMenuAction.java b/taverna-edits-impl/src/main/java/net/sf/taverna/t2/workbench/edits/impl/menu/UndoMenuAction.java
new file mode 100644
index 0000000..e1242b3
--- /dev/null
+++ b/taverna-edits-impl/src/main/java/net/sf/taverna/t2/workbench/edits/impl/menu/UndoMenuAction.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * 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 net.sf.taverna.t2.workbench.edits.impl.menu;
+
+import static javax.swing.JOptionPane.ERROR_MESSAGE;
+import static javax.swing.JOptionPane.showMessageDialog;
+import static net.sf.taverna.t2.workbench.edits.impl.menu.UndoMenuSection.UNDO_SECTION_URI;
+
+import javax.swing.Action;
+
+import net.sf.taverna.t2.ui.menu.AbstractMenuAction;
+import net.sf.taverna.t2.workbench.edits.Edit;
+import net.sf.taverna.t2.workbench.edits.EditManager;
+import net.sf.taverna.t2.workbench.selection.SelectionManager;
+
+import org.apache.log4j.Logger;
+
+import uk.org.taverna.scufl2.api.container.WorkflowBundle;
+
+/**
+ * Undo the last {@link Edit} done on the current workflow using the
+ * {@link EditManager}.
+ * 
+ * @author Stian Soiland-Reyes
+ * 
+ */
+public class UndoMenuAction extends AbstractMenuAction {
+	private static Logger logger = Logger.getLogger(UndoMenuAction.class);
+	private final EditManager editManager;
+	private SelectionManager selectionManager;
+	private AbstractUndoAction undoAction;
+
+	public UndoMenuAction(EditManager editManager) {
+		super(UNDO_SECTION_URI, 10);
+		this.editManager = editManager;
+	}
+
+	@SuppressWarnings("serial")
+	@Override
+	protected Action createAction() {
+		undoAction = new AbstractUndoAction("Undo", editManager) {
+			@Override
+			protected boolean isActive(WorkflowBundle workflowBundle) {
+				return editManager.canUndoDataflowEdit(workflowBundle);
+			}
+
+			@Override
+			protected void performUndoOrRedo(WorkflowBundle workflowBundle) {
+				try {
+					editManager.undoDataflowEdit(workflowBundle);
+				} catch (RuntimeException e) {
+					logger.warn("Could not undo for " + workflowBundle, e);
+					showMessageDialog(null, "Could not undo for workflow "
+							+ workflowBundle + ":\n" + e, "Could not undo",
+							ERROR_MESSAGE);
+				}
+			}
+		};
+		undoAction.setSelectionManager(selectionManager);
+		return undoAction;
+	}
+
+	public void setSelectionManager(SelectionManager selectionManager) {
+		this.selectionManager = selectionManager;
+		if (undoAction != null)
+			undoAction.setSelectionManager(selectionManager);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-edits-impl/src/main/java/net/sf/taverna/t2/workbench/edits/impl/menu/UndoMenuSection.java
----------------------------------------------------------------------
diff --git a/taverna-edits-impl/src/main/java/net/sf/taverna/t2/workbench/edits/impl/menu/UndoMenuSection.java b/taverna-edits-impl/src/main/java/net/sf/taverna/t2/workbench/edits/impl/menu/UndoMenuSection.java
new file mode 100644
index 0000000..b83a650
--- /dev/null
+++ b/taverna-edits-impl/src/main/java/net/sf/taverna/t2/workbench/edits/impl/menu/UndoMenuSection.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * 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 net.sf.taverna.t2.workbench.edits.impl.menu;
+
+import java.net.URI;
+
+import net.sf.taverna.t2.ui.menu.AbstractMenuSection;
+
+/**
+ * A section of the Edit menu that contains {@link UndoMenuSection undo} and
+ * {@link RedoMenuAction redo}.
+ * 
+ * @author Stian Soiland-Reyes
+ */
+public class UndoMenuSection extends AbstractMenuSection {
+	public static final URI UNDO_SECTION_URI = URI
+			.create("http://taverna.sf.net/2008/t2workbench/edits#undoSection");
+	public static final URI EDIT_MENU_URI = URI
+			.create("http://taverna.sf.net/2008/t2workbench/menu#edit");
+
+	public UndoMenuSection() {
+		super(EDIT_MENU_URI, 10, UNDO_SECTION_URI);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-edits-impl/src/main/java/net/sf/taverna/t2/workbench/edits/impl/toolbar/EditToolbarSection.java
----------------------------------------------------------------------
diff --git a/taverna-edits-impl/src/main/java/net/sf/taverna/t2/workbench/edits/impl/toolbar/EditToolbarSection.java b/taverna-edits-impl/src/main/java/net/sf/taverna/t2/workbench/edits/impl/toolbar/EditToolbarSection.java
new file mode 100644
index 0000000..9eea85a
--- /dev/null
+++ b/taverna-edits-impl/src/main/java/net/sf/taverna/t2/workbench/edits/impl/toolbar/EditToolbarSection.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * 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 net.sf.taverna.t2.workbench.edits.impl.toolbar;
+
+import static net.sf.taverna.t2.ui.menu.DefaultToolBar.DEFAULT_TOOL_BAR;
+
+import java.net.URI;
+
+import net.sf.taverna.t2.ui.menu.AbstractMenuSection;
+
+public class EditToolbarSection extends AbstractMenuSection {
+	public static final URI EDIT_TOOLBAR_SECTION = URI
+			.create("http://taverna.sf.net/2008/t2workbench/menu#editToolbarSection");
+
+	public EditToolbarSection() {
+		super(DEFAULT_TOOL_BAR, 60, EDIT_TOOLBAR_SECTION);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-edits-impl/src/main/java/net/sf/taverna/t2/workbench/edits/impl/toolbar/RedoToolbarAction.java
----------------------------------------------------------------------
diff --git a/taverna-edits-impl/src/main/java/net/sf/taverna/t2/workbench/edits/impl/toolbar/RedoToolbarAction.java b/taverna-edits-impl/src/main/java/net/sf/taverna/t2/workbench/edits/impl/toolbar/RedoToolbarAction.java
new file mode 100644
index 0000000..09c0058
--- /dev/null
+++ b/taverna-edits-impl/src/main/java/net/sf/taverna/t2/workbench/edits/impl/toolbar/RedoToolbarAction.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * 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 net.sf.taverna.t2.workbench.edits.impl.toolbar;
+
+import static net.sf.taverna.t2.workbench.edits.impl.toolbar.EditToolbarSection.EDIT_TOOLBAR_SECTION;
+
+import java.net.URI;
+
+import javax.swing.Action;
+
+import net.sf.taverna.t2.ui.menu.AbstractMenuAction;
+import net.sf.taverna.t2.workbench.edits.impl.menu.RedoMenuAction;
+
+public class RedoToolbarAction extends AbstractMenuAction {
+	private static final URI EDIT_TOOLBAR_REDO_URI = URI
+			.create("http://taverna.sf.net/2008/t2workbench/menu#editToolbarRedo");
+	private final RedoMenuAction redoMenuAction;
+
+	public RedoToolbarAction(RedoMenuAction redoMenuAction) {
+		super(EDIT_TOOLBAR_SECTION, 20, EDIT_TOOLBAR_REDO_URI);
+		this.redoMenuAction = redoMenuAction;
+	}
+
+	@Override
+	protected Action createAction() {
+		return redoMenuAction.getAction();
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-edits-impl/src/main/java/net/sf/taverna/t2/workbench/edits/impl/toolbar/UndoToolbarAction.java
----------------------------------------------------------------------
diff --git a/taverna-edits-impl/src/main/java/net/sf/taverna/t2/workbench/edits/impl/toolbar/UndoToolbarAction.java b/taverna-edits-impl/src/main/java/net/sf/taverna/t2/workbench/edits/impl/toolbar/UndoToolbarAction.java
new file mode 100644
index 0000000..8e31ed3
--- /dev/null
+++ b/taverna-edits-impl/src/main/java/net/sf/taverna/t2/workbench/edits/impl/toolbar/UndoToolbarAction.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * 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 net.sf.taverna.t2.workbench.edits.impl.toolbar;
+
+import static net.sf.taverna.t2.workbench.edits.impl.toolbar.EditToolbarSection.EDIT_TOOLBAR_SECTION;
+
+import java.net.URI;
+
+import javax.swing.Action;
+
+import net.sf.taverna.t2.ui.menu.AbstractMenuAction;
+import net.sf.taverna.t2.workbench.edits.impl.menu.UndoMenuAction;
+
+public class UndoToolbarAction extends AbstractMenuAction {
+	private static final URI EDIT_TOOLBAR_UNDO_URI = URI
+			.create("http://taverna.sf.net/2008/t2workbench/menu#editToolbarUndo");
+	private final UndoMenuAction undoMenuAction;
+
+	public UndoToolbarAction(UndoMenuAction undoMenuAction) {
+		super(EDIT_TOOLBAR_SECTION, 10, EDIT_TOOLBAR_UNDO_URI);
+		this.undoMenuAction = undoMenuAction;
+	}
+
+	@Override
+	protected Action createAction() {
+		return undoMenuAction.getAction();
+	}
+}