event notification for RDF API and change to model setup for SimpleReasoner

This commit is contained in:
brianjlowe 2012-06-11 21:03:16 +00:00
parent 964cb1bdb4
commit f55916b8d8
12 changed files with 245 additions and 14 deletions

View file

@ -0,0 +1,136 @@
package edu.cornell.mannlib.vitro.webapp.dao.jena;
import java.util.Set;
import com.hp.hpl.jena.graph.BulkUpdateHandler;
import com.hp.hpl.jena.graph.Capabilities;
import com.hp.hpl.jena.graph.Graph;
import com.hp.hpl.jena.graph.GraphEventManager;
import com.hp.hpl.jena.graph.GraphStatisticsHandler;
import com.hp.hpl.jena.graph.Node;
import com.hp.hpl.jena.graph.Reifier;
import com.hp.hpl.jena.graph.TransactionHandler;
import com.hp.hpl.jena.graph.Triple;
import com.hp.hpl.jena.graph.TripleMatch;
import com.hp.hpl.jena.graph.query.QueryHandler;
import com.hp.hpl.jena.shared.AddDeniedException;
import com.hp.hpl.jena.shared.DeleteDeniedException;
import com.hp.hpl.jena.shared.PrefixMapping;
import com.hp.hpl.jena.util.iterator.ExtendedIterator;
import com.hp.hpl.jena.util.iterator.WrappedIterator;
public class DifferenceGraph implements Graph {
private Graph g;
private Graph subtract;
public DifferenceGraph(Graph g, Graph subtract) {
this.g = g;
this.subtract = subtract;
}
@Override
public void close() {
// not clear what the best behavior here is
}
@Override
public boolean contains(Triple arg0) {
return g.contains(arg0) && !subtract.contains(arg0);
}
@Override
public boolean contains(Node arg0, Node arg1, Node arg2) {
return g.contains(arg0, arg1, arg2) && !subtract.contains(arg0, arg1, arg2);
}
@Override
public void delete(Triple arg0) throws DeleteDeniedException {
g.delete(arg0);
}
@Override
public boolean dependsOn(Graph arg0) {
return g.dependsOn(arg0);
}
@Override
public ExtendedIterator<Triple> find(TripleMatch arg0) {
Set<Triple> tripSet = g.find(arg0).toSet();
tripSet.removeAll(subtract.find(arg0).toSet());
return WrappedIterator.create(tripSet.iterator());
}
@Override
public ExtendedIterator<Triple> find(Node arg0, Node arg1, Node arg2) {
Set<Triple> tripSet = g.find(arg0, arg1, arg2).toSet();
tripSet.removeAll(subtract.find(arg0, arg1, arg2).toSet());
return WrappedIterator.create(tripSet.iterator());
}
@Override
public BulkUpdateHandler getBulkUpdateHandler() {
return g.getBulkUpdateHandler();
}
@Override
public Capabilities getCapabilities() {
return g.getCapabilities();
}
@Override
public GraphEventManager getEventManager() {
return g.getEventManager();
}
@Override
public PrefixMapping getPrefixMapping() {
return g.getPrefixMapping();
}
@Override
public Reifier getReifier() {
return g.getReifier();
}
@Override
public GraphStatisticsHandler getStatisticsHandler() {
return g.getStatisticsHandler();
}
@Override
public TransactionHandler getTransactionHandler() {
return g.getTransactionHandler();
}
@Override
public boolean isClosed() {
return g.isClosed();
}
@Override
public boolean isEmpty() {
return g.isEmpty();
}
@Override
public boolean isIsomorphicWith(Graph arg0) {
return g.isIsomorphicWith(arg0);
}
@Override
public QueryHandler queryHandler() {
return g.queryHandler();
}
@Override
public int size() {
return g.size() - subtract.size();
}
@Override
public void add(Triple arg0) throws AddDeniedException {
g.add(arg0);
}
}

View file

