Add main parser that parses the structure of a CWL workflow
Project: http://git-wip-us.apache.org/repos/asf/incubator-taverna-language/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-taverna-language/commit/4ee2f5bc Tree: http://git-wip-us.apache.org/repos/asf/incubator-taverna-language/tree/4ee2f5bc Diff: http://git-wip-us.apache.org/repos/asf/incubator-taverna-language/diff/4ee2f5bc Branch: refs/heads/cwlparser Commit: 4ee2f5bc021c236aea248b0917a57d00b4d6ae66 Parents: 881a409 Author: Majdi Haouech <[email protected]> Authored: Mon Jun 11 16:52:26 2018 +0200 Committer: Majdi Haouech <[email protected]> Committed: Mon Jun 11 16:52:26 2018 +0200 ---------------------------------------------------------------------- .../taverna/scufl2/cwl/WorkflowParser.java | 232 +++++++++++++++++++ .../scufl2/cwl/components/PortDetail.java | 12 +- 2 files changed, 243 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-taverna-language/blob/4ee2f5bc/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/WorkflowParser.java ---------------------------------------------------------------------- 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 new file mode 100644 index 0000000..f0f6b2a --- /dev/null +++ b/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/WorkflowParser.java @@ -0,0 +1,232 @@ +/* + * 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.io.*; +import java.util.*; + +import java.lang.NullPointerException; + +import org.yaml.snakeyaml.Yaml; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + + +import org.apache.taverna.scufl2.api.core.Workflow; +import org.apache.taverna.scufl2.api.core.Processor; +import org.apache.taverna.scufl2.api.core.DataLink; + +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 org.apache.taverna.scufl2.api.port.SenderPort; +import org.apache.taverna.scufl2.api.port.ReceiverPort; +import org.apache.taverna.scufl2.api.container.WorkflowBundle; + +import org.apache.taverna.scufl2.api.io.WorkflowBundleIO; +import org.apache.taverna.scufl2.api.io.WriterException; + +public class WorkflowParser { + + private static final String FILE_NAME = "/hello_world.cwl"; + private CWLParser cwlParser; + private Converter converter; + + private Map<String, InputWorkflowPort> workflowInputs; + private Map<String, OutputWorkflowPort> workflowOutputs; + private Map<String, Processor> workflowProcessors; + private Map<String, InputProcessorPort> processorInputs; + private Map<String, OutputProcessorPort> processorOutputs; + private Set<DataLink> dataLinks; + + public WorkflowParser() { + Yaml reader = new Yaml(); + ObjectMapper mapper = new ObjectMapper(); + JsonNode cwlFile = mapper.valueToTree(reader.load(WorkflowParser.class.getResourceAsStream(FILE_NAME))); + this.cwlParser = new CWLParser(cwlFile); + this.converter = new Converter(); + } + + public WorkflowParser(JsonNode cwlFile) { + this.cwlParser = new CWLParser(cwlFile); + this.converter = new Converter(); + workflowInputs = new HashMap<>(); + workflowOutputs = new HashMap<>(); + workflowProcessors = new HashMap<>(); + processorInputs = new HashMap<>(); + processorOutputs = new HashMap<>(); + dataLinks = new HashSet<DataLink>(); + } + + public Workflow buildWorkflow() { + parseInputs(); + parseOutputs(); + Set<Step> cwlSteps = cwlParser.parseSteps(); + parseProcessors(cwlSteps); + parseDataLinks(cwlSteps); + + Workflow workflow = new Workflow(); + Set<InputWorkflowPort> inputs = new HashSet<>(workflowInputs.values()); + Set<OutputWorkflowPort> outputs = new HashSet<>(workflowOutputs.values()); + Set<Processor> processors = new HashSet<>(workflowProcessors.values()); + + workflow.setInputPorts(inputs); + workflow.setOutputPorts(outputs); + workflow.setProcessors(processors); + workflow.setDataLinks(dataLinks); + +// writeWorkflowToFile(workflow); + + return workflow; + } + + public void writeWorkflowToFile(Workflow workflow) { + try { + WorkflowBundleIO io = new WorkflowBundleIO(); + File scufl2File = new File("workflow.wfbundle"); + WorkflowBundle bundle = io.createBundle(); + Set<Workflow> workflowSet = new HashSet<>(); + workflowSet.add(workflow); + bundle.setWorkflows(workflowSet); + bundle.setMainWorkflow(workflow); + io.writeBundle(bundle, scufl2File, "application/vnd.taverna.scufl2.workflow-bundle"); + } catch(WriterException e) { + System.out.println("Exception writing the workflow bundle"); + } catch(IOException e) { + System.out.println("IOException"); + } + } + + public void parseInputs() { + Set<PortDetail> cwlInputs = cwlParser.parseInputs(); + if(cwlInputs != null) { + for (PortDetail port : cwlInputs) { + String portId = port.getId(); + InputWorkflowPort workflowPort = converter.convertInputWorkflowPort(port); + workflowInputs.put(portId, workflowPort); + } + } + } + + public void parseOutputs() { + Set<PortDetail> cwlOutputs = cwlParser.parseOutputs(); + for(PortDetail port: cwlOutputs) { + String portId = port.getId(); + OutputWorkflowPort workflowPort = converter.convertOutputWorkflowPort(port); + workflowOutputs.put(portId, workflowPort); + } + } + + public void parseProcessors(Set<Step> cwlSteps) { + for(Step step: cwlSteps) { + Processor processor = converter.convertStepToProcessor(step); + workflowProcessors.put(step.getId(), processor); + + DataLink datalink = new DataLink(); + for(StepInput stepInput: step.getInputs()) { + InputProcessorPort processorPort = new InputProcessorPort(processor, stepInput.getId()); + processorInputs.put(stepInput.getId(), processorPort); + } + for(StepOutput stepOutput: step.getOutputs()) { + OutputProcessorPort processorPort = new OutputProcessorPort(processor, stepOutput.getId()); + processorOutputs.put(stepOutput.getId(), processorPort); + } + } + } + + public void parseDataLinks(Set<Step> cwlSteps) { + for(Step step: cwlSteps) { + for(StepInput stepInput: step.getInputs()) { + String[] sourcePath = stepInput.getSource().split("/"); + String source = sourcePath[sourcePath.length-1]; + source = source.replace("#", ""); + + DataLink dataLink = new DataLink(); + SenderPort sender = workflowInputs.get(source); + if(sender == null) { + sender = processorOutputs.get(source); + } + if(sender == null) { + throw new NullPointerException("Cannot find sender port with name: " + source); + } + String receiverId = stepInput.getId(); + ReceiverPort receiver = workflowOutputs.get(receiverId); + if(receiver == null) { + receiver = processorInputs.get(receiverId); + } + if(receiver == null) { + throw new NullPointerException("Cannot find receiver port with name: " + receiverId); + } + dataLink.setSendsTo(receiver); + dataLink.setReceivesFrom(sender); + dataLinks.add(dataLink); + } + } + } + + public Map<String, InputWorkflowPort> getWorkflowInputs() { + return workflowInputs; + } + + public void setWorkflowInputs(Map<String, InputWorkflowPort> workflowInputs) { + this.workflowInputs = workflowInputs; + } + + public Map<String, OutputWorkflowPort> getWorkflowOutputs() { + return workflowOutputs; + } + + public void setWorkflowOutputs(Map<String, OutputWorkflowPort> workflowOutputs) { + this.workflowOutputs = workflowOutputs; + } + + public Map<String, Processor> getWorkflowProcessors() { + return workflowProcessors; + } + + public void setWorkflowProcessors(Map<String, Processor> workflowProcessors) { + this.workflowProcessors = workflowProcessors; + } + + public Map<String, InputProcessorPort> getProcessorInputs() { + return processorInputs; + } + + public void setProcessorInputs(Map<String, InputProcessorPort> processorInputs) { + this.processorInputs = processorInputs; + } + + public Map<String, OutputProcessorPort> getProcessorOutputs() { + return processorOutputs; + } + + public void setProcessorOutputs(Map<String, OutputProcessorPort> processorOutputs) { + this.processorOutputs = processorOutputs; + } + + public Set<DataLink> getDataLinks() { + return dataLinks; + } + + public void setDataLinks(Set<DataLink> dataLinks) { + this.dataLinks = dataLinks; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-taverna-language/blob/4ee2f5bc/taverna-scufl2-cwl/src/main/java/org/apache/taverna/scufl2/cwl/components/PortDetail.java ---------------------------------------------------------------------- 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 563c76f..53604e7 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 @@ -25,11 +25,21 @@ import java.util.ArrayList; public class PortDetail { - private String label; + private String id; + private String label; private int depth; private String description; private ArrayList<String> format; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + public int getDepth() { return depth; }
