Semantic Web Research Group

OWL-S API     |     Download     |     Support     |     License     |     Documentation     |     Projects     |     OWL-S Home

Contents

  1. API javadocs
  2. Service examples
  3. Reading/writing service descriptions
  4. OWL-S Validation
  5. Loading cached ontologies
  6. Executing services
  7. Execution monitoring
  8. Creating composite processes
  9. Using OWL resources
  10. WSDL support

Tutorial

  1. API javadocs

    The javadocs of the API is included in the distribution file. You can access the online version here.

  2. 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.

  3. 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);

     

  4. 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);
  5. 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 the OWLCache.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. See OWLCache.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.

     

  6. 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 another ValueMap which 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 = (OWLDataValueaOutputValueMap.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. See RunService.java in the examples directory for more examples of this kind.
     

  7. 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. See RunService.java in the examples directory for an example of how to use the listener.
     

  8. Creating composite processes

    It is possible to create service descriptions, profiles or processes programmatically. OWLSFactory provides functions to create any of these structures. CreateSequence.java in 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 = (ServicetheServices.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;
    }


     

  9. Using OWL resources

    Every resource in the API (Service, Profile, Process, etc.) extends OWLIndividual which 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 function getImplementation() 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 a getImplementation() 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.
     

  10. 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.
     


 

MINDSWAP is a W3C member