Fix conflicts and merge branch 'cwlparser' into cwl
diff --git a/README.md b/README.md
index 0e332d2..6d5ae2f 100644
--- a/README.md
+++ b/README.md
@@ -97,6 +97,7 @@
 
 Experimental modules:
 
+* [taverna-scufl2-cwl](taverna-scufl2-cwl/) Load/save [Common Workflow Language](https://www.commonwl.org/)
 * [taverna-scufl2-scufl](taverna-scufl2-scufl/) Load Taverna 1 `.xml` workflows (SCUFL 1)
 * [taverna-scufl2-annotation](taverna-scufl2-annotation/) Annotation utillity functions
 * [taverna-baclava-language](taverna-baclava-language) Load Taverna 2 data documents (workflow inputs/outputs)
diff --git a/pom.xml b/pom.xml
index 44dc74f..8c813ba 100644
--- a/pom.xml
+++ b/pom.xml
@@ -309,6 +309,7 @@
       <module>taverna-scufl2-wfbundle</module>
       <module>taverna-tavlang-tool</module>
       <module>taverna-scufl2-wfdesc</module>
+      <module>taverna-scufl2-cwl</module>
     </modules>
   </profile>
   <profile>
diff --git a/taverna-scufl2-cwl/pom.xml b/taverna-scufl2-cwl/pom.xml
index 3b11dff..0f76ffd 100644
--- a/taverna-scufl2-cwl/pom.xml
+++ b/taverna-scufl2-cwl/pom.xml
@@ -48,6 +48,12 @@
     </dependency>
 
     <dependency>
+      <groupId>com.fasterxml.jackson.dataformat</groupId>
+      <artifactId>jackson-dataformat-yaml</artifactId>
+      <version>${jackson.version}</version>
+    </dependency>
+
+    <dependency>
       <groupId>org.yaml</groupId>
       <artifactId>snakeyaml</artifactId>
       <version>1.17</version>
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 b607190..eff7ef6 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
@@ -32,11 +32,15 @@
 import org.apache.taverna.scufl2.api.port.OutputProcessorPort;
 
 import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
 
 public class Converter {
 
+    private JsonNodeFactory jsonNodeFactory;
     public Converter() {
-
+        jsonNodeFactory = JsonNodeFactory.instance;
     }
 
     public InputWorkflowPort convertInputWorkflowPort(PortDetail input) {
@@ -75,4 +79,87 @@
 
         return processor;
     }
+
+    public JsonNode convertWorkflowProcessToJsonNode(WorkflowProcess workflow) {
+        Map<String, Processor> workflowProcessors = workflow.getWorkflowProcessors();
+        Map<String, InputProcessorPort> processorInputs = workflow.getProcessorInputs();
+        Map<String, OutputProcessorPort> processorOutputs = workflow.getProcessorOutputs();
+
+        ObjectNode result = jsonNodeFactory.objectNode();
+        ObjectNode inputs = convertInputWorkflows(workflow.getWorkflowInputs());
+        ObjectNode outputs = convertOutputWorkflows(workflow.getWorkflowOutputs());
+        ObjectNode steps = convertProcessors(workflow);
+        result.put("inputs", inputs);
+        result.put("outputs", outputs);
+        result.put("steps", steps);
+
+        return result;
+    }
+
+    private ObjectNode convertInputWorkflows(Map<String, InputWorkflowPort> workflowInputs) {
+        ObjectNode node = jsonNodeFactory.objectNode();
+        for(Map.Entry<String, InputWorkflowPort> entry: workflowInputs.entrySet()) {
+            String name = entry.getKey();
+            node.put(name, "string");  // TODO: Put the correct input type and not just string
+        }
+
+        return node;
+    }
+
+    private ObjectNode convertOutputWorkflows(Map<String, OutputWorkflowPort> workflowOutputs) {
+        ObjectNode node = jsonNodeFactory.objectNode();
+        for(Map.Entry<String, OutputWorkflowPort> entry: workflowOutputs.entrySet()) {
+            String name = entry.getKey();
+            node.put(name, "string");  // TODO: Put the correct input type and not just string
+        }
+
+        return node;
+    }
+
+    private ObjectNode convertProcessors(WorkflowProcess workflow) {
+        ObjectNode node = jsonNodeFactory.objectNode();
+        Map<String, Processor> processors = workflow.getWorkflowProcessors();
+
+        for(Map.Entry<String, Processor> entry: processors.entrySet()) {
+            Processor processor = entry.getValue();
+            ObjectNode step = jsonNodeFactory.objectNode();
+            ArrayNode inputs = jsonNodeFactory.arrayNode();
+            ArrayNode outputs = jsonNodeFactory.arrayNode();
+            for(InputProcessorPort port: processor.getInputPorts()) {
+                ObjectNode input = jsonNodeFactory.objectNode();
+                input.put(port.getName(), "string");
+                input.put("source", "");
+                inputs.add(input);
+            }
+            for(OutputProcessorPort port: processor.getOutputPorts()) {
+                ObjectNode output = jsonNodeFactory.objectNode();
+                output.put(port.getName(), "string");
+                outputs.add(output);
+            }
+            step.put("run", "NotImplemented");
+            step.put("inputs", inputs);
+            step.put("outputs", outputs);
+            node.put(processor.getName(), step);
+        }
+
+        return node;
+    }
+
+    public PortDetail convertToPortDetail(InputWorkflowPort inPort) {
+        int depth = inPort.getDepth();
+        String id = inPort.getName();
+        PortDetail port = new PortDetail();
+        port.setId(id);
+        port.setDepth(depth);
+
+        return port;
+    }
+
+    public PortDetail convertToPortDetail(OutputWorkflowPort outPort) {
+        String id = outPort.getName();
+        PortDetail port = new PortDetail();
+        port.setId(id);
+
+        return port;
+    }
 }
\ No newline at end of file
diff --git a/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/Main.java b/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/Main.java
new file mode 100644
index 0000000..e5f7159
--- /dev/null
+++ b/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/Main.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.scufl2.cwl;
+
+import org.yaml.snakeyaml.Yaml;
+
+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;
+
+public class Main {
+
+    private static final String HELLO_WORLD_CWL = "/hello_world.cwl";
+    private static final String WORKFLOW_WITH_COMMAND = "/workflow_with_command.cwl";
+    private static JsonNode cwlFile;
+
+    public static void main(String[] args) {
+
+        Yaml reader = new Yaml();
+        ObjectMapper mapper = new ObjectMapper();
+        cwlFile = mapper.valueToTree(reader.load(Main.class.getResourceAsStream(WORKFLOW_WITH_COMMAND)));
+        System.out.println(cwlFile);
+
+        Process workflow = ProcessFactory.createProcess(cwlFile);
+        workflow.parse();
+        Converter converter = new Converter();
+        JsonNode node = converter.convertWorkflowProcessToJsonNode((WorkflowProcess) workflow);
+        printAsYaml(node);
+    }
+
+    private static void printAsYaml(JsonNode node) {
+        try {
+            String yaml = new YAMLMapper().writeValueAsString(node);
+            System.out.println("YAML DATA");
+            System.out.println(yaml);
+        } catch (JsonProcessingException e) {
+            System.err.println("Error writing JsonNode to YAML");
+        }
+    }
+}
\ No newline at end of file
diff --git a/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/Main.java b/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/Main.java
deleted file mode 100644
index e69de29..0000000
--- a/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/Main.java
+++ /dev/null
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 b8902e7..481c93f 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
@@ -19,6 +19,8 @@
 
 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;
@@ -29,6 +31,7 @@
 import org.apache.taverna.scufl2.api.core.DataLink;
 import org.apache.taverna.scufl2.api.core.Workflow;
 
+import org.apache.taverna.scufl2.api.container.WorkflowBundle;
 import org.apache.taverna.scufl2.api.port.InputWorkflowPort;
 import org.apache.taverna.scufl2.api.port.OutputWorkflowPort;
 import org.apache.taverna.scufl2.api.port.InputProcessorPort;
@@ -36,6 +39,9 @@
 import org.apache.taverna.scufl2.api.port.SenderPort;
 import org.apache.taverna.scufl2.api.port.ReceiverPort;
 
+import org.apache.taverna.scufl2.api.io.WorkflowBundleIO;
+import org.apache.taverna.scufl2.api.io.WriterException;
+
 import com.fasterxml.jackson.databind.JsonNode;
 
 public class WorkflowProcess implements Process {
@@ -71,7 +77,7 @@
         workflow.setInputPorts(inputs);
         workflow.setOutputPorts(outputs);
         workflow.setProcessors(processors);
-        workflow.setDataLinks(dataLinks);
+
 
 //        System.out.println("DEBUG WORKFLOW");
 //        System.out.println(workflow.getInputPorts());
@@ -79,7 +85,6 @@
 //        System.out.println(workflow.getProcessors());
 
     }
-
     public void parseInputs() {
         Set<PortDetail> cwlInputs = cwlParser.parseInputs();
         for (PortDetail port: cwlInputs) {
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 10604b1..97d944f 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
@@ -18,8 +18,12 @@
  */
 package org.apache.taverna.scufl2.cwl;
 
+<<<<<<< HEAD
+
+=======
 import java.io.File;
 import java.io.IOException;
+>>>>>>> 87fa1c18d2b7aa210db3d238905234bf4f52b491
 import java.util.Set;
 import java.util.HashSet;
 import java.util.Map;
@@ -46,11 +50,14 @@
 import org.apache.taverna.scufl2.api.port.OutputWorkflowPort;
 import org.apache.taverna.scufl2.api.port.InputProcessorPort;
 
+<<<<<<< HEAD
+=======
 import org.apache.taverna.scufl2.api.io.WorkflowBundleIO;
 import org.apache.taverna.scufl2.api.io.WriterException;
 
 import org.apache.taverna.scufl2.api.container.WorkflowBundle;
 
+>>>>>>> 87fa1c18d2b7aa210db3d238905234bf4f52b491
 
 public class TestWorkflowProcess {
     private static final String HELLO_WORLD_CWL = "/hello_world.cwl";
@@ -98,6 +105,10 @@
     @Test
     public void testWorkflowSteps() {
         cwlFile = loadYamlFile(WORKFLOW_WITH_COMMAND);
+<<<<<<< HEAD
+        WorkflowProcess workflow = new WorkflowProcess(cwlFile);
+
+=======
         Process workflow = ProcessFactory.createProcess(cwlFile);
 
         assert(workflow instanceof WorkflowProcess);
@@ -118,6 +129,7 @@
         } catch(IOException e) {
             System.out.println("IOException");
         }
+>>>>>>> 87fa1c18d2b7aa210db3d238905234bf4f52b491
     }
 
 }
diff --git a/taverna-scufl2-cwl/taverna-scufl2-cwl.iml b/taverna-scufl2-cwl/taverna-scufl2-cwl.iml
new file mode 100644
index 0000000..788bb17
--- /dev/null
+++ b/taverna-scufl2-cwl/taverna-scufl2-cwl.iml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <exclude-output />
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/src2" isTestSource="false" />
+    </content>
+    <orderEntry type="jdk" jdkName="1.8" jdkType="JavaSDK" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/taverna-scufl2-cwl/workflow.t2flow.txt b/taverna-scufl2-cwl/workflow.t2flow.txt
new file mode 100644
index 0000000..59ce3fb
--- /dev/null
+++ b/taverna-scufl2-cwl/workflow.t2flow.txt
@@ -0,0 +1,10 @@
+WorkflowBundle 'bundle1'
+  MainWorkflow 'cdba0a80-366b-4f66-8f26-85e882d41eed'
+  Workflow 'cdba0a80-366b-4f66-8f26-85e882d41eed'
+    In 'name'
+    Processor 'step1'
+      In 'text'
+    Links
+      'name' -> 'step1:text'
+  MainProfile 'profile1'
+  Profile 'profile1'
diff --git a/taverna-scufl2-cwl/workflow.vnd.taverna.scufl2.structure.txt b/taverna-scufl2-cwl/workflow.vnd.taverna.scufl2.structure.txt
new file mode 100644
index 0000000..e8b6430
--- /dev/null
+++ b/taverna-scufl2-cwl/workflow.vnd.taverna.scufl2.structure.txt
Binary files differ
diff --git a/taverna-scufl2-cwl/workflow.wfbundle b/taverna-scufl2-cwl/workflow.wfbundle
new file mode 100644
index 0000000..e2c6d40
--- /dev/null
+++ b/taverna-scufl2-cwl/workflow.wfbundle
@@ -0,0 +1,10 @@
+WorkflowBundle 'bundle1'
+  MainWorkflow '6ce2e3b6-39b1-4773-8aee-e74cccb7ca7d'
+  Workflow '6ce2e3b6-39b1-4773-8aee-e74cccb7ca7d'
+    In 'name'
+    Processor 'step1'
+      In 'text'
+    Links
+      'name' -> 'step1:text'
+  MainProfile 'profile1'
+  Profile 'profile1'