-
Notifications
You must be signed in to change notification settings - Fork 5
Examples
Table of contents:
- OWL-API and Jena interfaces, overview
- RDF Model interface
- RDF Model factory
- Iteration over OWLAxioms for any Jena Model
- A source in Functional Syntax
- Copying ontologies between managers
- OntModel, passing a Graph as it is
- A SPARQL short example
- SPIN inference by example of use ONT-MAP
- ONT-D2RQ (an extended D2RQ) example
All examples (with except of two last) are available in this wiki itself (just clone it).
Basic OWL-API and Jena Model API functionality in one place.
Note that the manager instance is actually com.github.owlcs.ontapi.OntologyManager,
and the ontology instance is com.github.owlcs.ontapi.OntologyModel.
// Getting manager:
OWLOntologyManager manager = OntManagers.createONT();
// ====================================
// Interacting using OWL-API interface:
// ====================================
// Related data-factory:
OWLDataFactory factory = manager.getOWLDataFactory();
// Creating an ontology:
OWLOntology ontology = manager.createOntology(IRI.create("first"));
// Adding sub-class-of axiom:
ontology.addAxiom(factory.getOWLSubClassOfAxiom(factory.getOWLClass("first-class"), factory.getOWLThing()));
// =====================================
// Interacting using jena-API interface:
// =====================================
Model model = ((OntologyModel)ontology).asGraphModel();
model.createResource("second-class").addProperty(RDFS.subClassOf, model.createResource("first-class"));
// =================
// Printing results:
// =================
System.out.println("Ontology as Turtle:");
ontology.saveOntology(System.out);
System.out.println("\nList of owl-axioms:");
ontology.axioms().forEach(System.out::println);
System.out.println("\nAll jena-statements:");
model.listStatements().forEachRemaining(System.out::println);
Our com.github.owlcs.ontapi.OntologyManager contains methods to create and load org.apache.jena.rdf.model.Model directly,
that is a shortening of the standard way through com.github.owlcs.ontapi.OntologyModel interface:
// getting manager:
OntologyManager manager = OntManagers.createONT();
// creating a graph ontology:
OntGraphModel model = manager.createGraphModel("http://example.com");
// add version iri:
model.getID().setVersionIRI("http://example.com/1.0");
// add some annotations to the ontology header
model.getID().addComment("this is an example ontology", "fr");
// add some ns-prefixes (including standard):
model.setNsPrefixes(OntModelFactory.STANDARD).setNsPrefix("test", "http://example.com#");
// adding several individuals (both named and anonymous):
OntIndividual named = model.getOWLThing().createIndividual("http://example.com#individual");
OntIndividual anonymous = model.getOWLNothing().createIndividual();
// add disjoint individuals axiom assertion:
model.createDifferentIndividuals(named, anonymous);
// add annotation to anonymous individual declaration:
anonymous.addComment("this is an anonymous individual");
// print result as turtle to stdout:
model.write(System.out, OntFormat.TURTLE.getID());
3) ONT-API RDF model interacting with OWL 2 DL constructions (OWL-Object-Max-Cardinality Restriction).
The com.github.owlcs.ontapi.jena.model.OntGraphModel interface supports all the OWL2 language features.
Another way to get an instance of this model is com.github.owlcs.ontapi.jena.OntModelFactory factory.
Note that here is no any OWLOntology companion, which would wrap the same RDF data, unlike the previous example.
OntGraphModel model = OntModelFactory.createModel().setNsPrefixes(OntModelFactory.STANDARD);
OntNOP property = model.createObjectProperty("http://test#hasUnit");
OntClass clazz = model.createOntClass("http://test#Numeric");
clazz.addSuperClass(model.createOntClass("http://test#Characteristic"))
.addSuperClass(model.createObjectMaxCardinality(property, 1,
model.createOntClass("http://test#Scale")));
model.write(System.out, "ttl");
4) List OWLAxiom from Jena Model.
// Create a standard Jena Model:
Model m = ModelFactory.createDefaultModel();
// Load RDF data:
try (InputStream in = Example4.class.getResourceAsStream("/pizza.ttl")) {
RDFDataMgr.read(m, in, Lang.TURTLE);
}
// list all OWLAxioms from Jena Model:
AxiomType.AXIOM_TYPES.stream()
.map(AxiomParserProvider::get)
.forEach(t -> t.axioms(OntModelFactory.createModel(m.getGraph()))
.forEach(System.out::println));
Since ONT-API is OWL-API, all standard means of OWL-API are supported as well, if they are included in the distribution (more about it see on format page).
String functionalSyntaxString = "Ontology(<http://test.org/simple>" +
"SubClassOf(<http://test.org/simple#class2> <http://test.org/simple#class1>)" +
"ClassAssertion(<http://test.org/simple#class1> <http://test.org/simple#individual>))";
InputStream in = new ByteArrayInputStream(functionalSyntaxString.getBytes(StandardCharsets.UTF_8));
OntologyManager manager = OntManagers.createONT();
OntologyModel ontology = manager.loadOntologyFromOntologyDocument(in);
Model model = ontology.asGraphModel();
model.write(System.out, "ttl");
Note: please think twice if you are planning to use this functionality. Although this option exists, it does not mean that it is smart to mix two different implementations. Both implementations (OWL-API-impl and ONT-API), obviously, refer to OWL-API in a OOP is-a relation, ONT-API IS OWL-API, and it can be used in all cases where OWL-API is used. The only good reason for such a mixing is performance. If you found a lack of performance in ONT-API, please contact with me.
String uri = "http://ex.com";
// Get native OWL-API-impl manager through OWL-API-apibinding.
// Note that in ONT-API there is an alternative way: OntManagers.createOWL()
OWLOntologyManager owlManager = OWLManager.createOWLOntologyManager();
// Get ONT-API manager:
OntologyManager ontManager = OntManagers.createONT();
// Create pure OWL-ontology (no graph inside):
OWLOntology owlOntology = owlManager.createOntology(IRI.create(uri));
// Add single axiom (class-assertion):
OWLDataFactory df = ontManager.getOWLDataFactory();
OWLAxiom classAssertion = df.getOWLClassAssertionAxiom(
df.getOWLClass(IRI.create(uri + "#", "clazz")),
df.getOWLNamedIndividual(IRI.create(uri + "#", "individual")));
owlOntology.add(classAssertion);
// Copy from OWL- to ONT-Manager.
// This will produce an OWL-ontology (OntologyModel) with a jena Graph inside:
OntologyModel ontOntology = ontManager.copyOntology(owlOntology, OntologyCopy.DEEP);
// Print all triples from the inner graph:
ontOntology.asGraphModel().getGraph().find(Triple.ANY).forEachRemaining(System.out::println);
// Print all axioms:
ontOntology.axioms().forEach(System.out::println);
Please also note: starting the release 1.4.1 the possibility to move (the parameter OntologyCopy.MOVE) is disabled.
For moving use the copy-remove operations sequence.
The main reason for this is simple: we can't guarantee the same instance when a native OWLOntology implementation instance is specified (see #74).
There are a lot of Jena customers that only know OntModel,
and prefer to use it always and everywhere.
In ONT-API there is a way to pass any RDF Graph as it is into the OWLOntologyManager instance, to avoid the widely used, but time- and memory-consuming ways,
like round-tripping or piped-stream-based way.
// Jena ONT-Model API
OntModelSpec spec = OntModelSpec.OWL_DL_MEM;
OntModel o1 = ModelFactory.createOntologyModel(spec);
OntModel o2 = ModelFactory.createOntologyModel(spec);
o1.createOntology("http://test.com/1/v1")
.addImport(o2.createOntology("http://test.com/2"));
o1.addSubModel(o2);
o1.createOntology("http://test.com/1/v2");
o1.createClass("http://test.com#clazz1");
o2.createClass("http://test.com#clazz2");
// Pass to ONT-API
OntologyManager manager = OntManagers.createONT();
OntologyModel ontology = manager.addOntology(o1.getGraph());
// expected: two class-declarations:
ontology.axioms(Imports.INCLUDED).forEach(System.out::println);
// expected: <http://test.com/1/v1>
System.out.println(ontology.getOntologyID());
// expected: 2
System.out.println(manager.ontologies().count());
Since ONT-API is a RDF-centric OWL-API implementation, Jena-ARQ is working:
String uri = "http://ex.com/test";
String ns = uri + "#";
OntologyManager m = OntManagers.createONT();
OWLDataFactory df = m.getOWLDataFactory();
// Interacting with OWL-API interfaces: assembly the ontology:
OntologyModel o = m.createOntology(IRI.create(uri));
OWLAnnotationProperty a1 = df.getOWLAnnotationProperty(IRI.create(ns, "prop1"));
OWLAnnotationProperty a2 = df.getOWLAnnotationProperty(IRI.create(ns, "prop2"));
OWLClass c1 = df.getOWLClass(IRI.create(ns, "class1"));
OWLNamedIndividual i1 = df.getOWLNamedIndividual(IRI.create(ns, "indi1"));
o.add(df.getOWLDeclarationAxiom(a1));
o.add(df.getOWLDeclarationAxiom(a2));
o.add(df.getOWLDeclarationAxiom(c1));
o.add(df.getOWLAnnotationPropertyDomainAxiom(a1, c1.getIRI()));
o.add(df.getOWLClassAssertionAxiom(c1, i1));
o.add(df.getOWLSubAnnotationPropertyOfAxiom(a2, a1));
o.add(df.getOWLAnnotationAssertionAxiom(a1, df.getOWLAnonymousIndividual(), i1.getIRI()));
// Print ontology before updating:
o.axioms().forEach(System.out::println);
o.saveOntology(System.out);
// SPARQL UPDATE: replace owl:AnnotationProperty -> owl:ObjectProperty
UpdateAction.parseExecute("PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n" +
"PREFIX owl: <http://www.w3.org/2002/07/owl#>\n" +
"DELETE { ?x rdf:type owl:AnnotationProperty } \n" +
"INSERT { ?x rdf:type owl:ObjectProperty } \n" +
"WHERE { ?x rdf:type owl:AnnotationProperty }",
o.asGraphModel());
// Print result:
o.axioms().forEach(System.out::println);
o.saveOntology(System.out);
// SPARQL SELECT: just print all declarations:
try (QueryExecution qexec = QueryExecutionFactory.create(QueryFactory
.create("PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n" +
"SELECT ?s ?o WHERE { ?s a ?o }"), o.asGraphModel())) {
ResultSet res = qexec.execSelect();
while (res.hasNext()) {
System.out.println(res.next());
}
}
9) ONT-MAP (an OWL2 ontology to ontology data mapper and inference engine)
ONT-MAP is a SPIN based solution, which allows to transfer a data from one OWL2 schema to another.
Consider you have an ontology with two datatype properties, x and y, and data where a number individuals have coordinates assigned in the form of data property assertions.
And now you want to transfer this data to another form, into an ontology, where only one datatype property (z) with a meaning hypotenuse (z = sqrt(x^2 + y^2)).
The following code demonstrates the whole cycle of the described above scenario, starting from the creating test data, building mapping and finishing with running inference and validation:
Random r = new Random();
int n = 5;
// Assemble the source:
OntGraphModel src = OntModelFactory.createModel().setNsPrefixes(OntModelFactory.STANDARD);
src.setID("src");
OntClass c1 = src.createOntClass("C1");
OntDT d1 = src.getDatatype(XSD.integer);
OntNDP x = src.createDataProperty("X").addDomain(c1).addRange(d1);
OntNDP y = src.createDataProperty("Y").addDomain(c1).addRange(d1);
for (int i = 0; i < n; i++) {
c1.createIndividual("I#" + i)
.addProperty(x, d1.createLiteral(String.valueOf(r.nextInt(10))))
.addProperty(y, d1.createLiteral(String.valueOf(r.nextInt(10))));
}
src.write(System.out, "ttl");
// Assemble the target:
OntGraphModel dst = OntModelFactory.createModel().setNsPrefixes(OntModelFactory.STANDARD);
dst.setID("dst");
OntClass c2 = dst.createOntClass("C2");
OntDT d2 = dst.getDatatype(XSD.integer);
OntNDP z = dst.createDataProperty("Z").addDomain(c2).addRange(d2);
// Assemble the mapping:
MapManager manager = Managers.createMapManager();
MapFunction uuid = manager.getFunction(AVC.UUID);
MapFunction pow = manager.getFunction(MATH.pow);
MapFunction sum = manager.getFunction(SP.add);
MapFunction sqrt = manager.getFunction(MATH.sqrt);
MapFunction xd = manager.getFunction(XSD.xdouble);
MapFunction.Call f1 = uuid.create().build();
MapFunction.Call f2 = sqrt.create().addFunction(SP.arg1,
xd.create().addFunction(SP.arg1,
sum.create()
.addFunction(SP.arg1, pow.create()
.addProperty(SP.arg1, x)
.addLiteral(SP.arg2, 2))
.addFunction(SP.arg2, pow.create()
.addProperty(SP.arg1, y)
.addLiteral(SP.arg2, 2))))
.build();
MapModel res = manager.createMapModel();
res.asGraphModel().setID("map");
res.createContext(c1, c2, f1).addPropertyBridge(f2, z);
// Run inference:
res.runInference(src.getGraph(), dst.getGraph());
// Print and validate:
dst.write(System.out, "ttl");
Assert.assertEquals(n, dst.individuals().count());
Related readings:
- How to perform Ontology->Ontology mapping inference using the original Topbraid SPIN-API, see com.github.owlcs.ontapi.tests.SpinMappingTest test-class. NOTE: since 1.1.0 it is not original spin(org.topbraid:spin:2.0.0), but topQuadrant/SHACL(org.topbraid:shacl:1.0.1)
- How to normalize spin-ontology to OWL2 ontology (replace SPARQL-queries with their text (
sp:text) representation) see com.github.owlcs.ontapi.tests.GraphTransformersTest#testLoadSpinLibraryWithTransformation test-method.
10) ONT-D2RQ (a virtual graph backed to relational databases)
This API allows to represent a SQL database as RDF Graph, and, sequentially, as OWL2 ontology.
// JDBC Connection URI:
String uri = "jdbc:mysql://127.0.0.1/iswc";
// DB Credentials:
String u = "root";
String p = null;
// OWL manager:
OntologyManager manager = OntManagers.createONT();
// a connectivity to database:
OWLOntologyDocumentSource source = D2RQGraphDocumentSource.create(IRI.create(uri), u, p);
// connect, load db schema and assign ontology id to the result anonymous ontology:
OntGraphModel schema = manager.loadOntologyFromOntologyDocument(source).asGraphModel();
schema.setID("d2rq://from-mysql-iswc");
// by way of example, pass all db content into memory and print all OWLAxioms:
Graph inMemory = D2RQGraphUtils.toMemory(schema.getBaseGraph());
OntGraphModel withData = OntModelFactory.createModel(inMemory);
List<OWLAxiom> axioms = AxiomType.AXIOM_TYPES.stream()
.map(AxiomParserProvider::get)
.flatMap(t -> t.axioms(withData))
.map(ONTObject::getObject)
.collect(Collectors.toList());
// print:
axioms.forEach(System.out::println);
withData.write(System.out, "ttl");