@ -109,7 +109,8 @@ public class IndividualDaoJena extends JenaBaseDao implements IndividualDao {
public void removeVClass(String individualURI, String vclassURI) {
OntModel ontModel = getOntModelSelector().getABoxModel();
ontModel.enterCriticalSection(Lock.WRITE);
ontModel.getBaseModel().notifyEvent(new IndividualUpdateEvent(getWebappDaoFactory().getUserURI(),true,individualURI));
Object event = new IndividualUpdateEvent(getWebappDaoFactory().getUserURI(),true,individualURI);
ontModel.getBaseModel().notifyEvent(event);
try {
Resource indRes = ontModel.getResource(individualURI);
getOntModel().remove(indRes, RDF.type, ontModel.getResource(vclassURI));

View file

@ -42,6 +42,7 @@ public class JenaChangeListener implements ChangeListener {
@Override
public void notifyEvent(String graphURI, Object event) {
log.debug("event: " + event.getClass());
listener.notifyEvent(m, event);
}

View file

@ -41,7 +41,7 @@ public class RDFServiceDataset implements Dataset {
@Override
public Model getDefaultModel() {
return ModelFactory.createModelForGraph(g.getDefaultGraph());
return RDFServiceGraph.createRDFServiceModel(g.getDefaultGraph());
}
@Override
@ -51,7 +51,7 @@ public class RDFServiceDataset implements Dataset {
@Override
public Model getNamedModel(String arg0) {
return ModelFactory.createModelForGraph(g.getGraph(Node.createURI(arg0)));
return RDFServiceGraph.createRDFServiceModel(g.getGraph(Node.createURI(arg0)));
}
@Override

View file

@ -161,12 +161,12 @@ public class RDFServiceDatasetGraph implements DatasetGraph {
}
@Override
public Graph getDefaultGraph() {
public RDFServiceGraph getDefaultGraph() {
return new RDFServiceGraph(rdfService);
}
@Override
public Graph getGraph(Node arg0) {
public RDFServiceGraph getGraph(Node arg0) {
return new RDFServiceGraph(rdfService, arg0.getURI());
}

View file

@ -24,6 +24,9 @@ import com.hp.hpl.jena.graph.query.QueryHandler;
import com.hp.hpl.jena.graph.query.SimpleQueryHandler;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.rdf.listeners.StatementListener;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.shared.AddDeniedException;
import com.hp.hpl.jena.shared.DeleteDeniedException;
import com.hp.hpl.jena.shared.PrefixMapping;
@ -434,4 +437,22 @@ public class RDFServiceGraph implements GraphWithPerform {
}
}
public static Model createRDFServiceModel(final RDFServiceGraph g) {
Model m = ModelFactory.createModelForGraph(g);
m.register(new StatementListener() {
@Override
public void notifyEvent(Model m, Object event) {
ChangeSet changeSet = g.getRDFService().manufactureChangeSet();
changeSet.addPreChangeEvent(event);
try {
g.getRDFService().changeSetUpdate(changeSet);
} catch (RDFServiceException e) {
throw new RuntimeException(e);
}
}
});
return m;
}
}

View file

@ -86,4 +86,34 @@ public interface ChangeSet {
RDFService.ModelSerializationFormat serializationFormat,
ModelChange.Operation operation,
String graphURI);
/**
* Add an event that will be be passed to any change listeners in advance of
* the change set additions and retractions being performed. The event
* will only be fired if the precondition (if any) is met.
* @param event
*/
public void addPreChangeEvent(Object event);
/**
* Add an event that will be be passed to any change listeners after all of
* the change set additions and retractions are performed.
* @param event
*/
public void addPostChangeEvent(Object event);
/**
* Return a list of events to pass to any change listeners in
* advance of the change set additions and retractions being performed.
* @return
*/
public List<Object> getPreChangeEvents();
/**
* Return a list of events to pass to any change listeners after
* the change set additions and retractions are performed.
* @return
*/
public List<Object> getPostChangeEvents();
}

View file

@ -23,7 +23,9 @@ public class ChangeSetImpl implements ChangeSet {
private String preconditionQuery;
private RDFService.SPARQLQueryType queryType;
private ArrayList<ModelChange> modelChanges;
private ArrayList<ModelChange> modelChanges = new ArrayList<ModelChange>();
private ArrayList<Object> preChangeEvents = new ArrayList<Object>();
private ArrayList<Object> postChangeEvents = new ArrayList<Object>();
/**
* Getter for the precondition query
@ -122,4 +124,25 @@ public class ChangeSetImpl implements ChangeSet {
String graphURI) {
return new ModelChangeImpl(serializedModel, serializationFormat, operation, graphURI);
}
@Override
public void addPreChangeEvent(Object o) {
this.preChangeEvents.add(o);
}
@Override
public void addPostChangeEvent(Object o) {
this.postChangeEvents.add(o);
}
@Override
public List<Object> getPreChangeEvents() {
return this.preChangeEvents;
}
@Override
public List<Object> getPostChangeEvents() {
return this.postChangeEvents;
}
}

View file

@ -145,6 +145,17 @@ public abstract class RDFServiceImpl implements RDFService {
}
}
public synchronized void notifyListenersOfEvent(Object event) {
Iterator<ChangeListener> iter = registeredListeners.iterator();
while (iter.hasNext()) {
ChangeListener listener = iter.next();
// TODO what is the graphURI parameter for?
listener.notifyEvent(null, event);
}
}
protected boolean isPreconditionSatisfied(String query,
RDFService.SPARQLQueryType queryType)
throws RDFServiceException {

View file

@ -124,9 +124,15 @@ public class RDFServiceSDB extends RDFServiceImpl implements RDFService {
dataset.getLock().leaveCriticalSection();
}
}
for (Object o : changeSet.getPreChangeEvents()) {
this.notifyListenersOfEvent(o);
}
if (transaction) {
conn.getTransactionHandler().commit();
}
for (Object o : changeSet.getPostChangeEvents()) {
this.notifyListenersOfEvent(o);
}
} catch (Exception e) {
log.error(e, e);
if (transaction) {
@ -404,10 +410,12 @@ public class RDFServiceSDB extends RDFServiceImpl implements RDFService {
}
public void addedStatement(Statement stmt) {
log.debug("adding " + stmt + " to " + graphURI);
s.notifyListeners(stmt.asTriple(), ModelChange.Operation.ADD, graphURI);
}
public void removedStatement(Statement stmt) {
log.debug("removing " + stmt + " from " + graphURI);
s.notifyListeners(stmt.asTriple(), ModelChange.Operation.REMOVE, graphURI);
}

View file

@ -41,6 +41,7 @@ import com.hp.hpl.jena.vocabulary.RDFS;
import edu.cornell.mannlib.vitro.webapp.dao.jena.ABoxJenaChangeListener;
import edu.cornell.mannlib.vitro.webapp.dao.jena.CumulativeDeltaModeler;
import edu.cornell.mannlib.vitro.webapp.dao.jena.DifferenceGraph;
import edu.cornell.mannlib.vitro.webapp.dao.jena.RDFServiceGraph;
import edu.cornell.mannlib.vitro.webapp.dao.jena.event.BulkUpdateEvent;
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
@ -89,7 +90,7 @@ public class SimpleReasoner extends StatementListener {
this.tboxModel = tboxModel;
this.aboxModel = ModelFactory.createOntologyModel(
OntModelSpec.OWL_MEM, ModelFactory.createModelForGraph(
new RDFServiceGraph(rdfService)));
new DifferenceGraph(new RDFServiceGraph(rdfService), inferenceModel.getGraph())));
this.inferenceModel = inferenceModel;
this.inferenceRebuildModel = inferenceRebuildModel;
this.scratchpadModel = scratchpadModel;
@ -188,7 +189,6 @@ public class SimpleReasoner extends StatementListener {
* with DeltaComputer.
*/
protected synchronized void handleRemovedStatement(Statement stmt) {
if (batchMode1) {
aBoxDeltaModeler1.removedStatement(stmt);
} else if (batchMode2) {
@ -753,7 +753,7 @@ public class SimpleReasoner extends StatementListener {
Iterator<OntClass> parentIt = parents.iterator();
while (parentIt.hasNext()) {
OntClass parentClass = parentIt.next();
OntClass parentClass = parentIt.next();
// VIVO doesn't materialize statements that assert anonymous types
// for individuals. Also, sharing an identical anonymous node is
@ -770,7 +770,7 @@ public class SimpleReasoner extends StatementListener {
inferenceModel.enterCriticalSection(Lock.WRITE);
try {
if (inferenceModel.contains(infStmt)) {
inferenceModel.remove(infStmt);
inferenceModel.remove(infStmt);
}
} finally {
inferenceModel.leaveCriticalSection();

View file

@ -135,7 +135,7 @@ public class RDFServiceSetup extends JenaDataSourceSetupBase
RDFServiceFactory rdfServiceFactory = new RDFServiceFactorySingle(rdfService);
RDFServiceUtils.setRDFServiceFactory(ctx, rdfServiceFactory);
Graph g = new RDFServiceGraph(rdfService);
// Graph g = new RDFServiceGraph(rdfService);
Dataset dataset = new RDFServiceDataset(rdfService);
setStartupDataset(dataset, ctx);