Documentation
In the following we provide documentation for
- Seamless integration as OWLReasoner: Access OWLlink servers as OWLReasoners
- Direct access to OWLlink-specific queries: Access OWLlink servers as OWLlinkReasoners
- Setting up an OWLlink server based on an arbitrary OWLReasoner such as Pellet, FaCT++, HermiT which does not provide any OWLlink
server functionality by itself.
- Adding user-defined requests/responses to the OWLlink API
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 = ...;
OWLlinkHTTPXMLReasonerFactory reasonerFactory = new OWLlinkHTTPXMLReasonerFactory();
OWLOntology ontology = ...;;
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 = ...
CreateKB createKBRequest = new CreateKB();
KB kbResponse = reasoner.answer(createKBRequest);
Tell tellRequest = new Tell(kbResponse.getKB(), axioms);
OK okResponse = reasoner.answer(tellRequest);
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, ...);
for (Response response : responseMessage) {
}
int count = ...;
for (int i=0; i<count; i++) {
Response response = responseMessage.get(i);
}
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");
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:
- Using one of the predefined scripts or server factories for HermiT, Pellet, and FaCT++
- Wrapping an arbitrary OWLReasoner that implements the OWL API 2 or OWL API 3
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;
HermiTServerFactory hermit = new HermiTServerFactory();
OWLlinkServer server = hermit.createServer(port);//
server.run();
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 = ...;
OWLReasonerConfiguration reasonerConfiguration = ...;
AbstractOWLlinkReasonerConfiguration serverConfiguration = new AbstractOWLlinkReasonerConfiguration(reasonerConfiguration);
int port = ...;
OWLlinkServer server = new OWLlinkHTTPXMLServer(factory, serverConfiguration, port);
server.run();
. . .
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 = ...;
LegacyReasonerFactory legacyFactory = new LegacyReasonerFactory(reasonerFactory);
AbstractOWLlinkReasonerConfiguration serverConfiguration = new AbstractOWLlinkReasonerConfiguration();
int port = ...;
OWLlinkServer server = new OWLlinkServer(legacyFactory, serverConfiguration, port);
server.run();
. . .
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