OWL-S API | Download | Support | License | Documentation | Projects | OWL-S Home
Contents
API javadocs
Service examples
Reading/writing service descriptions
OWL-S Validation
Loading cached ontologies
Executing services
Execution monitoring
Creating composite processes
Using OWL resources
WSDL support
Tutorial
API javadocs
The javadocs of the API is included in the distribution file. You can access the online version here.
Service examples
There are couple of example OWL-S files here http://www.mindswap.org/2004/owl-s/services.shtml. These services are all grounded in actual WSDL services and can be executed with the API. These are simple service descriptions to show different features in OWL-S such as how to define XSLT transformations in groundings, how to define CompositeProcesses and data flows and so on.
The examples directory in the distribution file contains example code that shows how to use these service descriptions in the API.
Reading/writing service descriptions
There are two interfaces defined for reading and writing OWL files, OWLReader and OWLWriter. These are simple interfaces that provide the basic functionality of reading and writing OWL files. OWLReader's and Writers can be created via the static methods createReader() and createWriter() on the OWLFactory class. The OWLReader will read in an OWL file from a variety of inputs and produces an OWLOntology object. Alternatively, the OWLWriter class can write an OWLOntology object to a number of different outputs.
Also, an OWLKnowledgeBase can be created using the OWLFactory class. An OWLKnowledgeBase has several read methods which read the specified ontology into the KB. However, it also provides special read methods such as readService(URI) and readAllServices(URI) for reading in OWL-S descriptions. These methods return the Service found at the specfied URI and the list of Services found at a URI respectively.
Here is some example code to show you how to use the OWLReader, OWLWriter and OWLKnowledgeBase classes to read in OWL files and OWL-S descriptions. For more details, see the examples provided with the OWL-S API.
// create the URI of a known service for us to read in
URI aURI = URI.create("http://www.mindswap.org/2004/owl-s/1.1/ZipCodeFinder.owl");
// create a reader using the owl factory
OWLReader aReader = OWLFactory.createReader();
// read in the file specified by the URI using the newly created reader
OWLOntology aOntology = aReader.read(aURI);
// create an output stream to write the ontology to
FileOutputStream aOutputStream = new FileOutputStream("write-test.owl");
// create a writer using the owl factory
OWLWriter aWriter = OWLFactory.createWriter();
// write this ontology out to the specified output stream
aWriter.write(aOntology,aOutputStream);
// alternatively, we can create a KB object and use that to read in
// a file or set of files
// create a kb using the factory
OWLKnowledgeBase aKB = OWLFactory.createKB();
// now that we have a kb, we can read in the same file using the
// read method of the KB. the read method of the kb will create an
// OWLReader similar to the above example to read in the file. If you
// are reading in an OWL-S description you can use readService(URI)
// or readAllServices(URI) to get the service or list of services specfied
// by the URI.
Service aService = aKB.readService(aURI);OWL-S Validation
A simple validator is provided with the OWL-S API. It is located in the org.mindswap.owls.validator package. The OWLSValidator class provides a method validate() which takes the URI to an ontology, or a OWLKnowledgeBase to validate. It looks for common structural errors in the OWL-S description. The validator returns an OWLSValidatorReport upon validation which contains all the information about the validation, including whether or not the service(s) found are valid, and any error or warning messages. This report can be written to any output stream, or the Map of OWLSValidatorMessages can be iterated over to get at the validation results.
// create a new validator
OWLSValidator aValidator = new OWLSValidator();
// the URI of a known service for us to validate
String aURI = "http://www.mindswap.org/2004/owl-s/1.1/ZipCodeFinder.owl";
// run the validator
OWLSValidatorReport aReport = aValidator.validate(aURI);
// print the results to the console
aReport.print(System.out);Loading cached ontologies
Sometimes it is desirable to use cached versions of the files rather than downloading the remote files. The OWLCache class provides the functionality for this purpose. OWLCache.setLocalCacheDirectory(String) specifies a directory to find the cached files. The cache dir should include a file named service.idx that has the mappings from URI's to local file names. This index file is a text file where each line is in the format
[service description url]=[local filename]
The ':' characters in the url's should be escaped as "\:". See
Properties.load()for more details about the file format. You may choose to add file entries one by one using theOWLCache.addCachedFile()function. When there is a cache entry for a file, the cached version is only used when the original file cannot be found (e.g. no connection). It is also possible to give more priority to cached files and try to get the remote file only if there is no cached version. SeeOWLCache.setForced(boolean)for this functionality. Remember to include an xml:base statement in your cached files so that URIs generated from your local file will be exactly same as the remote one.Executing services
Executing a service means executing the process it has. The process should have a valid grounding specification in order to invoke the service successfully. The WSDL and UPnP groundings are supported by the API. A process is executed by the
ProcessExecutionEngine.execute(Process, ValueMap)function where second parameter specifies the values for input parameters. This function returns anotherValueMapwhich contains the output value bindings. The following code segment shows an example of executing a service:// create an execution engine
ProcessExecutionEngine exec = OWLSFactory.createExecutionEngine();
// create a kb
OWLKnowledgeBase kb = OWLFactory.createKB();
// read in the service description
Service aService = kb.readService("http://www.mindswap.org/2004/owl-s/1.1/Dictionary.owl");
// get the process for the server
Process aProcess = aService.getProcess();
// initialize the input values to be empty
ValueMap aInputValueMap = new ValueMap();
// specify an input value
String inValue = "hello";
// set the value in the map
aInputValueMap.setDataValue(aProcess.getInput("InputString"), inValue);
// run the process
ValueMap aOutputValueMap = exec.execute(aProcess, aInputValueMap);
// get the output
OWLDataValue out = (OWLDataValue) aOutputValueMap.getValue(aProcess.getOutput());
// display the value
System.err.println("Output = "+out.getValue());
The above is a simple example where the input is a simple XML Schema string. However, some services will have complex inputs that are represented by OWL classes. In this case, the value of input parameter can be set to the RDF/XML representation of the complex input. SeeRunService.javain the examples directory for more examples of this kind.
Execution monitoring
It is possible to monitor the progress of a service's execution. ProcessMontior defines a minimal set of functions for this purpose which are called when a service begins, finishes or fails execution. Simply use the
ProcessExecutionEngine.addMonitor(ProcessMonitor)to add a monitor to the execution engine. SeeRunService.javain the examples directory for an example of how to use the listener.
Creating composite processes
It is possible to create service descriptions, profiles or processes programmatically.
OWLSFactoryprovides functions to create any of these structures.CreateSequence.javain the examples directory shows an example of how to do this. The following code snippet shows the main idea:/**
*
* Create a new Sequence from the processes of the given services and put them in a new
* Service object with a automatically generated Profile. This function assumes that
* each service in the list has exactly one input and one output (except the first and
* last one) such that in the resulting Service the output of each service will be fed
* as input to the next one. The first service does not have to have an input and the
* last one does not need to have an output. The resulting service will have an input
* (or an output) depending on this.
*
* @param services List of Service objects
* @param baseURI The base URI for the generated service
* @return The Service which is a Sequence of the given services
*/
private Service createSequenceService(List theServices, URI theBaseURI) {
OWLOntology theOntology = OWLFactory.createOntology();
// create the new service
Service aService = theOntology.createService(URIUtils.createURI(theBaseURI, "TestService"));
// create the composite process for our service
CompositeProcess aProcess = theOntology.createCompositeProcess(URIUtils.createURI(theBaseURI, "TestProcess"));
// create the new profile and grounding
Profile aProfile = theOntology.createProfile(URIUtils.createURI(theBaseURI, "TestProfile"));
Grounding aGrounding = theOntology.createGrounding(URIUtils.createURI(theBaseURI, "TestGrounding"));
// set the profile, process and grounding for the new service
aService.setProfile(aProfile);
aService.setProcess(aProcess);
aService.setGrounding(aGrounding);
// now lets create the composite sequence
Sequence aSequence = theOntology.createSequence();
aProcess.setComposedOf(aSequence);
// for each service that we are composing
Perform[] performs = new Perform[theServices.size()];
for(int i = 0; i < theServices.size(); i++) {
// grab that service, and its process
Service s = (Service) theServices.get(i);
Process p = s.getProcess();
// create a new perform
performs[i] = theOntology.createPerform();
performs[i].setProcess(p);
// add it to the composition
aSequence.addComponent(performs[i]);
// and link with the previous perform
if(i > 0) {
Perform prevPerform = performs[i - 1];
Input input = p.getInputs().inputAt(0);
Output output = prevPerform.getProcess().getOutputs().outputAt(0);
// the value of 'input' is the value of 'output' from 'prevPerform'
performs[i].addBinding(input, prevPerform, output);
}
}
Perform firstPerform = performs[0];
Perform lastPerform = performs[theServices.size()-1];
boolean createInput = firstPerform.getProcess().getInputs().size() > 0;
boolean createOutput = lastPerform.getProcess().getOutputs().size() > 0;
if(createInput) {
Input input = firstPerform.getProcess().getInputs().inputAt(0);
Input newInput = theOntology.createInput(URIUtils.createURI(theBaseURI, "TestInput"));
newInput.setLabel(input.getLabel());
newInput.setParamType(input.getParamType());
newInput.setProcess(aProcess);
// input of the first perform is directly read from the input of the
// composite process
performs[0].addBinding(input, Perform.TheParentPerform, newInput);
}
if(createOutput) {
Output output = lastPerform.getProcess().getOutputs().outputAt(0);
Output newOutput = theOntology.createOutput(URIUtils.createURI(theBaseURI, "TestOutput"));
newOutput.setLabel(output.getLabel());
newOutput.setParamType(output.getParamType());
newOutput.setProcess(aProcess);
// the output of the composite process is the output pf last process
Result result = theOntology.createResult();
result.addBinding(newOutput, lastPerform, output);
aProcess.setResult(result);
}
// init profile inputs and outputs from the composite process inputs and outputs...
// ground the processes of the composite service...
// set some basic info
aProfile.setLabel("Composite Service");
aProfile.setTextDescription(aProfile.getLabel());
// return the composite service
return aService;
}
Using OWL resources
Every resource in the API (
Service,Profile,Process,etc.) extendsOWLIndividualwhich provides very basic functionalities to get and set object and data properties for any OWL resource. If additional information is required about the resources then the underlying RDF model can be queried. Right now, API is built on top of Jena so the functiongetImplementation()will return the corresponding resource in the Jena model.
Each service description is loaded into a separate Jena model where the model contains the imports closure of the service description, i.e. each ontology service description imports is also in that model. OWLModel provides agetImplementation()function that will return the underlying Jena Model. Individual OWLModel's can be accessed by the OWLKnowledgeBase they are a part of, stand-alone when created using OWLFactory.In the future releases it is planned to add support for OWL API.
WSDL Support
The API contains a package org.mindswap.wsdl that provides support for reading and executing WSDL services. Execution of OWL-S services is achieved through this package. The WSDL functionality is based on Axis package version 1.1. The main functionality added to Axis is the ability to execute services with complex inputs dynamically without a need to create stubs or extra code. The SOAP messages are created from the string representation of XML Schema complex type. This invocation method is not robust but works for most of the cases.
