Merge branch 'cwlparser'

Contributed by Majdi Haouech

Signed-off-by: Stian Soiland-Reyes <stain@apache.org>
diff --git a/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/CWLParser.java b/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/CWLParser.java
index 63e70d1..fd5f9c1 100644
--- a/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/CWLParser.java
+++ b/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/CWLParser.java
@@ -22,16 +22,11 @@
 import java.util.Set;
 import java.util.HashSet;
 
-import org.apache.taverna.scufl2.api.core.Workflow;
-import org.apache.taverna.scufl2.api.core.Processor;
-
-import org.apache.taverna.scufl2.api.port.InputWorkflowPort;
-import org.apache.taverna.scufl2.api.port.OutputWorkflowPort;
-import org.apache.taverna.scufl2.api.port.InputProcessorPort;
-import org.apache.taverna.scufl2.api.port.OutputProcessorPort;
-
 import com.fasterxml.jackson.databind.JsonNode;
 
+import org.apache.taverna.scufl2.cwl.components.Step;
+import org.apache.taverna.scufl2.cwl.components.PortDetail;
+
 public class CWLParser {
 
     private JsonNode cwlFile;
diff --git a/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/CWLReader.java b/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/CWLReader.java
index de9d799..8f0f664 100644
--- a/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/CWLReader.java
+++ b/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/CWLReader.java
@@ -27,6 +27,7 @@
 import org.apache.taverna.scufl2.api.io.WorkflowBundleReader;
 import org.apache.taverna.scufl2.api.io.ReaderException;
 
+import org.apache.taverna.scufl2.cwl.components.WorkflowProcess;
 
 public class CWLReader implements WorkflowBundleReader {
 
diff --git a/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/Converter.java b/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/Converter.java
index 5cfd9ce..79d4e24 100644
--- a/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/Converter.java
+++ b/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/Converter.java
@@ -21,8 +21,9 @@
 import java.util.Set;
 import java.util.HashSet;
 import java.util.Map;
-import java.util.HashMap;
 
+import org.apache.taverna.scufl2.api.common.NamedSet;
+import org.apache.taverna.scufl2.api.core.DataLink;
 import org.apache.taverna.scufl2.api.core.Workflow;
 import org.apache.taverna.scufl2.api.core.Processor;
 import org.apache.taverna.scufl2.api.container.WorkflowBundle;
@@ -37,6 +38,17 @@
 import com.fasterxml.jackson.databind.node.ArrayNode;
 import com.fasterxml.jackson.databind.node.JsonNodeFactory;
 
+import org.apache.taverna.scufl2.api.port.ReceiverPort;
+import org.apache.taverna.scufl2.api.port.SenderPort;
+import org.apache.taverna.scufl2.cwl.components.Process;
+import org.apache.taverna.scufl2.cwl.components.PortDetail;
+import org.apache.taverna.scufl2.cwl.components.Step;
+import org.apache.taverna.scufl2.cwl.components.InputPort;
+import org.apache.taverna.scufl2.cwl.components.OutputPort;
+import org.apache.taverna.scufl2.cwl.components.WorkflowProcess;
+import org.apache.taverna.scufl2.cwl.components.CommandLineTool;
+import org.apache.taverna.scufl2.cwl.components.Reference;
+
 public class Converter {
 
     private JsonNodeFactory jsonNodeFactory;
@@ -177,24 +189,58 @@
         Set<OutputWorkflowPort> outputs = new HashSet<>(workflowProcess.getWorkflowOutputs().values());
         workflow.setInputPorts(inputs);
         workflow.setOutputPorts(outputs);
+        Set<InputPort> inputPorts = workflowProcess.getInsideInputPorts();
+        Set<OutputPort> outputPorts = workflowProcess.getInsideOutputPorts();
+
+        NamedSet<InputProcessorPort> inputProcessorPorts = new NamedSet<>();
+        NamedSet<OutputProcessorPort> outputProcessorPorts = new NamedSet<>();
 
         for(Process process: workflowProcess.getProcesses()) {
+            Processor processor;
             if(process instanceof WorkflowProcess) {
                 Workflow childWorkflow = convertWorkflowProcess((WorkflowProcess) process, bundle); // TODO: Add nested relationship
+                processor = new Processor(workflow, childWorkflow.getName()); // TODO: Check if we want the processor to have the same name as the childworkflow
+                createProcessPortsFromWorkflow(processor, childWorkflow);
                 bundle.getWorkflows().add(childWorkflow);
             } else if(process instanceof CommandLineTool) {
-                Processor processor = convertCommandLineTool((CommandLineTool) process);
+                processor = convertCommandLineTool((CommandLineTool) process);
                 workflow.getProcessors().add(processor);
             } else {
                 assert(process instanceof Reference);
-                Processor processor = convertReference((Reference) process);
+                processor = convertReference((Reference) process);
                 workflow.getProcessors().add(processor);
             }
+            inputProcessorPorts.addAll(processor.getInputPorts());
+            outputProcessorPorts.addAll(processor.getOutputPorts());
+        }
+
+        // DataLinks
+        for(InputPort port: inputPorts) {
+            String senderName = port.getSource();
+            String destName = port.getName();
+            SenderPort senderPort = outputProcessorPorts.getByName(senderName);
+            if(senderPort == null) { // Source is one of the Workflow inputs
+                senderPort = workflow.getInputPorts().getByName(senderName);
+            }
+            ReceiverPort receiverPort = inputProcessorPorts.getByName(destName);
+            if(receiverPort == null) { // Destination is one of the Workflow outputs
+                receiverPort = workflow.getOutputPorts().getByName(destName);
+            }
+            new DataLink(workflow, senderPort, receiverPort);
         }
 
         return workflow;
     }
 
+    public void createProcessPortsFromWorkflow(Processor processor, Workflow workflow) {
+        for(InputWorkflowPort inputWorkflowPort: workflow.getInputPorts()) {
+            processor.getInputPorts().add(new InputProcessorPort(processor, inputWorkflowPort.getName()));
+        }
+        for(OutputWorkflowPort outputWorkflowPort: workflow.getOutputPorts()) {
+            processor.getOutputPorts().add(new OutputProcessorPort(processor, outputWorkflowPort.getName()));
+        }
+    }
+
     public Processor convertCommandLineTool(CommandLineTool command) {
         Processor processor = new Processor(null, command.getBaseCommand());
 
diff --git a/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/TavernaConverter.java b/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/TavernaConverter.java
new file mode 100644
index 0000000..da1ece3
--- /dev/null
+++ b/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/TavernaConverter.java
@@ -0,0 +1,81 @@
+package org.apache.taverna.scufl2.cwl;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import org.apache.taverna.scufl2.api.common.NamedSet;
+import org.apache.taverna.scufl2.api.core.DataLink;
+import org.apache.taverna.scufl2.api.core.Processor;
+import org.apache.taverna.scufl2.api.core.Workflow;
+import org.apache.taverna.scufl2.api.port.InputProcessorPort;
+import org.apache.taverna.scufl2.api.port.InputWorkflowPort;
+import org.apache.taverna.scufl2.api.port.OutputWorkflowPort;
+import org.apache.taverna.scufl2.api.port.SenderPort;
+import org.apache.taverna.scufl2.cwl.components.InputPort;
+import org.apache.taverna.scufl2.cwl.components.OutputPort;
+import org.apache.taverna.scufl2.cwl.components.Reference;
+import org.apache.taverna.scufl2.cwl.components.Step;
+import org.apache.taverna.scufl2.cwl.components.WorkflowProcess;
+
+public class TavernaConverter {
+
+    public WorkflowProcess convertWorkflow(Workflow workflow) {
+        WorkflowProcess process = new WorkflowProcess();
+        process.setName(workflow.getName());
+        Set<InputPort> inputs = convertInputPorts(workflow);
+        Set<OutputPort> outputs = convertOutputPorts(workflow);
+
+        process.setInputPorts(inputs);
+        process.setOutputPorts(outputs);
+
+        return process;
+    }
+
+    public Set<InputPort> convertInputPorts(Workflow workflow) {
+        Set<InputPort> result = new HashSet<>();
+        for(InputWorkflowPort workflowPort: workflow.getInputPorts()) {
+            InputPort port = new InputPort(workflowPort.getName(), "");
+            result.add(port);
+        }
+        return result;
+    }
+
+    public Set<OutputPort> convertOutputPorts(Workflow workflow) {
+        Set<OutputPort> result = new HashSet<>();
+        for(OutputWorkflowPort workflowPort: workflow.getOutputPorts()) {
+            OutputPort port = new OutputPort(workflowPort.getName());
+            result.add(port);
+        }
+        return result;
+    }
+
+    public Set<Step> convertProcessors(Workflow workflow) {
+        Set<Step> result = new HashSet<>();
+        NamedSet<Processor> processors = workflow.getProcessors();
+        Set<DataLink> dataLinks = workflow.getDataLinks();
+        Map<String, SenderPort> portNameToSource = new HashMap<>();
+        for(DataLink link: dataLinks) {
+            portNameToSource.put(link.getSendsTo().getName(), link.getReceivesFrom());
+        }
+
+        for(Processor processor: processors) {
+            Step step = convertProcessor(processor, portNameToSource);
+            result.add(step);
+        }
+        return result;
+    }
+
+    public Step convertProcessor(Processor processor, Map<String, SenderPort> portNameToSource) {
+        Step step = new Step();
+        step.setRun(new Reference(processor.getName())); // TODO: Support nested steps. Check name value.
+        for(InputProcessorPort port: processor.getInputPorts()) {
+            InputPort stepPort = new InputPort();
+            stepPort.setName(port.getName());
+            SenderPort senderPort = portNameToSource.get(port.getName());
+            stepPort.setSource(senderPort.getName());
+            step.getInputs().add(stepPort);
+        }
+        return step;
+    }
+}
diff --git a/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/WorkflowParser.java b/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/WorkflowParser.java
index 2680bf4..9191806 100644
--- a/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/WorkflowParser.java
+++ b/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/WorkflowParser.java
@@ -49,6 +49,12 @@
 import org.apache.taverna.scufl2.api.io.WorkflowBundleIO;
 import org.apache.taverna.scufl2.api.io.WriterException;
 
+import org.apache.taverna.scufl2.cwl.components.Step;
+import org.apache.taverna.scufl2.cwl.components.PortDetail;
+import org.apache.taverna.scufl2.cwl.components.InputPort;
+import org.apache.taverna.scufl2.cwl.components.OutputPort;
+
+
 public class WorkflowParser {
 
     private static final String FILE_NAME = "/hello_world.cwl";
diff --git a/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/YAMLHelper.java b/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/YAMLHelper.java
index 1b016f8..6561c59 100644
--- a/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/YAMLHelper.java
+++ b/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/YAMLHelper.java
@@ -36,6 +36,13 @@
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.fasterxml.jackson.databind.node.TextNode;
 
+import org.apache.taverna.scufl2.cwl.components.Process;
+import org.apache.taverna.scufl2.cwl.components.Step;
+import org.apache.taverna.scufl2.cwl.components.PortDetail;
+import org.apache.taverna.scufl2.cwl.components.InputPort;
+import org.apache.taverna.scufl2.cwl.components.OutputPort;
+import org.apache.taverna.scufl2.cwl.components.ProcessFactory;
+
 public class YAMLHelper {
 
     public static final String ARRAY_SPLIT_BRACKETS = "\\[\\]";
@@ -122,9 +129,12 @@
                 Process run = ProcessFactory.createProcess(runNode);
                 run.parse();  // Recursively parse nested process
                 Set<InputPort> inputs = processStepInput(stepNode.get(INPUTS));
+                Set<OutputPort> outputs = processStepOutput(stepNode.get(OUTPUTS));
                 step.setId(id);
                 step.setRun(run);
                 step.setInputs(inputs);
+                step.setOutputs(outputs);
+
                 result.add(step);
             }
         } else if(steps.isObject()) {
@@ -142,8 +152,10 @@
                     step.setRun(run);
                 }
                 Set<InputPort> inputs = processStepInput(value.get(INPUTS));
+                Set<OutputPort> outputs = processStepOutput(value.get(OUTPUTS));
                 step.setId(id);
                 step.setInputs(inputs);
+                step.setOutputs(outputs);
 
                 result.add(step);
             }
@@ -180,6 +192,32 @@
         return result;
     }
 
+    private Set<OutputPort> processStepOutput(JsonNode outputs) {
+        Set<OutputPort> result = new HashSet<>();
+        if(outputs == null) {
+            return result;
+        }
+        if (outputs.isArray()) {
+
+            for (JsonNode output : outputs) {
+                String id = output.get(ID).asText();
+
+                result.add(new OutputPort(id));
+            }
+        } else if (outputs.isObject()) {
+            Iterator<Entry<String, JsonNode>> iterator = outputs.fields();
+            while (iterator.hasNext()) {
+                Entry<String, JsonNode> entry = iterator.next();
+
+                String id = entry.getKey();
+
+                result.add(new OutputPort(id));
+            }
+        }
+
+        return result;
+    }
+
     /**
      * This method will go through CWL tool input or out puts and figure outs
      * their IDs and the respective depths
diff --git a/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/CommandLineTool.java b/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/CommandLineTool.java
index dc5e16d..4270f46 100644
--- a/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/CommandLineTool.java
+++ b/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/CommandLineTool.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-package org.apache.taverna.scufl2.cwl;
+package org.apache.taverna.scufl2.cwl.components;
 
 import java.util.Set;
 import java.util.Map;
@@ -28,6 +28,9 @@
 import org.apache.taverna.scufl2.api.port.InputProcessorPort;
 import org.apache.taverna.scufl2.api.port.OutputProcessorPort;
 
+
+import org.apache.taverna.scufl2.cwl.*;
+
 public class CommandLineTool extends Process {
 
     private final static String BASE_COMMAND = "baseCommand";
@@ -43,6 +46,7 @@
     private Map<String, OutputProcessorPort> processorOutputs = new HashMap<>();
 
     public CommandLineTool(JsonNode node) {
+        this.name = "";
         this.node = node;
         this.cwlParser = new CWLParser(node);
         this.parse();
diff --git a/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/InputPort.java b/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/InputPort.java
index 1d1522d..1b44a27 100644
--- a/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/InputPort.java
+++ b/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/InputPort.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-package org.apache.taverna.scufl2.cwl;
+package org.apache.taverna.scufl2.cwl.components;
 
 public class InputPort {
 
diff --git a/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/OutputPort.java b/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/OutputPort.java
index c865e9c..ac7c139 100644
--- a/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/OutputPort.java
+++ b/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/OutputPort.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-package org.apache.taverna.scufl2.cwl;
+package org.apache.taverna.scufl2.cwl.components;
 
 public class OutputPort {
 
diff --git a/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/PortDetail.java b/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/PortDetail.java
index 53604e7..cbfdae9 100644
--- a/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/PortDetail.java
+++ b/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/PortDetail.java
@@ -17,15 +17,13 @@
  * under the License.
  */
 
-package org.apache.taverna.scufl2.cwl;
+package org.apache.taverna.scufl2.cwl.components;
 
 
 import java.util.ArrayList;
 
 public class PortDetail {
 
-
-
     private String id;
     private String label;
     private int depth;
diff --git a/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/Process.java b/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/Process.java
index 991df0a..c152b12 100644
--- a/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/Process.java
+++ b/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/Process.java
@@ -17,16 +17,20 @@
  * under the License.
  */
 
-package org.apache.taverna.scufl2.cwl;
+package org.apache.taverna.scufl2.cwl.components;
 
 import java.util.HashSet;
 import java.util.Set;
 
 public abstract class Process {
 
-    private Set<InputPort> inputPorts = new HashSet<>();
-    private Set<OutputPort> outputPorts = new HashSet<>();
+    protected Set<InputPort> inputPorts = new HashSet<>();
+    protected Set<OutputPort> outputPorts = new HashSet<>();
 
+    protected Set<InputPort> insideInputPorts = new HashSet<>();
+
+    protected Set<OutputPort> insideOutputPorts = new HashSet<>();
+    protected String name;
 
     public abstract void parse();
 
@@ -46,4 +50,29 @@
         this.outputPorts = outputs;
     }
 
+    public Set<InputPort> getInsideInputPorts() {
+      return insideInputPorts;
+    }
+
+    public void setInsideInputPorts(Set<InputPort> insideInputPorts) {
+      this.insideInputPorts = insideInputPorts;
+    }
+
+    public Set<OutputPort> getInsideOutputPorts() {
+      return insideOutputPorts;
+    }
+
+    public void setInsideOutputPorts(Set<OutputPort> insideOutputPorts) {
+      this.insideOutputPorts = insideOutputPorts;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+
 }
\ No newline at end of file
diff --git a/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/ProcessFactory.java b/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/ProcessFactory.java
index 301d417..6fa5569 100644
--- a/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/ProcessFactory.java
+++ b/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/ProcessFactory.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-package org.apache.taverna.scufl2.cwl;
+package org.apache.taverna.scufl2.cwl.components;
 
 import com.fasterxml.jackson.databind.JsonNode;
 
diff --git a/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/Reference.java b/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/Reference.java
index 9d5d0c0..0adb161 100644
--- a/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/Reference.java
+++ b/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/Reference.java
@@ -17,9 +17,8 @@
  * under the License.
  */
 
-package org.apache.taverna.scufl2.cwl;
+package org.apache.taverna.scufl2.cwl.components;
 
-import com.fasterxml.jackson.databind.JsonNode;
 
 public class Reference extends Process {
 
@@ -27,10 +26,12 @@
 
     public Reference() {
         source = "";
+        name = "";
     }
 
     public Reference(String src) {
         this.source = src;
+        this.name = "";
     }
 
     public void parse() {
diff --git a/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/Step.java b/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/Step.java
index 80ccf03..8ac65c2 100644
--- a/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/Step.java
+++ b/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/Step.java
@@ -17,10 +17,9 @@
  * under the License.
  */
 
-package org.apache.taverna.scufl2.cwl;
+package org.apache.taverna.scufl2.cwl.components;
 
 
-import java.util.ArrayList;
 import java.util.Set;
 import java.util.HashSet;
 
@@ -36,6 +35,7 @@
     public Step() {
         inputs = new HashSet<>();
         outputs = new HashSet<>();
+        id = "";
     }
 
     public String getId() {
@@ -82,4 +82,18 @@
         return "Step " + id + ": run = " + run;
     }
 
+    @Override
+    public boolean equals(Object obj) {
+        if(this == obj) return true;
+        if(obj == null) return false;
+        if(this.getClass() != obj.getClass()) return false;
+
+        Step other = (Step) obj;
+        return other.id.equals(id) && other.run.getName().equals(run.getName()); // && other.inputs == inputs && other.outputs == outputs;
+    }
+
+    @Override
+    public int hashCode() {
+        return id.hashCode() * 13 + run.getName().hashCode() * 17;
+    }
 }
\ No newline at end of file
diff --git a/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/WorkflowProcess.java b/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/WorkflowProcess.java
index a8e6607..617aab6 100644
--- a/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/WorkflowProcess.java
+++ b/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/WorkflowProcess.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-package org.apache.taverna.scufl2.cwl;
+package org.apache.taverna.scufl2.cwl.components;
 
 import java.util.Set;
 import java.util.HashSet;
@@ -30,7 +30,6 @@
 
 import org.apache.taverna.scufl2.api.core.Processor;
 import org.apache.taverna.scufl2.api.core.DataLink;
-import org.apache.taverna.scufl2.api.core.Workflow;
 
 import org.apache.taverna.scufl2.api.port.InputWorkflowPort;
 import org.apache.taverna.scufl2.api.port.OutputWorkflowPort;
@@ -41,6 +40,8 @@
 
 import com.fasterxml.jackson.databind.JsonNode;
 
+import org.apache.taverna.scufl2.cwl.*;
+
 public class WorkflowProcess extends Process {
 
     private CWLParser cwlParser;
@@ -56,8 +57,12 @@
 
     private Converter converter = new Converter();
 
-    public WorkflowProcess(InputStream stream) {
+    public WorkflowProcess() {
+        this.name = "";
+    }
 
+    public WorkflowProcess(InputStream stream) {
+        this();
         Yaml reader = new Yaml();
         ObjectMapper mapper = new ObjectMapper();
         JsonNode node = mapper.valueToTree(reader.load(stream));
@@ -67,6 +72,7 @@
     }
 
     public WorkflowProcess(JsonNode node) {
+        this();
         cwlParser = new CWLParser(node);
         this.parse();
     }
@@ -103,6 +109,8 @@
             Process process = step.getRun();
             process.setInputPorts(step.getInputs());
             process.setOutputPorts(step.getOutputs());
+            insideInputPorts.addAll(step.getInputs());
+            insideOutputPorts.addAll(step.getOutputs());
             result.add(process);
         }
 
diff --git a/taverna-scufl2-cwl/src/test/java/org/apache/taverna/scufl2/cwl/TestConverting.java b/taverna-scufl2-cwl/src/test/java/org/apache/taverna/scufl2/cwl/TestConverting.java
index 2b34a3c..ce57b96 100644
--- a/taverna-scufl2-cwl/src/test/java/org/apache/taverna/scufl2/cwl/TestConverting.java
+++ b/taverna-scufl2-cwl/src/test/java/org/apache/taverna/scufl2/cwl/TestConverting.java
@@ -19,7 +19,7 @@
 package org.apache.taverna.scufl2.cwl;
 
 
-import org.junit.Before;
+import org.apache.taverna.scufl2.api.core.DataLink;
 import org.junit.Test;
 import static org.junit.Assert.assertEquals;
 
@@ -27,12 +27,14 @@
 
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
 
 import org.apache.taverna.scufl2.api.container.WorkflowBundle;
 import org.apache.taverna.scufl2.api.core.Workflow;
 import org.apache.taverna.scufl2.api.core.Processor;
 
+import org.apache.taverna.scufl2.cwl.components.WorkflowProcess;
+import org.apache.taverna.scufl2.cwl.components.ProcessFactory;
+
 public class TestConverting {
     private static final String HELLO_WORLD_CWL = "/hello_world.cwl";
     private static final String WORKFLOW_WITH_COMMAND = "/workflow_with_command.cwl";
@@ -86,5 +88,13 @@
         Processor processor = workflow.getProcessors().iterator().next();
         assertEquals(1, processor.getInputPorts().size());
         assertEquals(0, processor.getOutputPorts().size());
+
+        String processorPortName = processor.getInputPorts().iterator().next().getName();
+        assertEquals("text", processorPortName);
+
+        assertEquals(1, workflow.getDataLinks().size());
+        DataLink dataLink = workflow.getDataLinks().iterator().next();
+        assertEquals("name", dataLink.getReceivesFrom().getName());
+        assertEquals("text", dataLink.getSendsTo().getName());
     }
 }
diff --git a/taverna-scufl2-cwl/src/test/java/org/apache/taverna/scufl2/cwl/TestParser.java b/taverna-scufl2-cwl/src/test/java/org/apache/taverna/scufl2/cwl/TestParser.java
index 20c494c..a4ea204 100644
--- a/taverna-scufl2-cwl/src/test/java/org/apache/taverna/scufl2/cwl/TestParser.java
+++ b/taverna-scufl2-cwl/src/test/java/org/apache/taverna/scufl2/cwl/TestParser.java
@@ -28,10 +28,8 @@
 
 import org.yaml.snakeyaml.Yaml;
 
-import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ArrayNode;
 
 import org.apache.taverna.scufl2.api.core.Workflow;
 import org.apache.taverna.scufl2.api.core.Processor;
@@ -40,7 +38,6 @@
 import org.apache.taverna.scufl2.api.common.NamedSet;
 
 import org.apache.taverna.scufl2.api.port.InputWorkflowPort;
-import org.apache.taverna.scufl2.api.port.OutputWorkflowPort;
 import org.apache.taverna.scufl2.api.port.InputProcessorPort;
 
 
diff --git a/taverna-scufl2-cwl/src/test/java/org/apache/taverna/scufl2/cwl/TestTavernaConverter.java b/taverna-scufl2-cwl/src/test/java/org/apache/taverna/scufl2/cwl/TestTavernaConverter.java
new file mode 100644
index 0000000..14bb8a0
--- /dev/null
+++ b/taverna-scufl2-cwl/src/test/java/org/apache/taverna/scufl2/cwl/TestTavernaConverter.java
@@ -0,0 +1,80 @@
+/*
+ * 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.scufl2.cwl;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.taverna.scufl2.api.core.Processor;
+import org.apache.taverna.scufl2.api.core.Workflow;
+import org.apache.taverna.scufl2.api.port.InputWorkflowPort;
+import org.apache.taverna.scufl2.api.port.OutputWorkflowPort;
+import org.apache.taverna.scufl2.cwl.components.InputPort;
+import org.apache.taverna.scufl2.cwl.components.Reference;
+import org.apache.taverna.scufl2.cwl.components.Step;
+import org.apache.taverna.scufl2.cwl.components.WorkflowProcess;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+
+public class TestTavernaConverter {
+
+    @Test
+    public void testWorkflowToWorkflowProcess() {
+        Workflow workflow = new Workflow();
+        workflow.setName("workflowName");
+        workflow.getInputPorts().add(new InputWorkflowPort(workflow, "input1"));
+        workflow.getInputPorts().add(new InputWorkflowPort(workflow, "input2"));
+        workflow.getOutputPorts().add(new OutputWorkflowPort(workflow, "output"));
+
+        TavernaConverter converter = new TavernaConverter();
+
+        WorkflowProcess workflowProcess = converter.convertWorkflow(workflow);
+        assertEquals(workflow.getInputPorts().size(), workflowProcess.getInputPorts().size());
+        assertEquals(workflow.getOutputPorts().size(), workflowProcess.getOutputPorts().size());
+
+        Set<String> expectedInputNames = workflow.getInputPorts().stream().map(InputWorkflowPort::getName).collect(Collectors.toSet());
+        Set<String> convertedInputNames = workflowProcess.getInputPorts().stream().map(InputPort::getName).collect(Collectors.toSet());
+
+        assertEquals(expectedInputNames, convertedInputNames);
+
+        assertEquals("output", workflowProcess.getOutputPorts().iterator().next().getName());
+    }
+
+    @Test
+    public void testProcessorsToSteps() {
+        Workflow workflow = new Workflow();
+        workflow.setName("workflowName");
+        workflow.getProcessors().add(new Processor(workflow, "processor1"));
+        workflow.getProcessors().add(new Processor(workflow, "processor2"));
+
+        Step step1 = new Step();
+        step1.setRun(new Reference("processor1"));
+        Step step2 = new Step();
+        step2.setRun(new Reference("processor2"));
+        Set<Step> steps = new HashSet<>();
+        steps.add(step1);
+        steps.add(step2);
+
+        TavernaConverter converter = new TavernaConverter();
+        Set<Step> convertedSteps = converter.convertProcessors(workflow);
+
+        assertEquals(steps, convertedSteps);
+    }
+}
diff --git a/taverna-scufl2-cwl/src/test/java/org/apache/taverna/scufl2/cwl/TestWorkflowNesting.java b/taverna-scufl2-cwl/src/test/java/org/apache/taverna/scufl2/cwl/TestWorkflowNesting.java
index d0f3e88..a4ea652 100644
--- a/taverna-scufl2-cwl/src/test/java/org/apache/taverna/scufl2/cwl/TestWorkflowNesting.java
+++ b/taverna-scufl2-cwl/src/test/java/org/apache/taverna/scufl2/cwl/TestWorkflowNesting.java
@@ -19,12 +19,7 @@
 package org.apache.taverna.scufl2.cwl;
 
 
-import java.io.File;
-import java.io.IOException;
 import java.util.Set;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.HashMap;
 
 import org.junit.Test;
 import static org.junit.Assert.assertEquals;
@@ -33,19 +28,13 @@
 
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
 
-import com.fasterxml.jackson.core.JsonProcessingException;
+import org.apache.taverna.scufl2.cwl.components.Process;
+import org.apache.taverna.scufl2.cwl.components.ProcessFactory;
+import org.apache.taverna.scufl2.cwl.components.CommandLineTool;
+import org.apache.taverna.scufl2.cwl.components.WorkflowProcess;
+import org.apache.taverna.scufl2.cwl.components.Reference;
 
-import org.apache.taverna.scufl2.api.core.Workflow;
-
-import org.apache.taverna.scufl2.api.port.InputWorkflowPort;
-import org.apache.taverna.scufl2.api.port.OutputWorkflowPort;
-
-import org.apache.taverna.scufl2.api.io.WorkflowBundleIO;
-import org.apache.taverna.scufl2.api.io.WriterException;
-
-import org.apache.taverna.scufl2.api.container.WorkflowBundle;
 
 public class TestWorkflowNesting {
     private static final String HELLO_WORLD_CWL = "/hello_world.cwl";
diff --git a/taverna-scufl2-cwl/src/test/java/org/apache/taverna/scufl2/cwl/TestWorkflowProcess.java b/taverna-scufl2-cwl/src/test/java/org/apache/taverna/scufl2/cwl/TestWorkflowProcess.java
index 4b3bba7..6ff449c 100644
--- a/taverna-scufl2-cwl/src/test/java/org/apache/taverna/scufl2/cwl/TestWorkflowProcess.java
+++ b/taverna-scufl2-cwl/src/test/java/org/apache/taverna/scufl2/cwl/TestWorkflowProcess.java
@@ -47,6 +47,11 @@
 
 import org.apache.taverna.scufl2.api.container.WorkflowBundle;
 
+import org.apache.taverna.scufl2.cwl.components.Process;
+import org.apache.taverna.scufl2.cwl.components.ProcessFactory;
+import org.apache.taverna.scufl2.cwl.components.WorkflowProcess;
+
+
 public class TestWorkflowProcess {
     private static final String HELLO_WORLD_CWL = "/hello_world.cwl";
     private static final String WORKFLOW_WITH_COMMAND = "/workflow_with_command.cwl";
diff --git a/taverna-scufl2-cwl/src/test/resources/hello_world.cwl b/taverna-scufl2-cwl/src/test/resources/hello_world.cwl
index 4207afa..eee01dd 100644
--- a/taverna-scufl2-cwl/src/test/resources/hello_world.cwl
+++ b/taverna-scufl2-cwl/src/test/resources/hello_world.cwl
@@ -32,6 +32,6 @@
 
     inputs:
       - id: text
-        source: "#x/name"
+        source: "name"
 
     outputs: []
diff --git a/taverna-scufl2-cwl/src/test/resources/workflow_with_workflow.cwl b/taverna-scufl2-cwl/src/test/resources/workflow_with_workflow.cwl
index 58323c5..7abca5e 100644
--- a/taverna-scufl2-cwl/src/test/resources/workflow_with_workflow.cwl
+++ b/taverna-scufl2-cwl/src/test/resources/workflow_with_workflow.cwl
@@ -25,7 +25,7 @@
 outputs:
   download:
     type: File
-    outputSource:  "#step1/curl"
+    outputSource:  "curl"
 
 steps:
   step1:
@@ -40,7 +40,7 @@
           run: example.cwl
           inputs:
             - id: text
-              source: "#x/name"
+              source: "name"
           outputs: []
     in:
       text: message