Search code examples
javasparqlowlpelletapache-jena

Jena Sparql only return direct superclass of instance


I'm using Jena in Java with Pellet as the reasoner. Now I need to query the class of a specific URI, but the problem is is that I don't know before hand what kind of instance it is, in what kind of class hierarchy, so I can't use filter options. When using:

SELECT * WHERE {<" + uri + "> rdf:type ?x}

It returns all superclasses. My hierarchy for this specific example looks like:

-Thing
 -Person
  -Adult
 -Animal
  -Dog

Every class has multiple instances. I don't know what kind of instance I'm querying beforehand. But let's say for example I'm querying an URI of an instance who is a type Dog. It will also return Animal and Thing. But I only want it to return Dog. Is that possible? Using LIMIT 1 only returns the direct superclass.


Solution

  • There is an easy way to do this with Jena which provides a special predicate to query for direct types so in your code you can generate the query as follows:

      "SELECT * { <" + ind + "> <" + ReasonerVocabulary.directRDFType + "> ?type }"
    

    or simply use the URI for this predicate directly in the query:

      SELECT * { <ind> <urn:x-hp-direct-predicate:http_//www.w3.org/1999/02/22-rdf-syntax-ns#type> ?type }
    

    It is also possible to write a rather inefficient but portable SPARQL query that will query direct types:

      PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> 
      PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> 
      PREFIX owl: <http://www.w3.org/2002/07/owl#> 
      SELECT * { 
        <ind> rdf:type ?directType .
        FILTER NOT EXISTS {
          <ind> rdf:type ?type .
          ?type rdfs:subClassOf ?directType .
          FILTER NOT EXISTS {
             ?type owl:equivalentClass ?directType .
          }
        }
      }
    

    A class is a direct type of an individual if there is no other type of the individual that is a subclass of this type. But a direct type might have equivalent classes. To handle these cases we have to use double negation in the query. This query is inefficient because it first retrieves all the types of the individual and filters the ones that are not direct. But on the plus side you can use it with systems other than Jena that does not provide a dedicated direct type predicate.