In this tutorial we demonstrate how to read a restriction or axiom from a OWLClass using the OWL API 5 and the visitor pattern. The example maven project is available on Github.
We use the OWL API version 5.1.4 and a small example ontology.
1. Prerequisites
- Install Maven to build the project (explained here)
- Java 1.8 ( OWL API uses streams etc. )
- Some understanding of OWL and ontologies in general
2. The example ontology
The ontology is only for demonstration purposes. It is about a vehicle (truck) that has some components like tires, doors and a steering wheel. Have a look at the important part:
[...] <owl:Class rdf:about="http://www.tutorial-academy.com/semantics#Truck"> <rdfs:subClassOf rdf:resource="http://www.tutorial-academy.com/semantics#Vehicle"/> <rdfs:subClassOf> <owl:Restriction> <owl:onProperty rdf:resource="http://www.tutorial-academy.com/semantics#hasComponent"/> <owl:someValuesFrom rdf:resource="http://www.tutorial-academy.com/semantics#Door"/> </owl:Restriction> </rdfs:subClassOf> <rdfs:subClassOf> <owl:Restriction> <owl:onProperty rdf:resource="http://www.tutorial-academy.com/semantics#hasComponent"/> <owl:minQualifiedCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">4</owl:minQualifiedCardinality> <owl:onClass rdf:resource="http://www.tutorial-academy.com/semantics#Tire"/> </owl:Restriction> </rdfs:subClassOf> <rdfs:subClassOf> <owl:Restriction> <owl:onProperty rdf:resource="http://www.tutorial-academy.com/semantics#hasComponent"/> <owl:qualifiedCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:qualifiedCardinality> <owl:onClass rdf:resource="http://www.tutorial-academy.com/semantics#SteeringWheel"/> </owl:Restriction> </rdfs:subClassOf> <rdfs:subClassOf> <owl:Restriction> <owl:onProperty rdf:resource="http://www.tutorial-academy.com/semantics#hasComponent"/> <owl:maxQualifiedCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">12</owl:maxQualifiedCardinality> <owl:onClass rdf:resource="http://www.tutorial-academy.com/semantics#Tire"/> </owl:Restriction> </rdfs:subClassOf> </owl:Class> [...]
We use the following restriction properties:
- SomeValuesFrom (e.g. at least one door)
- ExactCardinalty ( e.g. exactly one steering wheel)
- MinCardinality (e.g. at least 4 tires)
- MaxCardinality (e.g. at max 12 tires)
Check out this Protégé Screenshot for better visualization:

