blob: 5637ced2a59027bdcd27e5afe03ca98e1d331971 [file] [log] [blame]
/*
* 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.Set;
import java.util.HashSet;
import java.util.Map;
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;
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 com.fasterxml.jackson.databind.node.ObjectNode;
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.*;
public class Converter {
private JsonNodeFactory jsonNodeFactory;
public Converter() {
jsonNodeFactory = JsonNodeFactory.instance;
}
public InputWorkflowPort convertInputWorkflowPort(PortDetail input) {
InputWorkflowPort port = new InputWorkflowPort();
port.setName(input.getId());
port.setDepth(input.getDepth());
return port;
}
public OutputWorkflowPort convertOutputWorkflowPort(PortDetail input) {
OutputWorkflowPort port = new OutputWorkflowPort();
port.setName(input.getId());
return port;
}
public Processor convertStepToProcessor(Step step) {
Processor processor = new Processor(null, step.getId());
// Convert input ports
Set<InputProcessorPort> processorInputs = new HashSet<>();
Set<InputPort> inputs = step.getInputs();
for(InputPort input: inputs) {
InputProcessorPort port = new InputProcessorPort(processor, input.getName());
processorInputs.add(port);
}
processor.setInputPorts(processorInputs);
// Convert output ports
Set<OutputProcessorPort> processorOutputs = new HashSet<>();
Set<OutputPort> outputs = step.getOutputs();
for(OutputPort output: outputs) {
OutputProcessorPort port = new OutputProcessorPort(processor, output.getName());
processorOutputs.add(port);
}
processor.setOutputPorts(processorOutputs);
return processor;
}
public JsonNode convertWorkflowProcessToJsonNode(WorkflowProcess workflow) {
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;
}
public WorkflowBundle buildWorkflowBundle(Process process) {
WorkflowBundle bundle = new WorkflowBundle();
if(!(process instanceof WorkflowProcess)) {
throw new UnsupportedOperationException("WorkflowBundle is not created without an initial workflow yet");
}
Workflow workflow = convertWorkflowProcess((WorkflowProcess) process, bundle);
workflow.setParent(bundle);
return bundle;
}
public Workflow convertWorkflowProcess(WorkflowProcess workflowProcess, WorkflowBundle bundle) {
Workflow workflow = new Workflow();
Set<InputWorkflowPort> inputs = new HashSet<>(workflowProcess.getWorkflowInputs().values());
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 = convertCommandLineTool((CommandLineTool) process);
workflow.getProcessors().add(processor);
} else {
assert(process instanceof Reference);
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());
processor.setInputPorts(convertInputProcessPorts(command.getInputPorts()));
processor.setOutputPorts(convertOutputProcessPorts(command.getOutputPorts()));
return processor;
}
public Processor convertReference(Reference reference) {
Processor processor = new Processor(null, reference.getSource());
processor.setInputPorts(convertInputProcessPorts(reference.getInputPorts()));
processor.setOutputPorts(convertOutputProcessPorts(reference.getOutputPorts()));
return processor;
}
public Set<InputProcessorPort> convertInputProcessPorts(Set<InputPort> inputPorts) {
Set<InputProcessorPort> processorInputPorts = new HashSet<>();
for(InputPort port: inputPorts) {
processorInputPorts.add(new InputProcessorPort(null, port.getName()));
}
return processorInputPorts;
}
public Set<OutputProcessorPort> convertOutputProcessPorts(Set<OutputPort> outputPorts) {
Set<OutputProcessorPort> processorOutputPorts = new HashSet<>();
for(OutputPort port: outputPorts) {
processorOutputPorts.add(new OutputProcessorPort(null, port.getName()));
}
return processorOutputPorts;
}
}