Java tutorial
package org.apache.taverna.scufl2.wfdesc; /* * * 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. * */ import static org.apache.taverna.scufl2.api.common.Scufl2Tools.NESTED_WORKFLOW; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URI; import java.net.URISyntaxException; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.jena.ontology.Individual; import org.apache.jena.ontology.OntModel; import org.apache.jena.rdf.model.ModelFactory; import org.apache.jena.rdf.model.Resource; import org.apache.jena.riot.Lang; import org.apache.jena.riot.RDFDataMgr; import org.apache.jena.riot.RiotException; import org.apache.jena.vocabulary.OWL; import org.apache.taverna.scufl2.api.activity.Activity; import org.apache.taverna.scufl2.api.annotation.Annotation; import org.apache.taverna.scufl2.api.common.Child; import org.apache.taverna.scufl2.api.common.Named; import org.apache.taverna.scufl2.api.common.Scufl2Tools; import org.apache.taverna.scufl2.api.common.URITools; import org.apache.taverna.scufl2.api.common.Visitor.VisitorWithPath; import org.apache.taverna.scufl2.api.common.WorkflowBean; import org.apache.taverna.scufl2.api.configurations.Configuration; import org.apache.taverna.scufl2.api.container.WorkflowBundle; 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.io.WriterException; import org.apache.taverna.scufl2.api.port.InputPort; import org.apache.taverna.scufl2.api.port.OutputPort; import org.apache.taverna.scufl2.api.port.WorkflowPort; import org.apache.taverna.scufl2.api.profiles.ProcessorBinding; import org.apache.taverna.scufl2.api.profiles.ProcessorPortBinding; import org.apache.taverna.scufl2.api.profiles.Profile; import org.apache.taverna.scufl2.wfdesc.ontologies.Prov_o; import org.apache.taverna.scufl2.wfdesc.ontologies.Roterms; import org.apache.taverna.scufl2.wfdesc.ontologies.Wf4ever; import org.apache.taverna.scufl2.wfdesc.ontologies.Wfdesc; import com.fasterxml.jackson.databind.JsonNode; public class WfdescSerialiser { private static Logger logger = Logger.getLogger(WfdescSerialiser.class.getCanonicalName()); public static URI REST = URI.create("http://ns.taverna.org.uk/2010/activity/rest"); public static URI WSDL = URI.create("http://ns.taverna.org.uk/2010/activity/wsdl"); public static URI SECURITY = WSDL.resolve("wsdl/security"); public static URI OPERATION = WSDL.resolve("wsdl/operation"); public static URI BEANSHELL = URI.create("http://ns.taverna.org.uk/2010/activity/beanshell"); public static URI RSHELL = URI.create("http://ns.taverna.org.uk/2010/activity/rshell"); public static URI TOOL = URI.create("http://ns.taverna.org.uk/2010/activity/tool"); private Scufl2Tools scufl2Tools = new Scufl2Tools(); private URITools uriTools = new URITools(); public Scufl2Tools getScufl2Tools() { return scufl2Tools; } public URITools getUriTools() { return uriTools; } private String uriForBean(WorkflowBean bean) { return uriTools.uriForBean(bean).toASCIIString(); } protected OntModel save(final WorkflowBundle bundle) { final OntModel model = ModelFactory.createOntologyModel(); bundle.accept(new VisitorWithPath() { Scufl2Tools scufl2Tools = new Scufl2Tools(); public boolean visit() { WorkflowBean node = getCurrentNode(); // System.out.println(node); if (node instanceof WorkflowBundle) { return true; } // @SuppressWarnings("rawtypes") if (node instanceof org.apache.taverna.scufl2.api.core.Workflow) { entityForBean(node, Wfdesc.Workflow); } else if (node instanceof Processor) { Processor processor = (Processor) node; Individual process = entityForBean(processor, Wfdesc.Process); Individual wf = entityForBean(processor.getParent(), Wfdesc.Workflow); wf.addProperty(Wfdesc.hasSubProcess, process); } else if (node instanceof InputPort) { WorkflowBean parent = ((Child) node).getParent(); Individual input = entityForBean(node, Wfdesc.Input); Individual process = entityForBean(parent, Wfdesc.Process); process.addProperty(Wfdesc.hasInput, input); } else if (node instanceof OutputPort) { WorkflowBean parent = ((Child) node).getParent(); Individual output = entityForBean(node, Wfdesc.Output); Individual process = entityForBean(parent, Wfdesc.Process); process.addProperty(Wfdesc.hasOutput, output); } else if (node instanceof DataLink) { WorkflowBean parent = ((Child) node).getParent(); DataLink link = (DataLink) node; Individual dl = entityForBean(link, Wfdesc.DataLink); Individual source = entityForBean(link.getReceivesFrom(), Wfdesc.Output); dl.addProperty(Wfdesc.hasSource, source); Individual sink = entityForBean(link.getSendsTo(), Wfdesc.Input); dl.addProperty(Wfdesc.hasSink, sink); Individual wf = entityForBean(parent, Wfdesc.Workflow); wf.addProperty(Wfdesc.hasDataLink, dl); } else if (node instanceof Profile) { // So that we can get at the ProcessorBinding - buy only if // it is the main Profile return node == bundle.getMainProfile(); } else if (node instanceof ProcessorBinding) { ProcessorBinding b = (ProcessorBinding) node; Activity a = b.getBoundActivity(); Processor boundProcessor = b.getBoundProcessor(); Individual process = entityForBean(boundProcessor, Wfdesc.Process); // Note: We don't describe the activity and processor // binding in wfdesc. Instead we // assign additional types and attributes to the parent // processor try { URI type = a.getType(); Configuration c = scufl2Tools.configurationFor(a, b.getParent()); JsonNode json = c.getJson(); if (type.equals(BEANSHELL)) { process.addRDFType(Wf4ever.BeanshellScript); String s = json.get("script").asText(); process.addProperty(Wf4ever.script, s); JsonNode localDep = json.get("localDependency"); if (localDep != null && localDep.isArray()) { for (int i = 0; i < localDep.size(); i++) { String depStr = localDep.get(i).asText(); // FIXME: Better class for dependency? Individual dep = model.createIndividual(OWL.Thing); dep.addLabel(depStr, null); dep.addComment("JAR dependency", "en"); process.addProperty(Roterms.requiresSoftware, dep); // Somehow this gets the whole thing to fall // out of the graph! // QName depQ = new // QName("http://google.com/", ""+ // UUID.randomUUID()); // sesameManager.rename(dep, depQ); } } } if (type.equals(RSHELL)) { process.addRDFType(Wf4ever.RScript); String s = json.get("script").asText(); process.addProperty(Wf4ever.script, s); } if (type.equals(WSDL)) { process.addRDFType(Wf4ever.SOAPService); JsonNode operation = json.get("operation"); URI wsdl = URI.create(operation.get("wsdl").asText()); process.addProperty(Wf4ever.wsdlURI, wsdl.toASCIIString()); process.addProperty(Wf4ever.wsdlOperationName, operation.get("name").asText()); process.addProperty(Wf4ever.rootURI, wsdl.resolve("/").toASCIIString()); } if (type.equals(REST)) { process.addRDFType(Wf4ever.RESTService); // System.out.println(json); JsonNode request = json.get("request"); String absoluteURITemplate = request.get("absoluteURITemplate").asText(); String uriTemplate = absoluteURITemplate.replace("{", ""); uriTemplate = uriTemplate.replace("}", ""); // TODO: Detect {} try { URI root = new URI(uriTemplate).resolve("/"); process.addProperty(Wf4ever.rootURI, root.toASCIIString()); } catch (URISyntaxException e) { logger.warning("Potentially invalid URI template: " + absoluteURITemplate); // Uncomment to temporarily break // TestInvalidURITemplate: // rest.getWfRootURI().add(URI.create("http://example.com/FRED")); } } if (type.equals(TOOL)) { process.addRDFType(Wf4ever.CommandLineTool); JsonNode desc = json.get("toolDescription"); // System.out.println(json); JsonNode command = desc.get("command"); if (command != null) { process.addProperty(Wf4ever.command, command.asText()); } } if (type.equals(NESTED_WORKFLOW)) { Workflow nestedWf = scufl2Tools.nestedWorkflowForProcessor(boundProcessor, b.getParent()); // The parent process is a specialization of the // nested workflow // (because the nested workflow could exist as // several processors) specializationOf(boundProcessor, nestedWf); process.addRDFType(Wfdesc.Workflow); // Just like the Processor specializes the nested // workflow, the // ProcessorPorts specialize the WorkflowPort for (ProcessorPortBinding portBinding : b.getInputPortBindings()) { // Map from activity port (not in wfdesc) to // WorkflowPort WorkflowPort wfPort = nestedWf.getInputPorts() .getByName(portBinding.getBoundActivityPort().getName()); if (wfPort == null) { continue; } specializationOf(portBinding.getBoundProcessorPort(), wfPort); } for (ProcessorPortBinding portBinding : b.getOutputPortBindings()) { WorkflowPort wfPort = nestedWf.getOutputPorts() .getByName(portBinding.getBoundActivityPort().getName()); if (wfPort == null) { continue; } specializationOf(portBinding.getBoundProcessorPort(), wfPort); } } } catch (IndexOutOfBoundsException ex) { } return false; } else { // System.out.println("--NO!"); return false; } for (Annotation ann : scufl2Tools.annotationsFor(node, bundle)) { String annotationBody = ann.getBody().toASCIIString(); String baseURI = bundle.getGlobalBaseURI().resolve(ann.getBody()).toASCIIString(); InputStream annotationStream; try { annotationStream = bundle.getResources().getResourceAsInputStream(annotationBody); try { // FIXME: Don't just assume Lang.TURTLE RDFDataMgr.read(model, annotationStream, baseURI, Lang.TURTLE); } catch (RiotException e) { logger.log(Level.WARNING, "Can't parse RDF Turtle from " + annotationBody, e); } finally { annotationStream.close(); } } catch (IOException e) { logger.log(Level.WARNING, "Can't read " + annotationBody, e); } } if (node instanceof Named) { Named named = (Named) node; entityForBean(node, OWL.Thing).addLabel(named.getName(), null); } return true; } private void specializationOf(WorkflowBean special, WorkflowBean general) { Individual specialEnt = entityForBean(special, Prov_o.Entity); Individual generalEnt = entityForBean(general, Prov_o.Entity); specialEnt.addProperty(Prov_o.specializationOf, generalEnt); } private Individual entityForBean(WorkflowBean bean, Resource thing) { return model.createIndividual(uriForBean(bean), thing); } // @Override // public boolean visitEnter(WorkflowBean node) { // if (node instanceof Processor // || node instanceof org.apache.taverna.scufl2.api.core.Workflow // || node instanceof Port || node instanceof DataLink) { // visit(node); // return true; // } // // The other node types (e.g. dispatch stack, configuration) are // // not (directly) represented in wfdesc //// System.out.println("Skipping " + node); // return false; // }; }); return model; } public void save(WorkflowBundle wfBundle, OutputStream output) throws WriterException { OntModel model; final URI baseURI; if (wfBundle.getMainWorkflow() != null) { Workflow mainWorkflow = wfBundle.getMainWorkflow(); baseURI = uriTools.uriForBean(mainWorkflow); model = save(wfBundle); } else { throw new WriterException("wfdesc format requires a main workflow"); } model.setNsPrefix("rdfs", "http://www.w3.org/2000/01/rdf-schema#"); model.setNsPrefix("xsd", "http://www.w3.org/2001/XMLSchema#"); model.setNsPrefix("owl", "http://www.w3.org/2002/07/owl#"); model.setNsPrefix("prov", "http://www.w3.org/ns/prov#"); model.setNsPrefix("wfdesc", "http://purl.org/wf4ever/wfdesc#"); model.setNsPrefix("wf4ever", "http://purl.org/wf4ever/wf4ever#"); model.setNsPrefix("roterms", "http://purl.org/wf4ever/roterms#"); model.setNsPrefix("dc", "http://purl.org/dc/elements/1.1/"); model.setNsPrefix("dcterms", "http://purl.org/dc/terms/"); model.setNsPrefix("comp", "http://purl.org/DP/components#"); model.setNsPrefix("dep", "http://scape.keep.pt/vocab/dependencies#"); model.setNsPrefix("biocat", "http://biocatalogue.org/attribute/"); model.setNsPrefix("", "#"); try { model.write(output, Lang.TURTLE.getName(), baseURI.toString()); } catch (RiotException e) { throw new WriterException("Can't write to output", e); } } public void setScufl2Tools(Scufl2Tools scufl2Tools) { this.scufl2Tools = scufl2Tools; } public void setUriTools(URITools uriTools) { this.uriTools = uriTools; } }