3. The example code
The code is pretty simple and basically reads the example ontology first. Afterwards, the restrictions and axioms are read for each class and printed to the console.
public class App { public static void main( String[] args ) throws OWLOntologyCreationException, FileNotFoundException { // load ontology OWLOntologyManager manager = OWLManager.createOWLOntologyManager(); OWLOntology ontology = manager.loadOntologyFromOntologyDocument( new File( getRelativeResourcePath( "vehicle.owl" ) ) ); System.out.println( "Read and classes their axioms...\n" ); // get all classes in the ontology for( OWLClass oc : ontology.classesInSignature().collect( Collectors.toSet() ) ) { System.out.println( "Class: " + oc.toString() ); // get all axioms for each class for( OWLAxiom axiom : ontology.axioms( oc ).collect( Collectors.toSet() ) ) { System.out.println( "\tAxiom: " + axiom.toString() ); // create an object visitor to get to the subClass restrictions axiom.accept( new OWLObjectVisitor() { // found the subClassOf axiom public void visit( OWLSubClassOfAxiom subClassAxiom ) { // create an object visitor to read the underlying (subClassOf) restrictions subClassAxiom.getSuperClass().accept( new OWLObjectVisitor() { public void visit( OWLObjectSomeValuesFrom someValuesFromAxiom ) { printQuantifiedRestriction( oc, someValuesFromAxiom ); } public void visit( OWLObjectExactCardinality exactCardinalityAxiom ) { printCardinalityRestriction( oc, exactCardinalityAxiom ); } public void visit( OWLObjectMinCardinality minCardinalityAxiom ) { printCardinalityRestriction( oc, minCardinalityAxiom ); } public void visit( OWLObjectMaxCardinality maxCardinalityAxiom ) { printCardinalityRestriction( oc, maxCardinalityAxiom ); } // TODO: same for AllValuesFrom etc. }); } }); } System.out.println(); } } public static void printQuantifiedRestriction( OWLClass oc, OWLQuantifiedObjectRestriction restriction ) { System.out.println( "\t\tClass: " + oc.toString() ); System.out.println( "\t\tClassExpressionType: " + restriction.getClassExpressionType().toString() ); System.out.println( "\t\tProperty: "+ restriction.getProperty().toString() ); System.out.println( "\t\tObject: " + restriction.getFiller().toString() ); System.out.println(); } public static void printCardinalityRestriction( OWLClass oc, OWLObjectCardinalityRestriction restriction ) { System.out.println( "\t\tClass: " + oc.toString() ); System.out.println( "\t\tClassExpressionType: " + restriction.getClassExpressionType().toString() ); System.out.println( "\t\tCardinality: " + restriction.getCardinality() ); System.out.println( "\t\tProperty: "+ restriction.getProperty().toString() ); System.out.println( "\t\tObject: " + restriction.getFiller().toString() ); System.out.println(); } // resolve maven specific path for resources public static String getRelativeResourcePath( String resource ) throws FileNotFoundException { if( resource == null || resource.equals("") ) throw new IllegalArgumentException( resource ); URL url = App.class.getClassLoader().getResource( resource ); if( url == null ) throw new FileNotFoundException( resource ); return url.getPath(); } }
- Read the example ontology via the OWLOntologyManager
- Retrieve all classes contained in the ontology using ontology.classesInSignature(). This returns a stream which requires Java 1.8
- For each class retrieve the OWLAxiom via ontology.axioms( oc )
- Create an OWLObjectVisitor to visit the OWLSubClassOfAxiom surrounding the owl:Restriction
- Get the superclass of the OWLSubClassOfAxiom and create another OWLObjectVisitor to retrieve the owl:Restriction
- Print / Save / Process the contained values
4. Restriction output
The generated output looks like this:
Class: <http://www.tutorial-academy.com/semantics#Truck> Axiom: SubClassOf(<http://www.tutorial-academy.com/semantics#Truck> ObjectSomeValuesFrom(<http://www.tutorial-academy.com/semantics#hasComponent> <http://www.tutorial-academy.com/semantics#Door>)) Class: <http://www.tutorial-academy.com/semantics#Truck> ClassExpressionType: ObjectSomeValuesFrom Property: <http://www.tutorial-academy.com/semantics#hasComponent> Object: <http://www.tutorial-academy.com/semantics#Door> Axiom: SubClassOf(<http://www.tutorial-academy.com/semantics#Truck> ObjectExactCardinality(1 <http://www.tutorial-academy.com/semantics#hasComponent> <http://www.tutorial-academy.com/semantics#SteeringWheel>)) Class: <http://www.tutorial-academy.com/semantics#Truck> ClassExpressionType: ObjectExactCardinality Cardinality: 1 Property: <http://www.tutorial-academy.com/semantics#hasComponent> Object: <http://www.tutorial-academy.com/semantics#SteeringWheel> Axiom: SubClassOf(<http://www.tutorial-academy.com/semantics#Truck> ObjectMaxCardinality(12 <http://www.tutorial-academy.com/semantics#hasComponent> <http://www.tutorial-academy.com/semantics#Tire>)) Class: <http://www.tutorial-academy.com/semantics#Truck> ClassExpressionType: ObjectMaxCardinality Cardinality: 12 Property: <http://www.tutorial-academy.com/semantics#hasComponent> Object: <http://www.tutorial-academy.com/semantics#Tire> Axiom: SubClassOf(<http://www.tutorial-academy.com/semantics#Truck> <http://www.tutorial-academy.com/semantics#Vehicle>) Axiom: SubClassOf(<http://www.tutorial-academy.com/semantics#Truck> ObjectMinCardinality(4 <http://www.tutorial-academy.com/semantics#hasComponent> <http://www.tutorial-academy.com/semantics#Tire>)) Class: <http://www.tutorial-academy.com/semantics#Truck> ClassExpressionType: ObjectMinCardinality Cardinality: 4 Property: <http://www.tutorial-academy.com/semantics#hasComponent> Object: <http://www.tutorial-academy.com/semantics#Tire>
As you can see we have access to all the important properties. Cardinality, the expression type as well as the property and the object.
5.Conclusion
We had to read that data in order to transform OWL data into another format (OPC-UA). Normally, you probably do not have to read that data. You would rather add axioms, infer and reason over data.
The visitor pattern is something to read about and get used to, but once understood it is a very powerful tool.
The OWL API 5 has a lot of changes in comparison to version 4. In our understanding, there are just very few good tutorials / documentation examples out there yet.
If you have questions or problems, feel free to comment and ask.





