Read class restriction or axiom via OWL API 5

owl_read_restriction_properties_thumb

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:

Protégé Ontology Screenshot
Protégé Ontology Screenshot

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();
	}
}
  1. Read the example ontology via the OWLOntologyManager
  2. Retrieve all classes contained in the ontology using ontology.classesInSignature(). This returns a stream which requires Java 1.8
  3. For each class retrieve the OWLAxiom via ontology.axioms( oc )
  4. Create an OWLObjectVisitor to visit the OWLSubClassOfAxiom surrounding the owl:Restriction
  5. Get the superclass of the OWLSubClassOfAxiom and create another OWLObjectVisitor to retrieve the owl:Restriction
  6. 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.

Facebooktwitterredditpinterestlinkedinmail

Related posts

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.