In Jena it is possible to monitor a Model
for changes, so that
code can be run after changes are applied without the coding for
that Model having to do anything special. We call these changes
"events". This first
design and implementation is open for user comment and we may
refine or reduce the implementation as more experience is gained with
it.
To monitor a Model, you must register a ModelChangedListener with that Model:
Model m = ModelFactory.createDefaultModel(); ModelChangedListener L = new MyListener(); m.register( L );
MyListener must be an implementation of ModelChangedListener, for example:
class MyListener implements ModelChangedListener { public void addedStatement( Statement s ) { System.out.println( ">> added statement " + s ); } public void addedStatements( Statement [] statements ) {} public void addedStatements( List statements ) {} public void addedStatements( StmtIterator statements ) {} public void addedStatements( Model m ) {} public void removedStatement( Statement s ) {} public void removedStatements( Statement [] statements ) {} public void removedStatements( List statements ) {} public void removedStatements( StmtIterator statements ) {} public void removedStatements( Model m ) {} }
This listener ignores everything except the addition of single statements to m; those it prints out. The listener has a method for each of the ways that statements can be added to a Model:
Model::add(Statement)
Model::add(Statement[])
Model::add(List)
Model::add(StmtIterator)
Model::add(Model)
(Similarly for delete.)
The listener method is called when the statement(s) have been added to the Model, if no exceptions have been thrown. It does not matter if the statement was already in the Model or not; it is the act of adding it that fires the listener.
There is no guarantee that the statement, array, list, or model that is added or removed is the same one that is passed to the appropriate listener method, and the StmtIterator will never be the same one. However, in the current design:
We advise not relying on these ordering properties; instead assume that for any bulk update operation on the model, the listener will be told the method of update and the statements added or removed, but that the order may be different and duplicate statements may have been removed. Note in particular that a Model with any Listeners will have to record the complete contents of any StmtIterator that is added or removed to the model, so that the Model and the Listener can both see all the statements.
Finally, there is no guarantee that only Statements etc added through the Model API will be presented to the listener; any Triples added to its underlying Graph will also be presented to the listener as statements.
The full Listener API is rather chunky and it can be inconvenient to use, especially for the creation of inline classes. There are four utility classes in com.hp.hpl.jena.rdf.listeners:
In the current implementation, listener methods are called immediately the additions or removals are made, in the same thread as the one making the update. If a model has multiple listeners registered, the order in which they are informed about an update is unspecified and may change from update to update. If any listener throws an exception, that exception is thrown through the update call, and other listeners may not be informed of the update. Hence listener code should be brief and exception-free if at all possible.
A listener may be registered with the same model multiple times. If so, it will be invoked as many times as it is registered for each update event on the model.
A listener L may be unregistered from a Model using the method
unregister(L)
. If L is not registered with the model, nothing
happens.
If a listener is registered multiple times with the same model,
each unregister()
for that listener will remove just one of the
registrations.
In the current design, listeners are not informed of transaction boundaries, and all events are fed to listeners as soon as they happen.