Как использовать метод Jena OntModel.listClasses()?

Я пытаюсь использовать Jena OntModel, чтобы получить прямые отношения онтологии. Проблемы возникают из-за listClasses().

Я некоторое время искал советы в сети, но не нашел подходящего ответа на мою проблему.

Итак, вот полный пример с минимальными данными и кодом, показывающий, что не так.

У меня есть, например, эта базовая онтология (в формате N-Triple):

<http://weblab.ow2.org/wookie#Anti-social_behaviour> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://weblab.ow2.org/wookie#CriminalEvent>.
<http://weblab.ow2.org/wookie#Robbery> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://weblab.ow2.org/wookie#CriminalEvent>.
<http://weblab.ow2.org/wookie#Vehicle_crime> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://weblab.ow2.org/wookie#CriminalEvent>.
<http://weblab.ow2.org/wookie#Bicycle_theft> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://weblab.ow2.org/wookie#CriminalEvent>.
<http://weblab.ow2.org/wookie#CriminalEvent> <http://www.w3.org/2000/01/rdf-schema#subClassOf>  <http://weblab.ow2.org/wookie#Event>.
<http://weblab.ow2.org/wookie#Event> <http://www.w3.org/2000/01/rdf-schema#subClassOf>  <http://weblab.ow2.org/wookie#WookieThing>.
<http://weblab.ow2.org/wookie#Event> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#Class>.

Я в основном хотел бы иметь возможность получить все классы и для каждого класса получить подклассы.

Я использую следующий код JAVA:

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import com.hp.hpl.jena.ontology.OntClass;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QueryFactory;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.util.FileManager;

public class Main {

