-->

jena api get range of ObjectProperty

2019-09-08 17:19发布

问题:

I've and OWL file and I can explore it and navigate through classes and properties but I can't retrieve correct range of ObjectProperty. This is part of my OWL file:

<owl:ObjectProperty rdf:about="&aat;aat2209_located_in">
        <rdfs:label xml:lang="en">located in</rdfs:label>
        <rdfs:label xml:lang="it">si trova in</rdfs:label>
        <rdfs:comment xml:lang="en">The property defines a relationship between places or places and things</rdfs:comment>
        <rdfs:comment xml:lang="it">La proprietà definisce la relazione tra luoghi o tra luoghi e cose</rdfs:comment>
        <rdfs:domain>
            <owl:Class>
                <owl:unionOf rdf:parseType="Collection">
                    <rdf:Description rdf:about="&dbpedia-owl;Artwork"/>
                    <rdf:Description rdf:about="&dbpedia-owl;Cave"/>
                </owl:unionOf>
            </owl:Class>
        </rdfs:domain>
        <rdfs:range>
            <owl:Class>
                <owl:unionOf rdf:parseType="Collection">
                    <rdf:Description rdf:about="&lodmt;ArchaeologicalSite"/>
                    <rdf:Description rdf:about="&dbpedia-owl;Building"/>
                </owl:unionOf>
            </owl:Class>
        </rdfs:range>
    </owl:ObjectProperty>

And this is part of my code to explore OWL file

...    
OntModel inf = ModelFactory.createOntologyModel(OntModelSpec.OWL_DL_MEM_RULE_INF);
            InputStream in =getClass().getResourceAsStream("/"+DATA_IRI);
            inf.read(in, "");
            OntClass obj = inf.getOntClass(uri);
            ExtendedIterator<OntProperty> propIter = obj.listDeclaredProperties(false);
            if(propIter.hasNext()){
                while (propIter.hasNext()) {
                    Set<PropertyModel> properties = new HashSet<PropertyModel>();
                    final OntProperty ontProperty = (OntProperty) propIter.next();
                    ExtendedIterator<? extends OntProperty> eqProp = ontProperty.listEquivalentProperties();
                    if(eqProp.hasNext()){
                        while (eqProp.hasNext()) {
                            OntProperty property = (OntProperty) eqProp.next();
                            PropertyModel propModel = new PropertyModel();
                            propModel.setLabel(property.getLocalName());
                            propModel.setUri(property.getURI());
                            propModel.setRange(property.getRange().getLocalName());
                            properties.add(propModel);
                        }
                    }
    ...

Everytime I call property.getRange() I've this result: http://www.w3.org/2002/07/owl#Thing.

Anyone help me?

回答1:

It's ever so much easier if you provide complete but minimal data to work with. In this case, I've modified your data to be the following, which is complete in that it's a loadable RDF document, and minimal in that it only contains the object property declaration and the range axiom.

<rdf:RDF
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:owl="http://www.w3.org/2002/07/owl#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
<owl:ObjectProperty rdf:about="http://stackoverflow.com/q/24250198/1281433/aat2209_located_in">
        <rdfs:range>
            <owl:Class>
                <owl:unionOf rdf:parseType="Collection">
                    <rdf:Description rdf:about="http://stackoverflow.com/q/24250198/1281433/ArchaeologicalSite"/>
                    <rdf:Description rdf:about="http://stackoverflow.com/q/24250198/1281433/Building"/>
                </owl:unionOf>
            </owl:Class>
        </rdfs:range>
    </owl:ObjectProperty>
</rdf:RDF>

The following code loads it and shows the range(s) of the property:

import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.ontology.OntModelSpec;
import com.hp.hpl.jena.ontology.OntProperty;
import com.hp.hpl.jena.ontology.OntResource;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.util.iterator.ExtendedIterator;

public class RangeExample {
    public static void main(String[] args) {
        OntModel model = ModelFactory.createOntologyModel( OntModelSpec.OWL_DL_RULE_MEM_INF );
        model.read( "..../data.owl" );
        OntProperty locatedIn = model.getOntProperty( "http://stackoverflow.com/q/24250198/1281433/aat2209_located_in" );
        ExtendedIterator<? extends OntResource> ranges = locatedIn.listRange();
        while ( ranges.hasNext() ) { 
            System.out.println( ranges.next() );
        }
    }
}

The output for me is

http://www.w3.org/2002/07/owl#Thing
-3e020093:146a7247e66:-7ffb
http://www.w3.org/2000/01/rdf-schema#Resource

owl:Thing and rdfs:Resource are there because anytime you have x located_in y, you can be sure that y is an owl:Thing and an rdfs:Resource, since located_in is an object property. The other one, -3e020093:146a7247e66:-7ffb, is the identitifier of the RDF blank node that is the OWL union class expression.

Why aren't other classes returned?

Based on the following comment, it sounds like a bit more discussion is needed.

I obtain same result, but I would obtain ArchaeologicalSite and Building as result.

You asked for the range(s) of a particular object property that you declared. In OWL, a range of a property p is any class D such that "if p(x,y), then D(y)". That is, in RDF terms, if you a property p's has D as a range, then whenever there is a triple x p y, then you can also infer the triple y rdf:type D. This is the rule:

x p y     p rdfs:range D
-----------------------
   y rdf:type D

The range that you're asking about is a union class. An instance of the rule for your class would be like:

x located_in y     located_in rdfs:range (ArchaeologicalSite OR Building)
-------------------------------------------------------------------------
     y rdf:type (ArchaeologicalSite OR Building)

It would not make sense to infer that

y rdf:type ArchaeologicalSite

or that

y rdf:type Building

because that's more information than you have in x located_in y. For analogy, consider this example:

  1. You can have soup or salad for your appetizer. (The range of hasAppetizer is "soup or salad".)
  2. You had some unknown x for your appetizer.

From those, I can infer that x is either soup or salad, but I can't infer which particular one. Thus "soup or salad" is a range of hasAppetizer, but neither soup nor salad alone is.



标签: rdf jena owl rdfs