Documentation

In the following we provide documentation for

Seamless integration as OWLReasoner

The OWLlink API is bundled with an implementation of the HTTP/XML binding. The class org.semanticweb.owlapi.owllink.OWLlinkHTTPXMLReasoner is an implementation of an OWLReasoner. If your existing application already uses an OWLReasoner you can bind it to the OWLlinkHTTPXMLReasoner and you can use a remote OWLLink server (such as RacerPro) without further changes. Make sure that your favorite OWLlink server is running when executing your application.

OWLOntologyManager manager = ...;
OWLlinkHTTPXMLReasonerFactory factory = new OWLlinkHTTPXMLReasonerFactory();
OWLOntology ontology = manager.createOntology(IRI.create("tutorial"));
OWLClass A = manager.getOWLDataFactory().getOWLClass(IRI.create("http://tutorial#A"));
OWLClass B = manager.getOWLDataFactory().getOWLClass(IRI.create("http://tutorial#B"));
OWLAxiom a = manager.getOWLDataFactory().getOWLSubClassOfAxiom(A, B);
manager.addAxiom(ontology, a);
OWLReasoner reasoner = factory.createReasoner(ontology);
//now you can use the reasoner as usual, e.g.:
boolean b = reasoner.isSubClassOf(A, B);

Direct access to OWLlink-specific queries

To benefit from the additional functonality of OWLlink beyond the OWL API OWLReasoner interface, such as introspection, knowledge base management, parallel handling of knowledge bases, and additional queries, one can allocate the OWLlinkReasoner interface directy as shown in the following example.

OWLOntologyManager manager = ...;//Create/use an OWLOntologyManager
OWLlinkHTTPXMLReasonerFactory reasonerFactory = new OWLlinkHTTPXMLReasonerFactory();
OWLOntology ontology = ...;//Create/use an OWLOntology;
OWLlinkReasoner reasoner = reasonerFactory.createReasoner(ontology);
For the given ontology (also known as root ontology) a new knowledge base will be created on an OWLlink server. All ontology changes (i.e., addition and removal of axioms) with respect to that ontology will be exchanged with the server. Note that all OWLReasoner methods refer to that knowledge base which can be accessed via OWLlinkHTTPXMLReasoner.getDefaultKB():

OWLlinkReasoner reasoner = ...
NodeSet<OWLClass> = reasoner.getSubClasses(manager.getOWLDataFactory().getOWLThing(), true);
GetSubClassHierarchy request = new GetSubClassHierarchy(reasoner.getDefaultKB());
ClassHierarchy hierarchy = reasoner.answer(request);
One can also add new knowledge bases as shown in the following example. Note that the axioms of that knowledge base are handled independent of the root ontology of the OWLReasoner.
OWLlinkReasoner reasoner = ...
//Create a new (empty) knowledge base ...
CreateKB createKBRequest = new CreateKB();
KB kbResponse = reasoner.answer(createKBRequest);
//... and transfer a set of axioms (e.g., from another ontology, an temporary ontology etc.) to it
Tell tellRequest = new Tell(kbResponse.getKB(), axioms);
OK okResponse = reasoner.answer(tellRequest);
...
//Don't forget to release the knowledge base before terminating the application
ReleaseKB releaseKBRequest = new ReleaseKB(kbResponse.getKB());
okResponse = reasoner.answer(releaseKBRequest);
Make sure that if a new KB is created it should be released before terminating the application. The OWLlink API package org.semanticweb.owlapi.owllink.builtin.requests contains all default OWLlink request (incl. those of the retraction extension) and their corresponding responses are listed in the package org.semanticweb.owlapi.owllink.builtin.responses

Request by request

One can query an OWLlink server request by request as shown in the following.
Response someResponse = reasoner.answer(someQuery);
The response someResponse is automatically casted to the subclass of Response as needed by the request. For instance, a Tell request is always answered by an OK response, a GetSubClasses request by the corresponding ClassSynsets, etc.
Tell tell = new Tell(kbIRI, ontology.getAxioms());
OK ok = reasoner.answer(tell);
OWLClass A = ...;
GetSubClasses getSubClasses = new GetSubClasses(kbIRI, A);
ClassSynsets synsets = reasoner.answer(getSubClasses);

Request bundles

