问题
I'm getting a strange effect in Jena 2.5.5 (on Linux) where I am playing around with the inference API. The following code is a stripped down version. I am creating an initially empty Model and a generic rule reasoner. I add a reflexivity rule for a certain statement. I attach the reasoner to the model to get an InfModel. Then I create the matching statement and add it to the Model.
Result: InfModel contains both the statement and its reverse. So far so good, that's what it's supposed to do.
Now, when I System.out.println()
the InfModel prior to adding the matching statement to Model, the result is completely different: the rule seems not to fire and thus, InfModel will end up not containing the reverse of the original statement.
How does writing the model to the console change the functionality of the code? Is this behavior documented?
import java.util.*;
import com.hp.hpl.jena.rdf.model.*;
import com.hp.hpl.jena.reasoner.rulesys.*;
/**
* Describe class <code>RuleTest</code> here.
*/
public class RuleTest {
public static void main(String[] args) throws Exception {
/* create model */
Model model = ModelFactory.createDefaultModel();
/* output model */
System.out.println("original model : " + model);
System.out.println("-----");
/* collect rules */
List<Rule> rules = new ArrayList<Rule>();
Rule rule = Rule.parseRule("[ (subject predicate object) -> (object predicate subject) ].");
rules.add(rule);
/* create rule reasoner */
GenericRuleReasoner reasoner = new GenericRuleReasoner(rules);
/* attach reasoner to model */
InfModel infModel = ModelFactory.createInfModel(reasoner, model);
/* output model */
//-----------------------------------------------//
// commenting the following line in/out changes //
// the output of (*) below in Jena 2.5.5 ?!?!?! //
//-----------------------------------------------//
//System.out.println("inference model: " + infModel);
System.out.println("=====");
/* add facts to original model */
Resource s = model.createResource("subject");
Property p = model.createProperty("predicate");
RDFNode o = model.createResource("object");
Statement stmt = model.createStatement(s, p, o);
model.add(stmt);
/* output models */
System.out.println("original model : " + model);
System.out.println("-----");
System.out.println("inference model: " + infModel); // (*)
}
}
回答1:
Had a quick look at the relevant source and it appears that you have two options:
If you want to make changes to the base model and then be sure that they propagate to the infModel, then you have to call infModel.rebind() after having made the changes and before you "ask" the infModel anything.
You can use the infModel directly (instead of model) to create and add the statement's elements and the statement itself.
I know this does not directly answer your question, but it may solve your problem (which, btw, seems to be caused by reification triggered by the toString() method in ModelCom - the parent class of InfModel).
回答2:
It's likely that model.toString() has side-effects. I have not looked at the JENA source, so I can't be sure, though.
回答3:
It's now a few years later and Jena is in the 2.10.x series. When the indicated line is commented out, the output of your program is:
original model : <ModelCom {} | >
-----
=====
original model : <ModelCom {subject @predicate object} | [subject, predicate, object]>
-----
inference model: <ModelCom {object @predicate subject; subject @predicate object} | [object, predicate, subject] [subject, predicate, object]>
and the string representation of the InfModel contains two triples. When the line is uncommented, the output is:
original model : <ModelCom {} | >
-----
inference model: <ModelCom {} | >
=====
original model : <ModelCom {subject @predicate object} | [subject, predicate, object]>
-----
inference model: <ModelCom {subject @predicate object} | [subject, predicate, object]>
and the second string representation of the InfModel has only one triple, so the difference is still observed. (I included the output here, because in the question it isn't clear what difference was being observed.)
The short answer is that this happens because you're being sneaky and modifying model
without telling infModel
that you changed the underlying model
. To address this, you should add a call to infModel.rebind();
after you update model
. That is, you would now have:
model.add(stmt);
infModel.rebind();
When you do this, you'll get the same output in both cases. With the line commented:
original model : <ModelCom {} | >
-----
=====
original model : <ModelCom {subject @predicate object} | [subject, predicate, object]>
-----
inference model: <ModelCom {object @predicate subject; subject @predicate object} | [object, predicate, subject] [subject, predicate, object]>
With the line uncommented:
original model : <ModelCom {} | >
-----
inference model: <ModelCom {} | >
=====
original model : <ModelCom {subject @predicate object} | [subject, predicate, object]>
-----
inference model: <ModelCom {object @predicate subject; subject @predicate object} | [object, predicate, subject] [subject, predicate, object]>
My guess here is that writing the string representation of the InfModel doesn't cause any inference to be performed unless no inference has been performed yet, and then prints the underlying model and then any additional triples that are inferred. As a result:
- In the first case (when you print
infModel
just once) it hasn't done any inference yet, so it consultsmodel
and does the appropriate inference and gets the additional triples. Then it printsmodel
's triples and then the inferred triples. - In the second case (when you print
infModel
twice), the first time you printinfModel
, it consultsmodel
and does some inference, butmodel
is empty, so there are no additional triples, and then it printsmodel
's triples and the additional inferred triples (there are none). Then, the second timeinfModel
is printed, inference has already been performed, so it printsmodel
's triples (but there's an extra one) and any inferred triples (there are none, because no more inference was performed).
The call to rebind()
after adding triples to model
means that in the second case, the additional inferred triples are available at the time of printing.
来源:https://stackoverflow.com/questions/349652/printing-infmodel-earlier-changes-printed-representation-later