    public static void main(final String [] argv) throws FileNotFoundException, IOException {

        final OntModel model = ModelFactory.createOntologyModel();

        model.read(FileManager.get().open("./src/test/resources/eventOnto.n3"), "", "N-TRIPLE");

        // This part allows to check that the ontology model is really loaded and that inference is
        // correctly done. WORKING
        final List<Statement> statements = model.listStatements().toList();
        Collections.sort(statements, new Comparator<Statement>() {
            @Override
            public int compare(final Statement o1, final Statement o2) {
                return o1.toString().compareTo(o2.toString());
            }
        });

        for (final Statement statement : statements) {
            System.out.println(statement);
        }

        System.out.println("-------------------------------------------------");

        // Listing all the classes.
        final List<OntClass> classes = model.listClasses().toList();
        for (final OntClass ontclass : classes) {
            System.out.println(ontclass);
        }

        System.out.println("-------------------------------------------------");

        // Bug got nothing. So try with a SPARQL query...
        final Query query = QueryFactory.create("PREFIX rdf:<http://www.w3.org/2000/01/rdf-schema#> SELECT distinct ?class WHERE {?class a rdf:Class.}");
        final ResultSet queryResult = QueryExecutionFactory.create(query, model).execSelect();
        while (queryResult.hasNext()) {
            System.out.println(queryResult.next());
        }
        // and got many results...

    }

Отпечатки показывают, что онтологическая модель правильно загружена и сделан основной вывод. Это также показывает, что getClasses() ничего не возвращает, в то время как запрос SPARQL, запрашивающий классы, получает каждый отдельный класс.

[http://weblab.ow2.org/wookie#Anti-social_behaviour, http://www.w3.org/1999/02/22-rdf-syntax-ns#type, http://www.w3.org/2000/01/rdf-schema#Class]
[http://weblab.ow2.org/wookie#Anti-social_behaviour, http://www.w3.org/1999/02/22-rdf-syntax-ns#type, http://www.w3.org/2000/01/rdf-schema#Resource]
[http://weblab.ow2.org/wookie#Anti-social_behaviour, http://www.w3.org/2000/01/rdf-schema#subClassOf, http://weblab.ow2.org/wookie#Anti-social_behaviour]
[http://weblab.ow2.org/wookie#Anti-social_behaviour, http://www.w3.org/2000/01/rdf-schema#subClassOf, http://weblab.ow2.org/wookie#CriminalEvent]
[http://weblab.ow2.org/wookie#Anti-social_behaviour, http://www.w3.org/2000/01/rdf-schema#subClassOf, http://weblab.ow2.org/wookie#Event]
[http://weblab.ow2.org/wookie#Anti-social_behaviour, http://www.w3.org/2000/01/rdf-schema#subClassOf, http://weblab.ow2.org/wookie#WookieThing]
[http://weblab.ow2.org/wookie#Anti-social_behaviour, http://www.w3.org/2000/01/rdf-schema#subClassOf, http://www.w3.org/2000/01/rdf-schema#Resource]
[http://weblab.ow2.org/wookie#Anti-social_behaviour, http://www.w3.org/2000/01/rdf-schema#subClassOf, http://www.w3.org/2002/07/owl#Thing]
...(many other lines)...
-------------------------------------------------
-------------------------------------------------
( ?class = rdf:Property )
( ?class = rdf:List )
( ?class = rdfs:Resource )
( ?class = rdfs:Class )
( ?class = rdf:Statement )
( ?class = rdfs:Literal )
( ?class = <http://weblab.ow2.org/wookie#Event> )
( ?class = rdf:XMLLiteral )
( ?class = owl:Thing )
( ?class = <http://weblab.ow2.org/wookie#WookieThing> )
( ?class = <http://weblab.ow2.org/wookie#CriminalEvent> )
( ?class = rdfs:Container )
( ?class = <http://weblab.ow2.org/wookie#Robbery> )
( ?class = <http://weblab.ow2.org/wookie#Bicycle_theft> )
( ?class = rdf:Seq )
( ?class = rdf:Alt )
( ?class = <http://weblab.ow2.org/wookie#Anti-social_behaviour> )
( ?class = <http://weblab.ow2.org/wookie#Vehicle_crime> )
( ?class = rdfs:ContainerMembershipProperty )
( ?class = rdf:Bag )
( ?class = rdfs:Datatype )

Кто-нибудь знает, почему OntModel.getClasses() ничего не возвращает?


person Arthur Vaïsse    schedule 28.07.2014    source источник


Ответы (1)


Вы не получаете результатов по двум причинам.

  1. Профиль онтологии по умолчанию — это профиль OWL, поэтому вы получаете модель OWL, использующую getOntologyModel без определенного OntModelSpec. Вместо этого вам, вероятно, следует использовать онтологическую модель RDFS. Это заставит listClasses искать экземпляры rdfs:Class, а не owl:Class. Тем не менее, это все равно даст вам только один результат, потому что вы объявили только одну вещь как rdfs:Class.
  2. Вы объявили только одну вещь как rdfs:Class, а остальные должны быть выведены как rdfs:Classes на основании того факта, что они являются подклассами чего-то другого. Это означает, что вам нужно использовать модель вывода. В этом случае вам, вероятно, нужна модель логического вывода RDFS, но поскольку (некоторые) средства рассуждения Jena OWL включают правила RDFS, вы также можете использовать модель OWL.

Вот код, который загружает ваши данные в несколько различных типов моделей и показывает результаты listClasses:

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

import org.apache.jena.riot.Lang;
import org.apache.jena.riot.RDFDataMgr;

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.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;

public class ListClassesExample {
    public static void main(String[] args) throws IOException {
        String content = 
                "<http://weblab.ow2.org/wookie#Anti-social_behaviour> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://weblab.ow2.org/wookie#CriminalEvent>.\n" +
                "<http://weblab.ow2.org/wookie#Robbery> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://weblab.ow2.org/wookie#CriminalEvent>.\n" +
                "<http://weblab.ow2.org/wookie#Vehicle_crime> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://weblab.ow2.org/wookie#CriminalEvent>.\n" +
                "<http://weblab.ow2.org/wookie#Bicycle_theft> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://weblab.ow2.org/wookie#CriminalEvent>.\n" +
                "<http://weblab.ow2.org/wookie#CriminalEvent> <http://www.w3.org/2000/01/rdf-schema#subClassOf>  <http://weblab.ow2.org/wookie#Event>.\n" +
                "<http://weblab.ow2.org/wookie#Event> <http://www.w3.org/2000/01/rdf-schema#subClassOf>  <http://weblab.ow2.org/wookie#WookieThing>.\n" +
                "<http://weblab.ow2.org/wookie#Event> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#Class>.";

        final Model base = ModelFactory.createDefaultModel();
        try ( InputStream in = new ByteArrayInputStream( content.getBytes() )) { 
            RDFDataMgr.read( base, in, Lang.NTRIPLES );
        }

        System.out.println( "== OWL Classes (no inference) ==" );
        OntModel owlOntology = ModelFactory.createOntologyModel( OntModelSpec.OWL_MEM, base );
        for ( OntClass klass : owlOntology.listClasses().toList() ) {
            System.out.println( klass );
        }

        System.out.println( "== RDFS Classes (no inference) ==" );
        OntModel rdfsOntology = ModelFactory.createOntologyModel( OntModelSpec.RDFS_MEM, base );
        for ( OntClass klass : rdfsOntology.listClasses().toList() ) {
            System.out.println( klass );
        }

        System.out.println( "== RDFS Classes (with inference) ==" );
        OntModel rdfsOntologyInf = ModelFactory.createOntologyModel( OntModelSpec.RDFS_MEM_RDFS_INF, base );
        for ( OntClass klass : rdfsOntologyInf.listClasses().toList() ) {
            System.out.println( klass );
        }

        System.out.println( "== End ==");
    }
}
== OWL Classes (no inference) ==
== RDFS Classes (no inference) ==
http://weblab.ow2.org/wookie#Event
== RDFS Classes (with inference) ==
http://www.w3.org/1999/02/22-rdf-syntax-ns#Property
http://www.w3.org/1999/02/22-rdf-syntax-ns#List
http://www.w3.org/2000/01/rdf-schema#Resource
http://www.w3.org/2000/01/rdf-schema#Class
http://www.w3.org/1999/02/22-rdf-syntax-ns#Statement
http://www.w3.org/2000/01/rdf-schema#Literal
http://weblab.ow2.org/wookie#Event
http://weblab.ow2.org/wookie#WookieThing
http://weblab.ow2.org/wookie#CriminalEvent
http://www.w3.org/2000/01/rdf-schema#Container
http://weblab.ow2.org/wookie#Robbery
http://weblab.ow2.org/wookie#Bicycle_theft
http://www.w3.org/1999/02/22-rdf-syntax-ns#Seq
http://www.w3.org/1999/02/22-rdf-syntax-ns#Alt
http://weblab.ow2.org/wookie#Anti-social_behaviour
http://weblab.ow2.org/wookie#Vehicle_crime
http://www.w3.org/2000/01/rdf-schema#ContainerMembershipProperty
http://www.w3.org/1999/02/22-rdf-syntax-ns#Bag
http://www.w3.org/2000/01/rdf-schema#Datatype
http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral
== End ==

Здесь есть некоторые классы, которые вы не упомянули, потому что они влекут за собой аксиомы RDFS. Если вам просто нужны вещи, объявленные как rdfs:Classes в ваших данных, и их подклассы, вы можете использовать запрос SPARQL:

String query = "\n" +
        "prefix rdfs: <"+RDFS.getURI()+">\n" +
        "\n" +
        "select distinct ?class where {\n" +
        "  { ?class a rdfs:Class } union\n" +
        "  { ?class rdfs:subClassOf|^rdfs:subClassOf [] }\n" +
        "}";
ResultSet results = QueryExecutionFactory.create( query, base ).execSelect();
System.out.println( query );
ResultSetFormatter.out( results );
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>

select distinct ?class where {
  { ?class a rdfs:Class } union
  { ?class rdfs:subClassOf|^rdfs:subClassOf [] }
}
--------------------------------------------------------
| class                                                |
========================================================
| <http://weblab.ow2.org/wookie#Event>                 |
| <http://weblab.ow2.org/wookie#Bicycle_theft>         |
| <http://weblab.ow2.org/wookie#Anti-social_behaviour> |
| <http://weblab.ow2.org/wookie#WookieThing>           |
| <http://weblab.ow2.org/wookie#Vehicle_crime>         |
| <http://weblab.ow2.org/wookie#CriminalEvent>         |
| <http://weblab.ow2.org/wookie#Robbery>               |
--------------------------------------------------------
person Joshua Taylor    schedule 28.07.2014
comment
Спасибо за полный ответ. Прочитав документ еще раз более внимательно, он был объяснен в [1], части руководства JENA. Благодаря вам я теперь могу собрать весь класс и получить все прямые подклассы класса, и это было моей основной целью. Спасибо еще раз! [1]:jena.apache.org/documentation/ontology/ - person Arthur Vaïsse; 29.07.2014