Add method to create nested workflow
Contributed by Majdi Haouech (ICLA on file)
@haouech
See #41
Signed-off-by: Stian Soiland-Reyes <stain@apache.org>
diff --git a/taverna-scufl2-api/src/main/java/org/apache/taverna/scufl2/api/common/Scufl2Tools.java b/taverna-scufl2-api/src/main/java/org/apache/taverna/scufl2/api/common/Scufl2Tools.java
index c7d4b11..e3b5d6e 100644
--- a/taverna-scufl2-api/src/main/java/org/apache/taverna/scufl2/api/common/Scufl2Tools.java
+++ b/taverna-scufl2-api/src/main/java/org/apache/taverna/scufl2/api/common/Scufl2Tools.java
@@ -65,6 +65,7 @@
import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* Utility methods for dealing with SCUFL2 models
@@ -752,6 +753,34 @@
return activity;
}
+ public Configuration setAsNestedWorkflow(Processor processor, Workflow childWorkflow, Profile profile) {
+ if(processor.getParent() == null) {
+ throw new IllegalStateException("Processor " + processor + " has no parent");
+ }
+ if(processor.getParent().getParent() != childWorkflow.getParent()) {
+ throw new IllegalStateException(
+ "Processor " + processor + " and workflow " + childWorkflow + " are not in the same Workflow bundle");
+ }
+ if(nestedWorkflowForProcessor(processor, profile) != null) {
+ throw new IllegalStateException("Processor " + processor + " already has a nested workflow");
+ }
+ List<ProcessorBinding> processorBindings = processorBindingsForProcessor(processor, profile);
+ if(processorBindings.size() != 0) {
+ throw new IllegalStateException("Processor " + processor + "already has a binding");
+ }
+
+ Activity activity = createActivityFromProcessor(processor, profile);
+ activity.setType(NESTED_WORKFLOW);
+ Configuration configuration = createConfigurationFor(activity, NESTED_WORKFLOW);
+
+ ObjectNode json = configuration.getJsonAsObjectNode();
+ json.put("nestedWorkflow", childWorkflow.getName());
+
+ childWorkflow.setParent(processor.getParent().getParent());
+
+ return configuration;
+ }
+
public void removePortsBindingForUnknownPorts(ProcessorBinding binding) {
// First, remove ports no longer owned by processor
Iterator<ProcessorInputPortBinding> inputBindings = binding
diff --git a/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/api/common/TestScufl2Tools.java b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/api/common/TestScufl2Tools.java
index 5880253..d397168 100644
--- a/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/api/common/TestScufl2Tools.java
+++ b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/api/common/TestScufl2Tools.java
@@ -31,20 +31,24 @@
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.stream.Collectors;
import org.apache.taverna.scufl2.api.ExampleWorkflow;
import org.apache.taverna.scufl2.api.activity.Activity;
-import org.apache.taverna.scufl2.api.common.Child;
-import org.apache.taverna.scufl2.api.common.Scufl2Tools;
-import org.apache.taverna.scufl2.api.common.WorkflowBean;
import org.apache.taverna.scufl2.api.common.Visitor.VisitorWithPath;
+import org.apache.taverna.scufl2.api.configurations.Configuration;
import org.apache.taverna.scufl2.api.container.WorkflowBundle;
import org.apache.taverna.scufl2.api.core.ControlLink;
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.port.OutputActivityPort;
import org.apache.taverna.scufl2.api.port.OutputProcessorPort;
+import org.apache.taverna.scufl2.api.port.OutputWorkflowPort;
import org.apache.taverna.scufl2.api.profiles.ProcessorBinding;
import org.apache.taverna.scufl2.api.profiles.ProcessorInputPortBinding;
import org.apache.taverna.scufl2.api.profiles.ProcessorOutputPortBinding;
@@ -63,6 +67,59 @@
makeWorkflowBundle();
assertNotNull(workflowBundle);
}
+
+ @Test
+ public void testNestedWorkflows() {
+ Workflow child = new Workflow();
+ child.setName("childWorkflow");
+ child.setParent(workflowBundle);
+
+ Workflow mainWorkflow = workflowBundle.getMainWorkflow();
+ Processor processor = new Processor();
+ processor.setParent(mainWorkflow);
+
+ Profile profile = workflowBundle.getMainProfile();
+
+ Scufl2Tools tools = new Scufl2Tools();
+ tools.setAsNestedWorkflow(processor, child, profile);
+ Workflow nested = tools.nestedWorkflowForProcessor(processor, profile);
+
+ assertEquals(child, nested);
+
+ ProcessorBinding binding = processor.getBinding(profile);
+ Activity activity = binding.getBoundActivity();
+ Configuration configuration = activity.getConfiguration();
+
+ assertEquals(activity.getType(), Scufl2Tools.NESTED_WORKFLOW);
+ String nestedWorkflowName = configuration.getJson().get("nestedWorkflow").asText();
+ assertEquals(nestedWorkflowName, child.getName());
+ }
+
+ @Test
+ public void testNestedProcessHasCorrectStructure() {
+ Workflow child = new Workflow();
+ child.setName("childWorkflow");
+ child.setParent(workflowBundle);
+
+ Workflow mainWorkflow = workflowBundle.getMainWorkflow();
+ Processor processor = new Processor();
+ processor.setParent(mainWorkflow);
+
+ Profile profile = workflowBundle.getMainProfile();
+
+ Scufl2Tools tools = new Scufl2Tools();
+ tools.setAsNestedWorkflow(processor, child, profile);
+
+ Set<String> processorInputNames = processor.getInputPorts().stream().map(InputProcessorPort::getName).collect(Collectors.toSet());
+ Set<String> workflowInputNames = child.getInputPorts().stream().map(InputWorkflowPort::getName).collect(Collectors.toSet());
+
+ assertEquals(workflowInputNames, processorInputNames);
+
+ Set<String> processorOutputNames = processor.getOutputPorts().stream().map(OutputProcessorPort::getName).collect(Collectors.toSet());
+ Set<String> workflowOutputNames = child.getOutputPorts().stream().map(OutputWorkflowPort::getName).collect(Collectors.toSet());
+
+ assertEquals(workflowOutputNames, processorOutputNames);
+ }
@Test
public void controlLinksBlocking() {