HI all, A recent StackOverflow question [1] mentioned that OWL2's
owl:NamedIndividual couldn't be converted to an OntClass (presumably
for an OntModel with a OntModelSpec with an OWL profile). Ian
Dickinson pointed out that this arises from the fact that Jena's
reasoners don't yet support OWL2, so owl:NamedIndividual isn't known
to be an rdfs:Class. (I know OWL2 support isn't currently planned,
but that contributions are welcome. :) This isn't the question here.)
I was surprised to learn that things which are rdfs:Classes can be
converted to OntClasses, even if they are not owl:Classes.
I understand that Jena is being rather permissive here, and that the
implementation is intentional. The code that checks whether something
can be converted to an OntClass for the OWLDLProfile clearly checks
for RDFS.Class, RDFS.Datatype, and also anything that has been used as
the RDFS.domain or RDFS.range of a property (from OWLDLProfile.java):
{ OntClass.class, new SupportsCheck() {
@Override
public boolean doCheck( Node n, EnhGraph eg ) {
Graph g = eg.asGraph();
return hasType( n, eg, new Resource[] {OWL.Class,
OWL.Restriction, RDFS.Class, RDFS.Datatype} ) ||
// These are common cases that we should support
n.equals( OWL.Thing.asNode() ) ||
n.equals( OWL.Nothing.asNode() ) ||
g.contains( Node.ANY, RDFS.domain.asNode(), n ) ||
g.contains( Node.ANY, RDFS.range.asNode(), n ) ||
g.contains( n, OWL.intersectionOf.asNode(),
Node.ANY ) ||
g.contains( n, OWL.unionOf.asNode(), Node.ANY ) ||
g.contains( n, OWL.complementOf.asNode(), Node.ANY )
;
}
}
This leads to some surprising results in some situations that are
surprising to me. For instance, it means that a Resource can be
viewed as an OntClass, but that trying to listInstances of the
OntClass results in more conversion errors. For instance, the
following code gets an OntClass for OWL.Class, and then throws an
error when owl:Thing can't be converted to an Individual:
import com.hp.hpl.jena.ontology.OntClass;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.ontology.OntModelSpec;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.vocabulary.OWL;
public class OntClassExample {
public static void main(String[] args) {
OntModel om = ModelFactory.createOntologyModel(
OntModelSpec.OWL_DL_MEM_RULE_INF );
OntClass owlClass = OWL.Class.inModel( om ).as( OntClass.class
);
System.out.println( "OntClass: "+owlClass );
System.out.println( "Instances:
"+owlClass.listInstances().toList() );
}
}
Output is:
OntClass: http://www.w3.org/2002/07/owl#Class
Exception in thread "main"
com.hp.hpl.jena.ontology.ConversionException: Cannot convert node
http://www.w3.org/2002/07/owl#Thing to Individual
at
com.hp.hpl.jena.ontology.impl.IndividualImpl$1.wrap(IndividualImpl.java:61)
at com.hp.hpl.jena.enhanced.EnhNode.convertTo(EnhNode.java:152)
at com.hp.hpl.jena.enhanced.EnhNode.convertTo(EnhNode.java:31)
at com.hp.hpl.jena.enhanced.Polymorphic.asInternal(Polymorphic.java:62)
at com.hp.hpl.jena.enhanced.EnhNode.as(EnhNode.java:107)
at
com.hp.hpl.jena.ontology.impl.OntResourceImpl$SubjectAsMapper.map1(OntResourceImpl.java:1676)
at
com.hp.hpl.jena.ontology.impl.OntResourceImpl$SubjectAsMapper.map1(OntResourceImpl.java:1670)
at com.hp.hpl.jena.util.iterator.Map1Iterator.next(Map1Iterator.java:45)
at
com.hp.hpl.jena.util.iterator.WrappedIterator.next(WrappedIterator.java:94)
at
com.hp.hpl.jena.util.iterator.FilterIterator.hasNext(FilterIterator.java:55)
at
com.hp.hpl.jena.util.iterator.WrappedIterator.hasNext(WrappedIterator.java:90)
at
com.hp.hpl.jena.util.iterator.FilterIterator.hasNext(FilterIterator.java:54)
at
com.hp.hpl.jena.util.iterator.NiceIterator.asList(NiceIterator.java:217)
at
com.hp.hpl.jena.util.iterator.NiceIterator.toList(NiceIterator.java:190)
at OntClassExample.main(OntClassExample.java:24)
This seems to be by design, but now I'm curious whether allowing
rdfs:Classes to be converted to OntClasses in OWLDL OntModels is
useful in practice and, if so, for what purposes? This doesn't really
affect me one way or the other, but it was behavior that surprised me,
and I wonder whether not including the rdfs:Classes (and every
rdfs:domain and rdfs:range) for the OWLDLProfile might lead to less
surprise.
Thanks for reading,
Joshua Taylor
[1] http://stackoverflow.com/q/17445678/1281433
--
Joshua Taylor, http://www.cs.rpi.edu/~tayloj/