http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/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
deleted file mode 100644
index 35f3498..0000000
--- 
a/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RemoveWorkflowOutputPortEdit.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*******************************************************************************
- * 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 org.apache.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 org.apache.taverna.scufl2.api.activity.Activity;
-import org.apache.taverna.scufl2.api.configurations.Configuration;
-import org.apache.taverna.scufl2.api.container.WorkflowBundle;
-import org.apache.taverna.scufl2.api.core.Workflow;
-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.ProcessorOutputPortBinding;
-import org.apache.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/a9a52bd5/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
deleted file mode 100644
index 2d54f1c..0000000
--- 
a/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/RenameEdit.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*******************************************************************************
- * 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 org.apache.taverna.scufl2.api.common.Scufl2Tools.NESTED_WORKFLOW;
-import org.apache.taverna.scufl2.api.activity.Activity;
-import org.apache.taverna.scufl2.api.common.Named;
-import org.apache.taverna.scufl2.api.configurations.Configuration;
-import org.apache.taverna.scufl2.api.container.WorkflowBundle;
-import org.apache.taverna.scufl2.api.core.Workflow;
-import org.apache.taverna.scufl2.api.port.ActivityPort;
-import org.apache.taverna.scufl2.api.port.InputPort;
-import org.apache.taverna.scufl2.api.port.ProcessorPort;
-import org.apache.taverna.scufl2.api.port.WorkflowPort;
-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.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/a9a52bd5/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
deleted file mode 100644
index dafcf9d..0000000
--- 
a/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/ReorderMergePositionsEdit.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*******************************************************************************
- * 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 org.apache.taverna.scufl2.api.core.DataLink;
-import org.apache.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/a9a52bd5/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
deleted file mode 100644
index d2ed4ff..0000000
--- 
a/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/SetIterationStrategyStackEdit.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*******************************************************************************
- * 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 org.apache.taverna.scufl2.api.core.Processor;
-import org.apache.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/a9a52bd5/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
deleted file mode 100644
index 4936b98..0000000
--- 
a/taverna-edits-api/src/main/java/net/sf/taverna/t2/workflow/edits/UpdateDataflowInternalIdentifierEdit.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*******************************************************************************
- * 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 org.apache.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/a9a52bd5/taverna-edits-api/src/main/java/org/apache/taverna/workbench/edits/CompoundEdit.java
----------------------------------------------------------------------
diff --git 
a/taverna-edits-api/src/main/java/org/apache/taverna/workbench/edits/CompoundEdit.java
 