Requests can be bundled into one request message. This is supported by a special answer method that allows multiple requests as parameter as shown in the following.
ResponseMessage responseMessage = reasoner.answer(query1, query2, query3, ...);
The returned ResponseMessage contains the corresponding response for each request.
ResponseMessage responseMessage = reasoner.answer(query1, query2, query3, ...);
//iteration variant 1
for (Response response : responseMessage) {
  //process responses
  //response must be casted explicitly
}
//itertion variant 2
int count = ...;//number of requests
for (int i=0; i<count; i++) {
  Response response = responseMessage.get(i);
  //process response
  //response must be casted explicitly
}
Note that in the case of an OWLlink ErrorMessage is received an OWLlinkErrorResponseException will be thrown. The additional methods boolean isErrorResponse(int index) and hasErrorResponse(Request request) can also be used.

Configuring an OWLlinkHTTPXMLReasoner

The end-point of an HTTP/XML aware OWLlink server can be configured when creating a new instance of OWLlinkHTTPXMLReasonerFactory as shown in the following example.
OWLOntology ontology = ...;
URL url = new URL("http://localhost:8080");//Configure the server end-point
OWLlinkReasonerConfiguration reasonerConfiguration = new OWLlinkReasonerConfiguration(url);
OWLlinkHTTPXMLReasonerFactory factory = new OWLlinkHTTPXMLReasonerFactory();
OWLlinkReasoner reasoner = factory.createNonBufferingReasoner(ontology, reasonerConfiguration);
Note that the buffering respectively non-buffering mode of the OWLReasoner only refers to the root ontology not to knowledge bases that are explicitly created by a CreateKB request.

Setting up an OWLlink server for out-of-the-box OWLReasoners

If one is using an OWLReasoner implementation such as HermiT, Pellet or FaCT++ which do not provide an OWLlink server by their own one can also benefit from the client - server adapter (e.g., in order to archieve a more robust application) by running any OWLReasoner as an OWLlink server - even those which implement the outdated OWLAPI 2!

Note however that only those OWLlink requests are supported which can be mapped to the OWLReasoner.

There are the following possibilities to wrap an OWLReasoner:

Pre-defined server scripts and server factories

There are scripts for starting Pellet (versions prior to 2.0 that support OWL API 2, and versions >= 2.x that support OWL API 3), FaCT++ (for OWL API 2 and 3) as well as HermiT as OWLlink servers. Note that the binaries of these reasoners are not shipped with the OWLlink API. Please download them separately and put them in the "lib" sub-directory of the corresponding directory as explained in the following. For Pellet that supports the OWL API 2 (i.e., Pellet versions prior to 2.0.0) choose the directory pellet-server-OWLAPI2, for Pellet that supports the OWL API 3 (i.e., Pellet versions >= 2.x.y) choose the directory pellet-server-OWLAPI3, for FaCT choose either the directory fact-server-OWLAPI2 (OWL API 2 support) or fact-server-OWLAPI3 (current version of FaCT for OWL API 3), and for HermiT please choose the directory hermit-server.

The server start scripts will start an OWLlink server on port 8080 by default. One can adjust it by editing the script files.

For each of the mentioned reasoner versions one can also start an OWLlink server programmatically. Please remember that one has to adjust the Java classpath in order to make the binaries of the reasoner implementation accessible by OWLlink API. For instance, HermiT can be started as server as shown in the following.

int port = 8090;//HTTP port for the server, e.g., 8090
HermiTServerFactory hermit = new HermiTServerFactory();
OWLlinkServer server = hermit.createServer(port);//
server.run();
//shutdown the server:
server.stop();

Wrapping an arbitrary OWLAPI 3 OWLReasoner

To turn an OWLReasoner into a standalone HTTP/XML OWllink server one can take the following code as a blueprint.

