Now using Apache Jena (untested)
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/8fbd114c Tree: http://git-wip-us.apache.org/repos/asf/incubator-taverna-language/tree/8fbd114c Diff: http://git-wip-us.apache.org/repos/asf/incubator-taverna-language/diff/8fbd114c Branch: refs/heads/master Commit: 8fbd114c3f62b3bae86833364212ca8340e3661e Parents: 974a951 Author: Stian Soiland-Reyes <[email protected]> Authored: Wed Feb 10 12:22:33 2016 +0000 Committer: Stian Soiland-Reyes <[email protected]> Committed: Wed Feb 10 12:22:33 2016 +0000 ---------------------------------------------------------------------- .../taverna/scufl2/wfdesc/WfdescSerialiser.java | 460 +++++++++---------- 1 file changed, 227 insertions(+), 233 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-taverna-language/blob/8fbd114c/taverna-scufl2-wfdesc/src/main/java/org/apache/taverna/scufl2/wfdesc/WfdescSerialiser.java ---------------------------------------------------------------------- diff --git a/taverna-scufl2-wfdesc/src/main/java/org/apache/taverna/scufl2/wfdesc/WfdescSerialiser.java b/taverna-scufl2-wfdesc/src/main/java/org/apache/taverna/scufl2/wfdesc/WfdescSerialiser.java index 94bd5c3..c8c1c7a 100644 --- a/taverna-scufl2-wfdesc/src/main/java/org/apache/taverna/scufl2/wfdesc/WfdescSerialiser.java +++ b/taverna-scufl2-wfdesc/src/main/java/org/apache/taverna/scufl2/wfdesc/WfdescSerialiser.java @@ -21,7 +21,6 @@ package org.apache.taverna.scufl2.wfdesc; * */ - import static org.apache.taverna.scufl2.api.common.Scufl2Tools.NESTED_WORKFLOW; import java.io.IOException; @@ -38,6 +37,11 @@ import org.apache.jena.ontology.Individual; import org.apache.jena.ontology.OntClass; 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.riot.WriterGraphRIOT; import org.apache.jena.vocabulary.OWL; import org.apache.jena.vocabulary.RDFS; import org.apache.taverna.scufl2.api.activity.Activity; @@ -60,6 +64,7 @@ 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; @@ -68,25 +73,18 @@ 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"); + 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"); - + 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(); - private WorkflowBundle wfBundle; - public Scufl2Tools getScufl2Tools() { return scufl2Tools; @@ -99,266 +97,262 @@ public class WfdescSerialiser { private String uriForBean(WorkflowBean bean) { return uriTools.uriForBean(bean).toASCIIString(); } - - protected void save(final WorkflowBundle bundle) { + + 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); + + 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); + 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); + 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); + 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")); + // 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(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; + } + 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!"); + // 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); - - RDFFormat dataFormat = RDFFormat.TURTLE; - try { - getSesameManager().getConnection().add(annotationStream, baseURI, dataFormat); - } catch (OpenRDFException 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); - } - } + 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; - Labelled labelled = entityForBean(node, Labelled.class); - labelled.getLabel().add(named.getName()); + entityForBean(node, OWL.Thing).addLabel(named.getName(), null); } return true; } - private void specializationOf(WorkflowBean special, WorkflowBean general) { - Entity specialEnt = entityForBean(special, Entity.class); - Entity generalEnt = entityForBean(general, Entity.class); - specialEnt.getWfSpecializationOf().add(generalEnt); - } - - private Individual entityForBean(WorkflowBean bean, OntClass type) { - return model.createIndividual(uriForBean(bean), type); - } - -// @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; -// }; + 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 { - synchronized (this) { - if (this.wfBundle != null) { - throw new IllegalStateException( - "This serializer is not thread-safe and can only save one WorkflowBundle at a time"); - } - this.wfBundle = wfBundle; - } - try { + OntModel model; + final URI baseURI; if (wfBundle.getMainWorkflow() != null) { Workflow mainWorkflow = wfBundle.getMainWorkflow(); baseURI = uriTools.uriForBean(mainWorkflow); - save(wfBundle); + model = save(wfBundle); } else { throw new WriterException( "wfdesc format requires a main workflow"); } - - ContextAwareConnection connection = getSesameManager().getConnection(); - try { - connection.setNamespace("rdfs", + model.setNsPrefix("rdfs", "http://www.w3.org/2000/01/rdf-schema#"); - connection.setNamespace("xsd", "http://www.w3.org/2001/XMLSchema#"); - connection.setNamespace("owl", "http://www.w3.org/2002/07/owl#"); - connection.setNamespace("prov", "http://www.w3.org/ns/prov#"); - connection.setNamespace("wfdesc", + 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#"); - connection.setNamespace("wf4ever", + model.setNsPrefix("wf4ever", "http://purl.org/wf4ever/wf4ever#"); - connection.setNamespace("roterms", + model.setNsPrefix("roterms", "http://purl.org/wf4ever/roterms#"); - connection.setNamespace("dc", "http://purl.org/dc/elements/1.1/"); - connection.setNamespace("dcterms", "http://purl.org/dc/terms/"); - connection.setNamespace("comp", "http://purl.org/DP/components#"); - connection.setNamespace("dep", "http://scape.keep.pt/vocab/dependencies#"); - connection.setNamespace("biocat", "http://biocatalogue.org/attribute/"); - - connection.setNamespace("", "#"); - + 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/"); - connection.export(new OrganizedRDFWriter( - new TurtleWriterWithBase(output, baseURI))); - } catch (OpenRDFException e) { + model.setNsPrefix("", "#"); + + try { + model.write(output, Lang.TURTLE.getName(), baseURI.toString()); + } catch (RiotException e) { throw new WriterException("Can't write to output", e); } - } finally { - synchronized (this) { - this.wfBundle = null; - } - } + } public void setScufl2Tools(Scufl2Tools scufl2Tools) {
