Andy Seaborne wrote:
On 21/10/11 09:59, Paolo Castagna wrote:
Andy Seaborne wrote:
On 20/10/11 16:43, Paolo Castagna wrote:
Hi Andy

Andy Seaborne wrote:
On 19/10/11 10:41, Paolo Castagna wrote:
Hi,
I am using TDB and I'd like to be notified when a triple is added or
deleted
to/from a Graph. I am not sure what is the best way to achieve this.

Here is a first attempt (which is not working):

InputStream in = ...
DatasetGraphTDB dsg = TDBFactory.createDatasetGraph();

GraphListener listener = new MyListener();
dsg.getDefaultGraph().getEventManager().register(listener);
Iterator<Node> iter = dsg.listGraphNodes();
while ( iter.hasNext() ) {
Graph graph = dsg.getGraph(iter.next());
graph.getEventManager().register(listener);
}

TDBLoader.load(dsg, in, false);

MyListener extends GraphListenerBase implements GraphListener.

I don't understand why, even for triples added to the default
graph, it
seems the addEvent(Triple t) and the deleteEvent(Triple t) methods in
MyListener are not called.

Is there a better alternative?

I found an EventManager in the ARQ's org.openjena.atlas.event package.
However, I don't think that is actually used to deliver events to
listeners as data is added/removed to/from a Jena Graph.

Thanks,
Paolo

See LangBase<X>.parse() [which does not tie it back to the dataset]
and experimental/maybe: DSG_Notify

I see:
http://svn.apache.org/repos/asf/incubator/jena/Jena2/ARQ/trunk/src/main/java/org/openjena/riot/lang/LangBase.java


http://svn.apache.org/repos/asf/incubator/jena/Scratch/AFS/Jena-Dev/trunk/src/dev/DSG_Notify.java



but note TDBLoader works by cutting through the layering to reduce
overhead.

Maybe something like DSG_Notify could be added as an option you need to
enable.
Trading some overhead with the event notification feature.


TDBloader could so start/finish but if you want to see every quad, use
a sink. Do you want object churn on every quad?

Not necessary, but I was trying to see if it is possible to intercept
all the
update routes. It isn't, therefore if someone need to do that, it must
be done
from the "outside" of TDB.

And, yes, it makes less sense for bulk loading/large updates.

The use case/requirement is: how to keep an external index up-to-date
with the
main RDF store, in this case TDB.

I tried to think: what if we increase the granularity of the data (in
order to
reduce the overhead). However, I am not sure what would be the best
way to
aggregate|find all the quads|triples which have been added/removed.

GraphListener may well work for model.read.

Yes. Confirmed.

Model model = ModelFactory.createModelForGraph(dsg.getDefaultGraph()) ;
model.add(...);

InputStream in = ...
model.read(in, "", "N-TRIPLES");

The GraphListener is notified.

So, to summarize: a GraphListener is notified of changes only if the
Model APIs
are used to make the changes, not if the Graph SPIs are used.

The GraphListener is notifed if the Graph SPI is used. TDBLoader does
not use the graph API when bulk loading.

I also tried with the .add method on a DatasetGraphTDB:

InputStream in = ...
DatasetGraphTDB dsg = TDBFactory.createDatasetGraph();
GraphListener listener = new MyListener();
dsg.getDefaultGraph().getEventManager().register(listener);
dsg.add(new Quad(Quad.defaultGraphIRI, ...));

But, MyListener does not get notified when dsg.add() method is called.
Is it because Quad.defaultGraphIRI is the wrong "default" graph IRI to
use here?

I tried with Quad.defaultGraphNodeGenerated as well, but it's the same.
No method is called on MyListener.

You are adding a quad to a datasetgraph, not a triple to a graph.

You are not using the Graph SPI - you get that by getting a graph from the datasetgraph.

Ok.

This works as expected:

  Graph graph = dsg.getDefaultGraph();
  graph.add(new Triple(...));

If someone need a place to intercept all changes to a TDB Dataset,
the GraphListener approach is not the solution, since there are many
ways to change the TDB Dataset without using the Graph SPI (and
therefore without a GraphListener being notified of the changes).

What would be a better approach?

Thanks,
Paolo


    Andy


TDBLoader could add "start bulk update", "end bulk update" events but
that does not capture every quad added. Use a Sink for that.

Yes, this is what I do now:

InputStream in = ...
MySinkQuad sink = new MySinkQuad(...);
RiotReader.parseQuads(in, Lang.NQUADS, null, sink);

Thanks,
Paolo


Andy


Thanks.

Paolo


Andy





Reply via email to