b/taverna-edits-api/src/main/java/org/apache/taverna/workbench/edits/CompoundEdit.java
new file mode 100644
index 0000000..514042b
--- /dev/null
+++ 
b/taverna-edits-api/src/main/java/org/apache/taverna/workbench/edits/CompoundEdit.java
@@ -0,0 +1,117 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workbench.edits;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.taverna.scufl2.api.common.WorkflowBean;
+
+/**
+ * Implementation of Edit which contains an ordered list of child edits. Child
+ * edits are applied collectively and in order, any failure in any child edit
+ * causes an undo of previously applied children and a propogation of the edit
+ * exception.
+ * 
+ * @author Tom Oinn
+ */
+public class CompoundEdit implements Edit<WorkflowBean> {
+       private final transient List<Edit<?>> childEdits;
+       private transient boolean applied = false;
+
+       /**
+        * Create a new compound edit with no existing Edit objects.
+        * 
+        */
+       public CompoundEdit() {
+               this.childEdits = new ArrayList<>();
+       }
+
+       /**
+        * Create a new compound edit with the specified edits as children.
+        */
+       public CompoundEdit(List<Edit<?>> edits) {
+               this.childEdits = edits;
+       }
+
+       /**
+        * Get the list of edits.
+        * @return a live-editable list.
+        */
+       public List<Edit<?>> getChildEdits() {
+               return childEdits;
+       }
+
+       /**
+        * Attempts to call the doEdit method of all child edits. If any of 
those
+        * children throws an EditException any successful edits are rolled 
back and
+        * the exception is rethrown as the cause of a new EditException from 
the
+        * CompoundEdit
+        */
+       @Override
+       public synchronized WorkflowBean doEdit() throws EditException {
+               if (isApplied())
+                       throw new EditException("Cannot apply an edit more than 
once!");
+               List<Edit<?>> doneEdits = new ArrayList<>();
+               try {
+                       for (Edit<?> edit : childEdits) {
+                               edit.doEdit();
+                               /*
+                                * Insert the done edit at position 0 in the 
list so we can
+                                * iterate over the list in the normal order if 
we need to
+                                * rollback, this ensures that the most recent 
edit is first.
+                                */
+                               doneEdits.add(0, edit);
+                       }
+                       applied = true;
+               } catch (EditException ee) {
+                       for (Edit<?> undoMe : doneEdits)
+                               undoMe.undo();
+                       applied = false;
+                       throw new EditException("Failed child of compound 
edit", ee);
+               }
+               return null;
+       }
+
+       /**
+        * There is no explicit subject for a compound edit, so this method 
always
+        * returns null.
+        */
+       @Override
+       public Object getSubject() {
+               return null;
+       }
+
+       /**
+        * Rolls back all child edits in reverse order
+        */
+       @Override
+       public synchronized void undo() {
+               for (int i = childEdits.size() - 1; i >= 0; i--)
+                       // Undo child edits in reverse order
+                       childEdits.get(i).undo();
+               applied = false;
+       }
+
+       @Override
+       public boolean isApplied() {
+               return applied;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-edits-api/src/main/java/org/apache/taverna/workbench/edits/Edit.java
----------------------------------------------------------------------
diff --git 
a/taverna-edits-api/src/main/java/org/apache/taverna/workbench/edits/Edit.java 
b/taverna-edits-api/src/main/java/org/apache/taverna/workbench/edits/Edit.java
new file mode 100644
index 0000000..63e9c77
--- /dev/null
+++ 
b/taverna-edits-api/src/main/java/org/apache/taverna/workbench/edits/Edit.java
@@ -0,0 +1,65 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workbench.edits;
+
+import org.apache.taverna.scufl2.api.common.WorkflowBean;
+
+/**
+ * The workflow object model exposed by this API is read only. Properties of 
the
+ * model can only be changed through implementations of this interface, this
+ * ensures a consistant approach to grouped edits (transactions) and undo / 
redo
+ * support within the UI. It also potentially allows for capture of editing
+ * provenance where a workflow is repurposed or created from an aggregate of
+ * several others.
+ * 
+ * @author Tom Oinn
+ */
+public interface Edit<TargetType extends WorkflowBean> {
+       /**
+        * Perform the edit
+        * 
+        * @throws EditException
+        *             if the edit fails. If an edit throws EditException it 
should
+        *             try to ensure the subject is unaltered. Where this is
+        *             impossible consider breaking edits down into a compound 
edit.
+        */
+       TargetType doEdit() throws EditException;
+
+       /**
+        * Undo the edit, reverting the subject to the state it was in prior to 
the
+        * edit
+        */
+       void undo();
+
+       /**
+        * Return the object to which this edit applies
+        * 
+        * @return
+        */
+       Object getSubject();
+
+       /**
+        * Has the edit been applied yet?
+        * 
+        * @return true if and only if the edit has been successfully applied 
to the
+        *         subject
+        */
+       boolean isApplied();
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-edits-api/src/main/java/org/apache/taverna/workbench/edits/EditException.java
----------------------------------------------------------------------
diff --git 
a/taverna-edits-api/src/main/java/org/apache/taverna/workbench/edits/EditException.java
 
b/taverna-edits-api/src/main/java/org/apache/taverna/workbench/edits/EditException.java
new file mode 100644
index 0000000..bd249d5
--- /dev/null
+++ 
b/taverna-edits-api/src/main/java/org/apache/taverna/workbench/edits/EditException.java
@@ -0,0 +1,41 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workbench.edits;
+
+/**
+ * Superclass of all exceptions thrown when altering the workflow model through
+ * the edit manager.
+ * 
+ * @author Tom Oinn
+ */
+@SuppressWarnings("serial")
+public class EditException extends Exception {
+       public EditException(String string) {
+               super(string);
+       }
+
+       public EditException(String string, Throwable cause) {
+               super(string, cause);
+       }
+
+       public EditException(Throwable t) {
+               super(t);
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-edits-api/src/main/java/org/apache/taverna/workbench/edits/EditManager.java
----------------------------------------------------------------------
diff --git 
a/taverna-edits-api/src/main/java/org/apache/taverna/workbench/edits/EditManager.java
 
b/taverna-edits-api/src/main/java/org/apache/taverna/workbench/edits/EditManager.java
new file mode 100644
index 0000000..ca90a4b
--- /dev/null
+++ 
b/taverna-edits-api/src/main/java/org/apache/taverna/workbench/edits/EditManager.java
@@ -0,0 +1,221 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workbench.edits;
+
+import org.apache.taverna.scufl2.api.container.WorkflowBundle;
+import org.apache.taverna.lang.observer.Observable;
+import org.apache.taverna.lang.observer.Observer;
+import org.apache.taverna.workbench.edits.EditManager.EditManagerEvent;
+
+/**
+ * Manager that can handle {@link Edit edits} for a {@link WorkflowBundle}.
+ * <p>
+ * Edits to a workflow that are to be undoable or redoable should be created by
+ * using {@link EditManager#getEdits()} to get an {@link Edits} object. Using
+ * this to create {@link Edit}s, instead of calling {@link Edit#doEdit()}, use
+ * {@link EditManager#doDataflowEdit(WorkflowBundle, Edit)} to associate the
+ * edit with the specified Dataflow.
+ * <p>
+ * It is possible to undo a series of edits done on a particular dataflow in
+ * this way by using {@link #undoDataflowEdit(WorkflowBundle)}. If one or more
+ * undoes have been performed, they can be redone step by step using
+ * {@link #redoDataflowEdit(WorkflowBundle)}. Note that it is no longer 
possible
+ * to call {@link #redoDataflowEdit(WorkflowBundle)} after a
+ * {@link #doDataflowEdit(WorkflowBundle, Edit)}.
+ * <p>
+ * The EditManager is {@link Observable}. If you
+ * {@linkplain Observable#addObserver(net.sf.taverna.t2.lang.observer.Observer)
+ * add an observer} you can be notified on {@linkplain DataflowEditEvent 
edits},
+ * {@linkplain DataFlowUndoEvent undoes} and {@linkplain DataFlowRedoEvent
+ * redoes}.
+ * 
+ * @author Stian Soiland-Reyes
+ */
+public interface EditManager extends Observable<EditManagerEvent> {
+       /**
+        * <code>true</code> if {@link #redoDataflowEdit(WorkflowBundle)} on the
+        * given dataflow would redo the last undone edit. If there are no 
previous
+        * edits, return <code>false</code>.
+        * 
+        * @param dataflow
+        *            {@link WorkflowBundle} which last affecting edit is to be
+        *            undone
+        * @return <code>true</code if and only if
+        *         {@link #redoDataflowEdit(WorkflowBundle)} would undo
+        */
+       boolean canRedoDataflowEdit(WorkflowBundle dataflow);
+
+       /**
+        * <code>true</code> if {@link #undoDataflowEdit(WorkflowBundle)} on the
+        * given dataflow would undo the last edit. If there are no previous 
edits,
+        * return <code>false</code>.
+        * 
+        * @param dataflow
+        *            {@link WorkflowBundle} which last affecting edit is to be
+        *            undone
+        * @return <code>true</code if {@link #undoDataflowEdit(WorkflowBundle)}
+        *         would undo
+        */
+       boolean canUndoDataflowEdit(WorkflowBundle dataflow);
+
+       /**
+        * Do an {@link Edit} affecting the given {@link WorkflowBundle}.
+        * <p>
+        * The edit is {@link Edit#doEdit() performed} and the edit can later be
+        * undone using {@link EditManager#undoDataflowEdit(WorkflowBundle)}.
+        * <p>
+        * Note that any events previously undone with
+        * {@link EditManager#undoDataflowEdit(WorkflowBundle)} for the given
+        * dataflow can no longer be
+        * {@link EditManager#redoDataflowEdit(WorkflowBundle) redone} after 
calling
+        * this method.
+        * 
+        * @see EditManager#undoDataflowEdit(WorkflowBundle)
+        * @param dataflow
+        *            {@link WorkflowBundle} this edit is affecting
+        * @param edit
+        *            {@link Edit} that should be done using {@link 
Edit#doEdit()}.
+        * @throws EditException
+        *             If {@link Edit#doEdit()} fails
+        */
+       void doDataflowEdit(WorkflowBundle dataflow, Edit<?> edit)
+                       throws EditException;
+
+       /**
+        * Redo the last {@link Edit} that was undone using
+        * {@link #undoDataflowEdit(WorkflowBundle)}.
+        * <p>
+        * Note that the {@link EditManager} might only be able to redo a 
reasonable
+        * number of steps.
+        * <p>
+        * It is not possible to use {@link #redoDataflowEdit(WorkflowBundle)} 
after
+        * a {@link #doDataflowEdit(WorkflowBundle, Edit)} affecting the same
+        * {@link WorkflowBundle}, or if no edits have been undone yet. No 
action
+        * would be taken in these cases.
+        * 
+        * @param dataflow
+        *            {@link WorkflowBundle} which last affecting edit is to be
+        *            redone
+        * @throws EditException
+        *             If {@link Edit#doEdit()} fails
+        */
+       void redoDataflowEdit(WorkflowBundle dataflow) throws EditException;
+
+       /**
+        * Undo the last {@link Edit} affecting the given {@link 
WorkflowBundle}.
+        * <p>
+        * This can be called in succession until there are no more known 
undoes.
+        * Note that the {@link EditManager} might only be able to undo a 
reasonable
+        * number of steps.
+        * <p>
+        * The last edit must have been performed using
+        * {@link EditManager#doDataflowEdit(WorkflowBundle, Edit)} or
+        * {@link EditManager#redoDataflowEdit(WorkflowBundle)}. The undo is 
done
+        * using {@link Edit#undo()}. If no edits have been performed for the
+        * dataflow yet, no action is taken.
+        * <p>
+        * Undoes can be redone using {@link #redoDataflowEdit(WorkflowBundle)}.
+        * 
+        * @param dataflow
+        *            {@link WorkflowBundle} which last affecting edit is to be
+        *            undone
+        */
+       void undoDataflowEdit(WorkflowBundle dataflow);
+
+       /**
+        * An event about an {@link Edit} on a {@link WorkflowBundle}, 
accessible
+        * through {@link AbstractDataflowEditEvent#getEdit()} and
+        * {@link AbstractDataflowEditEvent#getDataFlow()}.
+        */
+       public static abstract class AbstractDataflowEditEvent implements
+                       EditManagerEvent {
+               private final WorkflowBundle dataFlow;
+               private final Edit<?> edit;
+
+               public AbstractDataflowEditEvent(WorkflowBundle dataFlow, 
Edit<?> edit) {
+                       if (dataFlow == null || edit == null)
+                               throw new NullPointerException(
+                                               "Dataflow and/or Edit can't be 
null");
+                       this.dataFlow = dataFlow;
+                       this.edit = edit;
+               }
+
+               /**
+                * The {@link WorkflowBundle} this event affected.
+                * 
+                * @return A {@link WorkflowBundle}
+                */
+               public WorkflowBundle getDataFlow() {
+                       return dataFlow;
+               }
+
+               /**
+                * The {@link Edit} that was performed, undoed or redone on the
+                * {@link #getDataFlow() dataflow}.
+                * 
+                * @return An {@link Edit}
+                */
+               @Override
+               public Edit<?> getEdit() {
+                       return edit;
+               }
+       }
+
+       /**
+        * An event sent when an {@link Edit} has been performed on a
+        * {@link WorkflowBundle}.
+        * 
+        */
+       public static class DataflowEditEvent extends AbstractDataflowEditEvent 
{
+               public DataflowEditEvent(WorkflowBundle dataFlow, Edit<?> edit) 
{
+                       super(dataFlow, edit);
+               }
+       }
+
+       /**
+        * An event sent when a previously undone {@link Edit} has been redone 
on a
+        * {@link WorkflowBundle}.
+        * 
+        */
+       public static class DataFlowRedoEvent extends AbstractDataflowEditEvent 
{
+               public DataFlowRedoEvent(WorkflowBundle dataFlow, Edit<?> edit) 
{
+                       super(dataFlow, edit);
+               }
+       }
+
+       /**
+        * An event sent when an {@link Edit} has been undone on a
+        * {@link WorkflowBundle}.
+        * 
+        */
+       public static class DataFlowUndoEvent extends AbstractDataflowEditEvent 
{
+               public DataFlowUndoEvent(WorkflowBundle dataFlow, Edit<?> edit) 
{
+                       super(dataFlow, edit);
+               }
+       }
+
+       /**
+        * An event given to {@link Observer}s registered with
+        * {@link Observable#addObserver(Observer)}.
+        */
+       public interface EditManagerEvent {
+               public Edit<?> getEdit();
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-edits-api/src/main/java/org/apache/taverna/workbench/edits/package-info.java
----------------------------------------------------------------------
diff --git 
a/taverna-edits-api/src/main/java/org/apache/taverna/workbench/edits/package-info.java
 
b/taverna-edits-api/src/main/java/org/apache/taverna/workbench/edits/package-info.java
new file mode 100644
index 0000000..49e0e32
--- /dev/null
+++ 
b/taverna-edits-api/src/main/java/org/apache/taverna/workbench/edits/package-info.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
+ 
******************************************************************************/
+/**
+ * A {@link net.sf.taverna.t2.workbench.edits.EditManager} that can manage
+ * {@link net.sf.taverna.t2.workflowmodel.Edit}s performed from the UI.
+ * <p>
+ * To perform an edit that is to be undoable, use
+ * {@link EditManager#doDataflowEdit(net.sf.taverna.t2.workflowmodel.Dataflow, 
net.sf.taverna.t2.workflowmodel.Edit)}
+ * instead of {@link net.sf.taverna.t2.workflowmodel.Edit#doEdit()}. Such edits
+ * can be
+ * {@link 
EditManager#undoDataflowEdit(net.sf.taverna.t2.workflowmodel.Dataflow) undone}
+ * and
+ * {@link 
EditManager#redoDataflowEdit(net.sf.taverna.t2.workflowmodel.Dataflow) redone}.
+ * </p>
+ * <p>
+ * Edits are organised by {@link net.sf.taverna.t2.workflowmodel.Dataflow} so
+ * that if a user changes the active workflow in the Workbench and does "Undo" 
-
+ * that would undo the last undo done related to that workflow.
+ * </p>
+ * <p>
+ * The {@link net.sf.taverna.t2.workbench.edits.impl} implementation of the
+ * EditManager is discovered by {@link 
net.sf.taverna.t2.workbench.edits.EditManager#getInstance()}. The
+ * implementation also includes {@link 
net.sf.taverna.t2.ui.menu.MenuComponent}s
+ * for Undo and Redo.
+ * </p>
+ * 
+ * @author Stian Soiland-Reyes
+ * 
+ */
+package org.apache.taverna.workbench.edits;

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AbstractEdit.java
----------------------------------------------------------------------
diff --git 
a/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AbstractEdit.java
 
b/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AbstractEdit.java
new file mode 100644
index 0000000..afb3b54
--- /dev/null
+++ 
b/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AbstractEdit.java
@@ -0,0 +1,118 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflow.edits;
+
+import org.apache.taverna.workbench.edits.Edit;
+import org.apache.taverna.workbench.edits.EditException;
+import org.apache.taverna.scufl2.api.common.Scufl2Tools;
+import org.apache.taverna.scufl2.api.common.WorkflowBean;
+
+/**
+ * An abstract {@link Edit} implementation that checks if an edit has been
+ * applied or not.
+ *
+ * @author Stian Soiland-Reyes
+ *
+ * @param <Subject>
+ *            Subject of this edit
+ */
+public abstract class AbstractEdit<Subject extends WorkflowBean> implements
+               Edit<Subject> {
+       private boolean applied = false;
+       private final Subject subject;
+       protected final Scufl2Tools scufl2Tools = new Scufl2Tools();
+
+       /**
+        * Construct an AbstractEdit.
+        *
+        * @param subjectType
+        *            The expected implementation type of the subject. The edit 
will
+        *            not go through unless the subject is an instance of this 
type.
+        *            If the edit don't care about the implementation type, 
provide
+        *            the official SubjectInterface instead.
+        * @param subject
+        *            The subject of this edit
+        */
+       public AbstractEdit(Subject subject) {
+               if (subject == null && !isNullSubjectAllowed())
+                       throw new IllegalArgumentException(
+                                       "Cannot construct an edit with null 
subject");
+               this.subject = subject;
+       }
+
+       protected boolean isNullSubjectAllowed() {
+               return false;
+       }
+
+       @Override
+       public final Subject doEdit() throws EditException {
+               if (applied)
+                       throw new EditException("Edit has already been 
applied!");
+               try {
+                       synchronized (subject) {
+                               doEditAction(subject);
+                               applied = true;
+                               return this.subject;
+                       }
+               } catch (EditException ee) {
+                       applied = false;
+                       throw ee;
+               }
+       }
+
+       /**
+        * Do the actual edit here
+        *
+        * @param subject
+        *            The instance to which the edit applies
+        * @throws EditException
+        */
+       protected abstract void doEditAction(Subject subject)
+                       throws EditException;
+
+       /**
+        * Undo any edit effects here
+        *
+        * @param subject
+        *            The instance to which the edit applies
+        */
+       protected abstract void undoEditAction(Subject subject);
+
+       @Override
+       public final Subject getSubject() {
+               return subject;
+       }
+
+       @Override
+       public final boolean isApplied() {
+               return applied;
+       }
+
+       @Override
+       public final void undo() {
+               if (!applied)
+                       throw new RuntimeException(
+                                       "Attempt to undo edit that was never 
applied");
+               synchronized (subject) {
+                       undoEditAction(subject);
+                       applied = false;
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddActivityEdit.java
----------------------------------------------------------------------
diff --git 
a/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddActivityEdit.java
 
b/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddActivityEdit.java
new file mode 100644
index 0000000..69b30f9
--- /dev/null
+++ 
b/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddActivityEdit.java
@@ -0,0 +1,54 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflow.edits;
+
+import org.apache.taverna.scufl2.api.activity.Activity;
+import org.apache.taverna.scufl2.api.core.Processor;
+import org.apache.taverna.scufl2.api.profiles.ProcessorBinding;
+
+/**
+ * Creates a ProcessorBinding binding for the Activity and Processor and adds 
the binding to the
+ * Profile containing the Activity.
+ *
+ * @author David Withers
+ */
+public class AddActivityEdit extends AbstractEdit<Processor> {
+       private Activity activity;
+       private ProcessorBinding addedProcessorBinding;
+
+       public AddActivityEdit(Processor processor, Activity activity) {
+               super(processor);
+               this.activity = activity;
+       }
+
+       @Override
+       protected void doEditAction(Processor processor) {
+               ProcessorBinding binding = new ProcessorBinding();
+               binding.setBoundProcessor(processor);
+               binding.setBoundActivity(activity);
+               binding.setParent(activity.getParent());
+               addedProcessorBinding = binding;
+       }
+
+       @Override
+       protected void undoEditAction(Processor processor) {
+               addedProcessorBinding.setParent(null);
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddActivityInputPortMappingEdit.java
----------------------------------------------------------------------
diff --git 
a/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddActivityInputPortMappingEdit.java
 
b/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddActivityInputPortMappingEdit.java
new file mode 100644
index 0000000..7125953
--- /dev/null
+++ 
b/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddActivityInputPortMappingEdit.java
@@ -0,0 +1,58 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflow.edits;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.taverna.scufl2.api.activity.Activity;
+import org.apache.taverna.scufl2.api.port.InputActivityPort;
+import org.apache.taverna.scufl2.api.port.InputProcessorPort;
+import org.apache.taverna.scufl2.api.profiles.ProcessorBinding;
+import org.apache.taverna.scufl2.api.profiles.ProcessorInputPortBinding;
+
+public class AddActivityInputPortMappingEdit extends AbstractEdit<Activity> {
+       private final InputProcessorPort inputProcessorPort;
+       private final InputActivityPort inputActivityPort;
+       private List<ProcessorInputPortBinding> portBindings;
+
+       public AddActivityInputPortMappingEdit(Activity activity,
+                       InputProcessorPort inputProcessorPort,
+                       InputActivityPort inputActivityPort) {
+               super(activity);
+               this.inputProcessorPort = inputProcessorPort;
+               this.inputActivityPort = inputActivityPort;
+       }
+
+       @Override
+       protected void doEditAction(Activity activity) {
+               portBindings = new ArrayList<>();
+               for (ProcessorBinding binding : scufl2Tools
+                               .processorBindingsToActivity(activity))
+                       portBindings.add(new ProcessorInputPortBinding(binding,
+                                       inputProcessorPort, inputActivityPort));
+       }
+
+       @Override
+       protected void undoEditAction(Activity activity) {
+               for (ProcessorInputPortBinding binding : portBindings)
+                       binding.setParent(null);
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddActivityOutputPortMappingEdit.java
----------------------------------------------------------------------
diff --git 
a/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddActivityOutputPortMappingEdit.java
 
b/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddActivityOutputPortMappingEdit.java
new file mode 100644
index 0000000..75880be
--- /dev/null
+++ 
b/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddActivityOutputPortMappingEdit.java
@@ -0,0 +1,58 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflow.edits;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.taverna.scufl2.api.activity.Activity;
+import org.apache.taverna.scufl2.api.port.OutputActivityPort;
+import org.apache.taverna.scufl2.api.port.OutputProcessorPort;
+import org.apache.taverna.scufl2.api.profiles.ProcessorBinding;
+import org.apache.taverna.scufl2.api.profiles.ProcessorOutputPortBinding;
+
+public class AddActivityOutputPortMappingEdit extends AbstractEdit<Activity> {
+       private final OutputProcessorPort outputProcessorPort;
+       private final OutputActivityPort outputActivityPort;
+       private List<ProcessorOutputPortBinding> portBindings;
+
+       public AddActivityOutputPortMappingEdit(Activity activity,
+                       OutputProcessorPort outputProcessorPort,
+                       OutputActivityPort outputActivityPort) {
+               super(activity);
+               this.outputProcessorPort = outputProcessorPort;
+               this.outputActivityPort = outputActivityPort;
+       }
+
+       @Override
+       protected void doEditAction(Activity activity) {
+               portBindings = new ArrayList<>();
+               for (ProcessorBinding binding : scufl2Tools
+                               .processorBindingsToActivity(activity))
+                       portBindings.add(new ProcessorOutputPortBinding(binding,
+                                       outputActivityPort, 
outputProcessorPort));
+       }
+
+       @Override
+       protected void undoEditAction(Activity activity) {
+               for (ProcessorOutputPortBinding binding : portBindings)
+                       binding.setParent(null);
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddChildEdit.java
----------------------------------------------------------------------
diff --git 
a/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddChildEdit.java
 
b/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddChildEdit.java
new file mode 100644
index 0000000..13d8c0b
--- /dev/null
+++ 
b/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddChildEdit.java
@@ -0,0 +1,51 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflow.edits;
+
+import org.apache.taverna.scufl2.api.common.Child;
+import org.apache.taverna.scufl2.api.common.WorkflowBean;
+
+/**
+ * Adds a child to a parent.
+ *
+ * @author David Withers
+ */
+public class AddChildEdit<T extends WorkflowBean> extends AbstractEdit<T> {
+       private Child<T> child;
+
+       public AddChildEdit(T parent, Child<T> child) {
+               super(parent);
+               this.child = child;
+       }
+
+       @Override
+       protected void doEditAction(T parent) {
+               child.setParent(parent);
+       }
+
+       @Override
+       protected void undoEditAction(T parent) {
+               child.setParent(null);
+       }
+
+       public Child<T> getChild() {
+               return child;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddDataLinkEdit.java
----------------------------------------------------------------------
diff --git 
a/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddDataLinkEdit.java
 
b/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddDataLinkEdit.java
new file mode 100644
index 0000000..9a8f848
--- /dev/null
+++ 
b/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddDataLinkEdit.java
@@ -0,0 +1,89 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflow.edits;
+
+import java.util.List;
+
+import org.apache.taverna.scufl2.api.core.DataLink;
+import org.apache.taverna.scufl2.api.core.Workflow;
+import org.apache.taverna.scufl2.api.iterationstrategy.CrossProduct;
+import org.apache.taverna.scufl2.api.iterationstrategy.DotProduct;
+import org.apache.taverna.scufl2.api.iterationstrategy.IterationStrategyParent;
+import 
org.apache.taverna.scufl2.api.iterationstrategy.IterationStrategyTopNode;
+import org.apache.taverna.scufl2.api.iterationstrategy.PortNode;
+import org.apache.taverna.scufl2.api.port.InputProcessorPort;
+import org.apache.taverna.scufl2.api.port.ReceiverPort;
+
+/**
+ * Adds a DataLink to a Workflow.
+ * <p>
+ * Handles setting the merge position of all dataLinks with the same receiver 
port.
+ * <p>
+ * Modifies the processor's iteration strategy or when the first DataLink is 
added.
+ *
+ * @author David Withers
+ */
+public class AddDataLinkEdit extends AbstractEdit<Workflow> {
+       private DataLink dataLink;
+       private PortNode portNode;
+
+       public AddDataLinkEdit(Workflow workflow, DataLink dataLink) {
+               super(workflow);
+               this.dataLink = dataLink;
+       }
+
+       @Override
+       protected void doEditAction(Workflow workflow) {
+               ReceiverPort sink = dataLink.getSendsTo();
+               List<DataLink> datalinksTo = scufl2Tools.datalinksTo(sink);
+               if (datalinksTo.size() > 0) {
+                       if (datalinksTo.size() == 1)
+                               datalinksTo.get(0).setMergePosition(0);
+                       dataLink.setMergePosition(datalinksTo.size());
+               } else {
+                       dataLink.setMergePosition(null);
+                       if (sink instanceof InputProcessorPort) {
+                               InputProcessorPort inputProcessorPort = 
(InputProcessorPort) sink;
+                               for (IterationStrategyTopNode node : 
inputProcessorPort.getParent().getIterationStrategyStack()) {
+                                       portNode = new PortNode(node, 
inputProcessorPort);
+                                       
portNode.setDesiredDepth(inputProcessorPort.getDepth());
+                                       break;
+                               }
+                       }
+               }
+               dataLink.setParent(workflow);
+       }
+
+       @Override
+       protected void undoEditAction(Workflow workflow) {
+               dataLink.setParent(null);
+               ReceiverPort sink = dataLink.getSendsTo();
+               List<DataLink> datalinksTo = scufl2Tools.datalinksTo(sink);
+               if (datalinksTo.size() == 1)
+                       datalinksTo.get(0).setMergePosition(null);
+               else if (datalinksTo.isEmpty()&&portNode != null) {
+                       IterationStrategyParent parent = portNode.getParent();
+                       if (parent instanceof DotProduct)
+                               ((DotProduct) parent).remove(portNode);
+                       else if (parent instanceof CrossProduct)
+                               ((CrossProduct) parent).remove(portNode);
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddIterationStrategyEdit.java
----------------------------------------------------------------------
diff --git 
a/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddIterationStrategyEdit.java
 
b/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddIterationStrategyEdit.java
new file mode 100644
index 0000000..27b0af0
--- /dev/null
+++ 
b/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddIterationStrategyEdit.java
@@ -0,0 +1,48 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflow.edits;
+
+import org.apache.taverna.scufl2.api.iterationstrategy.IterationStrategyStack;
+import 
org.apache.taverna.scufl2.api.iterationstrategy.IterationStrategyTopNode;
+
+/**
+ * Adds an IterationStrategyTopNode to an IterationStrategyStack.
+ *
+ * @author David Withers
+ */
+public class AddIterationStrategyEdit extends 
AbstractEdit<IterationStrategyStack> {
+       private final IterationStrategyTopNode iterationStrategyTopNode;
+
+       public AddIterationStrategyEdit(IterationStrategyStack 
iterationStrategyStack,
+                       IterationStrategyTopNode iterationStrategyTopNode) {
+               super(iterationStrategyStack);
+               this.iterationStrategyTopNode = iterationStrategyTopNode;
+       }
+
+       @Override
+       public void doEditAction(IterationStrategyStack iterationStrategyStack) 
{
+               iterationStrategyStack.add(iterationStrategyTopNode);
+       }
+
+       @Override
+       public void undoEditAction(IterationStrategyStack 
iterationStrategyStack) {
+               iterationStrategyStack.remove(iterationStrategyTopNode);
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddIterationStrategyInputPortEdit.java
----------------------------------------------------------------------
diff --git 
a/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddIterationStrategyInputPortEdit.java
 
b/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddIterationStrategyInputPortEdit.java
new file mode 100644
index 0000000..d918445
--- /dev/null
+++ 
b/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddIterationStrategyInputPortEdit.java
@@ -0,0 +1,49 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflow.edits;
+
+import org.apache.taverna.scufl2.api.iterationstrategy.IterationStrategyStack;
+import org.apache.taverna.scufl2.api.iterationstrategy.PortNode;
+
+/**
+ * Adds an iteration strategy input port node to an iteration strategy.
+ * 
+ * @author David Withers
+ */
+public class AddIterationStrategyInputPortEdit extends
+               AbstractEdit<IterationStrategyStack> {
+       private final PortNode portNode;
+
+       public AddIterationStrategyInputPortEdit(
+                       IterationStrategyStack iterationStrategy, PortNode 
portNode) {
+               super(iterationStrategy);
+               this.portNode = portNode;
+       }
+
+       @Override
+       public void doEditAction(IterationStrategyStack iterationStrategy) {
+               portNode.setParent(iterationStrategy.get(0));
+       }
+
+       @Override
+       public void undoEditAction(IterationStrategyStack iterationStrategy) {
+               portNode.setParent(null);
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddProcessorEdit.java
----------------------------------------------------------------------
diff --git 
a/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddProcessorEdit.java
 
b/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddProcessorEdit.java
new file mode 100644
index 0000000..e30a6a0
--- /dev/null
+++ 
b/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddProcessorEdit.java
@@ -0,0 +1,44 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflow.edits;
+
+import org.apache.taverna.scufl2.api.core.Processor;
+import org.apache.taverna.scufl2.api.core.Workflow;
+
+/**
+ * Adds a Processor to a Workflow.
+ *
+ * @author Stuart Owen
+ * @author David Withers
+ */
+public class AddProcessorEdit extends AddChildEdit<Workflow> {
+       private Processor processor;
+
+       public AddProcessorEdit(Workflow workflow, Processor processor) {
+               super(workflow, processor);
+               this.processor = processor;
+       }
+
+       @Override
+       protected void doEditAction(Workflow workflow) {
+               getSubject().getProcessors().addWithUniqueName(processor);
+               super.doEditAction(workflow);
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddProcessorInputPortEdit.java
----------------------------------------------------------------------
diff --git 
a/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddProcessorInputPortEdit.java
 
b/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddProcessorInputPortEdit.java
new file mode 100644
index 0000000..7a22491
--- /dev/null
+++ 
b/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddProcessorInputPortEdit.java
@@ -0,0 +1,44 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflow.edits;
+
+import org.apache.taverna.scufl2.api.core.Processor;
+import org.apache.taverna.scufl2.api.port.InputProcessorPort;
+
+/**
+ * Adds an input port to a processor.
+ *
+ * @author Tom Oinn
+ * @author David Withers
+ */
+public class AddProcessorInputPortEdit extends AddChildEdit<Processor> {
+       private final InputProcessorPort port;
+
+       public AddProcessorInputPortEdit(Processor processor, 
InputProcessorPort port) {
+               super(processor, port);
+               this.port = port;
+       }
+
+       @Override
+       protected void doEditAction(Processor processor) {
+               processor.getInputPorts().addWithUniqueName(port);
+               super.doEditAction(processor);
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddProcessorOutputPortEdit.java
----------------------------------------------------------------------
diff --git 
a/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddProcessorOutputPortEdit.java
 
b/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddProcessorOutputPortEdit.java
new file mode 100644
index 0000000..1cdfef2
--- /dev/null
+++ 
b/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddProcessorOutputPortEdit.java
@@ -0,0 +1,45 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflow.edits;
+
+import org.apache.taverna.scufl2.api.core.Processor;
+import org.apache.taverna.scufl2.api.port.OutputProcessorPort;
+
+/**
+ * Adds an output port to a processor.
+ * 
+ * @author Tom Oinn
+ * @author David Withers
+ */
+public class AddProcessorOutputPortEdit extends AddChildEdit<Processor> {
+       private final OutputProcessorPort port;
+
+       public AddProcessorOutputPortEdit(Processor processor,
+                       OutputProcessorPort port) {
+               super(processor, port);
+               this.port = port;
+       }
+
+       @Override
+       protected void doEditAction(Processor processor) {
+               processor.getOutputPorts().addWithUniqueName(port);
+               super.doEditAction(processor);
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddWorkflowInputPortEdit.java
----------------------------------------------------------------------
diff --git 
a/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddWorkflowInputPortEdit.java
 
b/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddWorkflowInputPortEdit.java
new file mode 100644
index 0000000..7b407d6
--- /dev/null
+++ 
b/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddWorkflowInputPortEdit.java
@@ -0,0 +1,109 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflow.edits;
+
+import static org.apache.taverna.scufl2.api.common.Scufl2Tools.NESTED_WORKFLOW;
+
+import java.util.List;
+
+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.scufl2.api.activity.Activity;
+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.port.InputActivityPort;
+import org.apache.taverna.scufl2.api.port.InputProcessorPort;
+import org.apache.taverna.scufl2.api.port.InputWorkflowPort;
+import org.apache.taverna.scufl2.api.profiles.ProcessorBinding;
+import org.apache.taverna.scufl2.api.profiles.ProcessorInputPortBinding;
+import org.apache.taverna.scufl2.api.profiles.Profile;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+/**
+ * Adds an input port to a workflow.
+ * 
+ * @author David Withers
+ */
+public class AddWorkflowInputPortEdit extends AbstractEdit<Workflow> {
+       private final InputWorkflowPort port;
+       private final CompoundEdit nestedPortEdit = new CompoundEdit();
+
+       public AddWorkflowInputPortEdit(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))
+                                                       
defineEditsForOneConfiguration(workflow, port,
+                                                                       
workflowBundle, activity, c);
+       }
+
+       private void defineEditsForOneConfiguration(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) {
+                       InputActivityPort activityPort = new 
InputActivityPort();
+                       activityPort.setName(port.getName());
+                       activityPort.setDepth(port.getDepth());
+                       edits.add(new AddChildEdit<>(activity, activityPort));
+
+                       for (ProcessorBinding binding : scufl2Tools
+                                       .processorBindingsToActivity(activity)) 
{
+                               Processor processor = 
binding.getBoundProcessor();
+                               InputProcessorPort processorPort = new 
InputProcessorPort();
+                               processorPort.setName(port.getName());
+                               processorPort.setDepth(port.getDepth());
+                               edits.add(new 
AddProcessorInputPortEdit(processor,
+                                               processorPort));
+
+                               ProcessorInputPortBinding portBinding = new 
ProcessorInputPortBinding();
+                               
portBinding.setBoundProcessorPort(processorPort);
+                               portBinding.setBoundActivityPort(activityPort);
+                               edits.add(new AddChildEdit<>(binding, 
portBinding));
+                       }
+               }
+       }
+
+       @Override
+       protected void doEditAction(Workflow workflow) throws EditException {
+               workflow.getInputPorts().addWithUniqueName(port);
+               port.setParent(workflow);
+               nestedPortEdit.doEdit();
+       }
+
+       @Override
+       protected void undoEditAction(Workflow workflow) {
+               port.setParent(null);
+               nestedPortEdit.undo();
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddWorkflowOutputPortEdit.java
----------------------------------------------------------------------
diff --git 
a/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddWorkflowOutputPortEdit.java
 
b/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddWorkflowOutputPortEdit.java
new file mode 100644
index 0000000..301754d
--- /dev/null
+++ 
b/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/AddWorkflowOutputPortEdit.java
@@ -0,0 +1,110 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflow.edits;
+
+import static org.apache.taverna.scufl2.api.common.Scufl2Tools.NESTED_WORKFLOW;
+
+import java.util.List;
+
+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.scufl2.api.activity.Activity;
+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.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.ProcessorOutputPortBinding;
+import org.apache.taverna.scufl2.api.profiles.Profile;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+/**
+ * Adds an output port to a workflow.
+ *
+ * @author David Withers
+ */
+public class AddWorkflowOutputPortEdit extends AbstractEdit<Workflow> {
+       private final OutputWorkflowPort port;
+       private final CompoundEdit nestedPortEdit = new CompoundEdit();
+
+       public AddWorkflowOutputPortEdit(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))
+                                                       
defineEditsForOneConfiguration(workflow, port,
+                                                                       
workflowBundle, activity, c);
+       }
+
+       private void defineEditsForOneConfiguration(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) {
+                       OutputActivityPort activityPort = new 
OutputActivityPort();
+                       activityPort.setName(port.getName());
+                       activityPort.setDepth(0);
+                       activityPort.setGranularDepth(0);
+                       edits.add(new AddChildEdit<>(activity, activityPort));
+
+                       for (ProcessorBinding binding : scufl2Tools
+                                       .processorBindingsToActivity(activity)) 
{
+                               Processor processor = 
binding.getBoundProcessor();
+                               OutputProcessorPort processorPort = new 
OutputProcessorPort();
+                               processorPort.setName(port.getName());
+                               processorPort.setDepth(0);
+                               processorPort.setGranularDepth(0);
+                               edits.add(new 
AddProcessorOutputPortEdit(processor,
+                                               processorPort));
+
+                               ProcessorOutputPortBinding portBinding = new 
ProcessorOutputPortBinding();
+                               
portBinding.setBoundProcessorPort(processorPort);
+                               portBinding.setBoundActivityPort(activityPort);
+                               edits.add(new AddChildEdit<>(binding, 
portBinding));
+                       }
+               }
+       }
+
+       @Override
+       protected void doEditAction(Workflow workflow) throws EditException {
+               workflow.getOutputPorts().addWithUniqueName(port);
+               port.setParent(workflow);
+               nestedPortEdit.doEdit();
+       }
+
+       @Override
+       protected void undoEditAction(Workflow workflow) {
+               port.setParent(null);
+               nestedPortEdit.undo();
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/ChangeDepthEdit.java
----------------------------------------------------------------------
diff --git 
a/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/ChangeDepthEdit.java
 
b/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/ChangeDepthEdit.java
new file mode 100644
index 0000000..1c48ac5
--- /dev/null
+++ 
b/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/ChangeDepthEdit.java
@@ -0,0 +1,103 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflow.edits;
+
+import static org.apache.taverna.scufl2.api.common.Scufl2Tools.NESTED_WORKFLOW;
+import org.apache.taverna.scufl2.api.activity.Activity;
+import org.apache.taverna.scufl2.api.configurations.Configuration;
+import org.apache.taverna.scufl2.api.container.WorkflowBundle;
+import org.apache.taverna.scufl2.api.core.Workflow;
+import org.apache.taverna.scufl2.api.port.ActivityPort;
+import org.apache.taverna.scufl2.api.port.DepthPort;
+import org.apache.taverna.scufl2.api.port.InputProcessorPort;
+import org.apache.taverna.scufl2.api.port.InputWorkflowPort;
+import org.apache.taverna.scufl2.api.profiles.ProcessorBinding;
+import org.apache.taverna.scufl2.api.profiles.ProcessorInputPortBinding;
+import org.apache.taverna.scufl2.api.profiles.Profile;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+/**
+ * Changes the depth of a port.
+ *
+ * @author David Withers
+ */
+public class ChangeDepthEdit<T extends DepthPort> extends AbstractEdit<T> {
+       private Integer newDepth, oldDepth;
+
+       public ChangeDepthEdit(T depthPort, Integer newDepth) {
+               super(depthPort);
+               this.newDepth = newDepth;
+               oldDepth = depthPort.getDepth();
+       }
+
+       @Override
+       protected void doEditAction(T depthPort) {
+               depthPort.setDepth(newDepth);
+               if (depthPort instanceof InputWorkflowPort)
+                       checkNestedPortDepths((InputWorkflowPort) depthPort, 
newDepth);
+       }
+
+       @Override
+       protected void undoEditAction(T depthPort) {
+               depthPort.setDepth(oldDepth);
+               if (depthPort instanceof InputWorkflowPort)
+                       checkNestedPortDepths((InputWorkflowPort) depthPort, 
oldDepth);
+       }
+
+       private void checkNestedPortDepths(InputWorkflowPort workflowPort,
+                       Integer depth) {
+               Workflow workflow = workflowPort.getParent();
+               if (workflow != null) {
+                       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))
+                                                               
checkOneConfiguration(workflowPort, depth,
+                                                                               
workflow, workflowBundle, activity, c);
+               }
+       }
+
+       private void checkOneConfiguration(InputWorkflowPort workflowPort,
+                       Integer depth, 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 = activity.getInputPorts().getByName(
+                               workflowPort.getName());
+               activityPort.setDepth(depth);
+               for (ProcessorBinding binding : scufl2Tools
+                               .processorBindingsToActivity(activity))
+                       for (ProcessorInputPortBinding portBinding : binding
+                                       .getInputPortBindings())
+                               if (portBinding.getBoundActivityPort() == 
activityPort) {
+                                       InputProcessorPort processorPort = 
portBinding
+                                                       
.getBoundProcessorPort();
+                                       processorPort.setDepth(depth);
+                               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/ChangeGranularDepthEdit.java
----------------------------------------------------------------------
diff --git 
a/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/ChangeGranularDepthEdit.java
 
b/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/ChangeGranularDepthEdit.java
new file mode 100644
index 0000000..061525a
--- /dev/null
+++ 
b/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/ChangeGranularDepthEdit.java
@@ -0,0 +1,48 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflow.edits;
+
+import org.apache.taverna.scufl2.api.port.GranularDepthPort;
+
+/**
+ * Changes the granular depth of a port.
+ * 
+ * @author David Withers
+ */
+public class ChangeGranularDepthEdit<T extends GranularDepthPort> extends
+               AbstractEdit<T> {
+       private Integer newGranularDepth, oldGranularDepth;
+
+       public ChangeGranularDepthEdit(T granularDepthPort, Integer 
newGranularDepth) {
+               super(granularDepthPort);
+               this.newGranularDepth = newGranularDepth;
+               oldGranularDepth = granularDepthPort.getGranularDepth();
+       }
+
+       @Override
+       protected void doEditAction(T granularDepthPort) {
+               granularDepthPort.setGranularDepth(newGranularDepth);
+       }
+
+       @Override
+       protected void undoEditAction(T granularDepthPort) {
+               granularDepthPort.setGranularDepth(oldGranularDepth);
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/ChangeJsonEdit.java
----------------------------------------------------------------------
diff --git 
a/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/ChangeJsonEdit.java
 
b/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/ChangeJsonEdit.java
new file mode 100644
index 0000000..53c351d
--- /dev/null
+++ 
b/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/ChangeJsonEdit.java
@@ -0,0 +1,49 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflow.edits;
+
+import org.apache.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/a9a52bd5/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/ClearIterationStrategyStackEdit.java
----------------------------------------------------------------------
diff --git 
a/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/ClearIterationStrategyStackEdit.java
 
b/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/ClearIterationStrategyStackEdit.java
new file mode 100644
index 0000000..fc39119
--- /dev/null
+++ 
b/taverna-edits-api/src/main/java/org/apache/taverna/workflow/edits/ClearIterationStrategyStackEdit.java
@@ -0,0 +1,49 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflow.edits;
+
+import org.apache.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);
+       }
+}

Reply via email to