OWLReasonerFactory reasonerFactory = ...;//OWLAPI 3 OWLReasonerFactory of your reasoner
OWLReasonerConfiguration reasonerConfiguration = ...;//OWLAPI 3 OWLReasonerConfiguration of your reasoner (optional)
AbstractOWLlinkReasonerConfiguration serverConfiguration = new AbstractOWLlinkReasonerConfiguration(reasonerConfiguration);
/* The serverConfiguration is used for configuring the OWLReasoner and for OWLlink server introspecting. Please adjust the values if needed, for instance to set supported Datatypes etc.:
serverConfiguration.setSupportedDatatypes(OWL2Datatype.XSD_LONG.getIRI(),
     OWL2Datatype.XSD_INT.getIRI(),
     OWL2Datatype.XSD_NON_POSITIVE_INTEGER.getIRI(),
     OWL2Datatype.XSD_NON_NEGATIVE_INTEGER.getIRI(),
     OWL2Datatype.XSD_SHORT.getIRI(),
     OWL2Datatype.OWL_REAL.getIRI());
*/

int port = ...;//HTTP port for the server
OWLlinkServer server = new OWLlinkHTTPXMLServer(factory, serverConfiguration, port);
server.run();
. . .
//Don't forget to stop the server later on by calling:
server.stop()

Wrapping an arbitrary OWLAPI 2 OWLReasoner

For compatibility reasons one can also wrap an OWLAPI 2 OWLReasoner in order to act as a standalone OWLlink server (note however that not all constructs of OWL 2 are supported). This feature is very useful to integrate either older versions of reasoners or reasoners that have not been ported to OWL API 3 yet into an application. Please remember that the application code uses OWLlink API and therefore OWL API 3.

org.semanticweb.owl.inference.OWLReasonerFactory.OWLReasonerFactory reasonerFactory = ...;//reasoner factory of the reasoner
LegacyReasonerFactory legacyFactory = new LegacyReasonerFactory(reasonerFactory);
AbstractOWLlinkReasonerConfiguration serverConfiguration = new AbstractOWLlinkReasonerConfiguration();
int port = ...;//HTTP port for the server
OWLlinkServer server = new OWLlinkServer(legacyFactory, serverConfiguration, port);
server.run();
. . .
//Don't forget to stop the server later on by calling:
server.stop()

Adding user-defined requests/responses to the OWLlink API

OWLlink requests and responses are represented as interface (with corresponding implementations) of Request (KBRequest) and Response. Each Request type information for the corresponding response must be added. Note that an OWLlink ErrorResponse are represented as Java Exceptions in order to fulfill OWL API's requirements.
public interface Request<R extends Response> {
   <O> O accept(ResponseVisitor<O> visitor);

public interface KBRequest<R extends KBResponse> extends Request<R> {
   IRI getKB();
}

public interface Response {
   <O> O accept(ResponseVisitor<O> visitor);
To make things easier the package org.semanticweb.owlapi.owllink.builtin.requests provides some common abstract implementations to be re-used.

The next step is to tell the implementation of the bindings that the user-defined requests/responses are available. This, however, is binding implementation-specific. By default, the OWLlink API provides an implementation of the HTTP/XML Binding and we explain in the following how to register user-defined requests/responses for that specific binding. In order to render XML one has to implement org.semanticweb.owlapi.owllink.renderer.OWLlinkXMLRequestRenderer interface and to provide org.semanticweb.owlapi.owllink.renderer.OWLlinkRequestRendererFactory. For instance, the Retract request of the OWLlink Retraction Extension is implemented as shown in the following:

public class OWLlinkXMLRetractRequestRenderer implements OWLlinkXMLRequestRenderer<RetractRequest> {
  public void render(Request request, OWLlinkXMLWriter writer) throws OWLRendererException {
    final RetractRequest rrequest = (RetractRequest) request;
     writer.writeStartElement(RetractionVocabulary.Retraction.getURI());
     IRI kb = rrequest.getKB();
     writer.writeKBAttribute(kb);
     for (OWLAxiom axiom : rrequest) {
       writer.writeOWLObject(axiom, kb);
     }
     writer.writeEndElement();
     }
  }

If one needs to provide an user-defined response one also need to implement org.semanticweb.owlapi.owllink.parser.OWLlinkElementHandler(or use the abstract implementation AbstractOWLlinkElementHandler in order to parse XML and generate the corresponding Java response object.In addition one needs to provide a org.semanticweb.owlapi.owllink.parser.OWLlinkElementHandlerFactory.

Finally, the implementation of both OWLlinkRequestRendererFactory and OWLlinkElementHandlerFactory needs to be registered at org.semanticweb.owlapi.owllink.OWLlinkXMLFactoryRegistry.



Supported by derivo