How to get Individual name from Node value in Jena

2019-07-30 01:13发布

问题:

I am facing a problem extracting the Individual's name from the Jena Graph (RDF Inference Model with Generic Rule Reasoner and OntSpec is RDFS_MEM_RDFS_INF ). It may be a simple case but I am not able to find proper tutorial online to get this done (new to jena rules). What is the proper api to call for in this case?

infStmts = pModel.listStatements().filterKeep( new Filter<Statement>() {
        @Override
        public boolean accept(Statement o) {                
            boolean ex = false;
            Property prop1 = pModel.getProperty(prefix + "hasPropertyP1");
            String predicateName  = o.asTriple().getPredicate().getLocalName();             
            if(predicateName.equalsIgnoreCase(prop1.getLocalName()) )                   
                ex = true;                
            return ex;

        }
    });

    Statement s = infStmts.next();
    Statement st = ResourceFactory.createStatement(s.getSubject(), s.getPredicate(), s.getObject());
    System.out.println(st.getSubject().toString() + "****" + pModel.getRDFNode(st.getSubject().asNode()).as(Individual.class));
Exception in thread "Thread-37" com.hp.hpl.jena.ontology.ConversionException: Cannot convert node 4e62503a:14b01762f42:-7eea 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)
...

The Jena rules file has the following rule

[rule: ( :Subject1 :hasPropertyP2 :Object1) ->
       ( ?x rdf:type :Class1)
       ( ?x :hasPropertyP1 :Object2)]

I need the value of ?x in terms of individuals' names

回答1:

In the following line you're trying to get the the subject, then get a Node version of it, and then get an Individual version of it.

System.out.println(st.getSubject().toString() + "****" + pModel.getRDFNode(st.getSubject().asNode()).as(Individual.class));

You're doing this for the subject of every triple in the graph. The documentation for Individual says:

In order to be recognised as an individual, rather than a generic resource, at least one rdf:type statement, referring to a known class, must be present in the model.

The error message you're getting,

Cannot convert node 4e62503a:14b01762f42:-7eea to Individual

indicates that somewhere in the graph, there's a triple whose subject is a blank node. Apparently one of those blank nodes doesn't meet the criteria for being an Individual. You need to check whether the node can be an Individual before doing as(Individual.class). You can check first with canAs(Individual.class).

However, you need to be aware that just because the rules file only has one rule does not mean that all the triples in the inference graph will have been generated by it. There can be lots more triples in the inference graph.

A better way to do what you're trying to do would be to list the statements with the property that you care about using Model.listStatements, and then check whether the subject is a URI resource, and if is, then get it as a URI resource and extract its URI:

Property p1 = model.createProperty(...)
StmtIterator stmts = model.listStatements(null,p1,null); 
while ( stmts.hasNext() ) {
  Statement stmt = stmts.next();
  RDFNode subject = stmt.getSubject();
  if ( subject.isURIResource() ) {
    System.out.println( "Subject URI is: "+ subject.asResource().getURI() );
  }
}