-
Notifications
You must be signed in to change notification settings - Fork 26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Delete event and annotations #330
base: master
Are you sure you want to change the base?
Changes from 11 commits
9d4e864
2209a0a
cf152ef
d982c32
7d65404
fb69982
a507fd9
fef6577
ad42345
be1d8c7
bc94e2a
fd88e11
f27f30e
5f337ce
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,15 +10,23 @@ | |
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
|
||
import opensilex.service.dao.exception.DAOPersistenceException; | ||
|
||
import org.apache.jena.arq.querybuilder.ExprFactory; | ||
import org.apache.jena.arq.querybuilder.UpdateBuilder; | ||
import org.apache.jena.arq.querybuilder.WhereBuilder; | ||
import org.apache.jena.datatypes.xsd.XSDDatatype; | ||
import org.apache.jena.graph.Node; | ||
import org.apache.jena.graph.NodeFactory; | ||
import org.apache.jena.rdf.model.Literal; | ||
import org.apache.jena.rdf.model.Property; | ||
import org.apache.jena.rdf.model.Resource; | ||
import org.apache.jena.rdf.model.ResourceFactory; | ||
import org.apache.jena.sparql.core.TriplePath; | ||
import org.apache.jena.sparql.path.Path; | ||
import org.apache.jena.sparql.path.PathFactory; | ||
import org.apache.jena.vocabulary.DCTerms; | ||
import org.apache.jena.vocabulary.RDF; | ||
import org.eclipse.rdf4j.query.BindingSet; | ||
|
@@ -27,6 +35,9 @@ | |
import org.eclipse.rdf4j.query.QueryLanguage; | ||
import org.eclipse.rdf4j.query.TupleQuery; | ||
import org.eclipse.rdf4j.query.TupleQueryResult; | ||
import org.eclipse.rdf4j.query.Update; | ||
import org.eclipse.rdf4j.query.UpdateExecutionException; | ||
import org.eclipse.rdf4j.repository.RepositoryConnection; | ||
import org.eclipse.rdf4j.repository.RepositoryException; | ||
import org.joda.time.DateTime; | ||
import org.joda.time.format.DateTimeFormat; | ||
|
@@ -501,10 +512,100 @@ private ArrayList<Annotation> getAnnotationsWithoutBodyValuesFromResult(TupleQue | |
return annotations; | ||
} | ||
|
||
@Override | ||
public void delete(List<Annotation> objects) throws DAOPersistenceException, Exception { | ||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. | ||
} | ||
/** | ||
* @return an {@link UpdateBuilder} producing a SPARQL query which remove all annotation having only | ||
* the given annotation as target. | ||
* @example | ||
* DELETE { ?s ?p ?o . } WHERE { | ||
* ?s oa:hasTarget+ "http://www.phenome-fppn.fr/test/id/annotation/1e331ca4-2e63-4728-8373-050a2b51c3dc". <br> | ||
* ?s ?p ?o | ||
* MINUS { | ||
* ?s oa:hasTarget ?s2, ?s3 . | ||
* FILTER( ?s2 != ?s3) | ||
* } | ||
* } | ||
* @param annotationUri | ||
* @throws RepositoryException | ||
* @throws UpdateExecutionException | ||
*/ | ||
protected UpdateBuilder getRemoveAllSuperAnnotationQuery(String annotationUri) throws RepositoryException, UpdateExecutionException { | ||
|
||
// create variables and annotation resource | ||
Node s = NodeFactory.createVariable("s"), s2 = NodeFactory.createVariable("s2"), s3 = NodeFactory.createVariable("s3"), | ||
p = NodeFactory.createVariable("p"), o = NodeFactory.createVariable("o"), | ||
oaTargetPred = NodeFactory.createURI(Oa.RELATION_HAS_TARGET.toString()), | ||
annotationNode = NodeFactory.createURI(annotationUri); | ||
|
||
Path oaTargetPath = PathFactory.pathOneOrMore1(PathFactory.pathLink(oaTargetPred)); // create the property path (oa:target)+ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Commentaire sur sa ligne propre |
||
|
||
return new UpdateBuilder() // build the query | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Commentaire useless |
||
.addDelete(s, p, o) | ||
.addWhere(new TriplePath(s, oaTargetPath, annotationNode) )// add the two WHERE basic graph pattern ( b.g.p.) | ||
.addWhere(s, p, o) | ||
.addMinus(new WhereBuilder() // add the minus clause in order to check if the annotation has more than one target | ||
.addWhere(s, oaTargetPred, s2) | ||
.addWhere(s, oaTargetPred, s3) | ||
.addFilter(new ExprFactory().ne(s2, s3)) // create ?s2 != ?s3, | ||
); | ||
} | ||
|
||
/** | ||
* @return an {@link UpdateBuilder} producing a SPARQL query which remove all annotation triples | ||
* @example | ||
* DELETE { | ||
* http://www.phenome-fppn.fr/test/id/annotation/1e331ca4-2e63-4728-8373-050a2b51c3dc ?p ?o . | ||
* ?s ?p1 http://www.phenome-fppn.fr/test/id/annotation/1e331ca4-2e63-4728-8373-050a2b51c3dc | ||
* } WHERE { | ||
* { http://www.phenome-fppn.fr/test/id/annotation/1e331ca4-2e63-4728-8373-050a2b51c3dc ?p ?o } | ||
* UNION | ||
* {?s ?p1 http://www.phenome-fppn.fr/test/id/annotation/1e331ca4-2e63-4728-8373-050a2b51c3dc } | ||
* } | ||
* | ||
* @param annotationUri : the URI of the {@link Annotation} to delete | ||
*/ | ||
protected UpdateBuilder getRemoveAllAnnotationTripleQuery(String annotationUri) throws RepositoryException { | ||
|
||
// create variables and annotation resource | ||
Node s = NodeFactory.createVariable("s"), | ||
p = NodeFactory.createVariable("p"), | ||
p2 = NodeFactory.createVariable("p2"), | ||
o = NodeFactory.createVariable("o"), | ||
annotationNode = NodeFactory.createURI(annotationUri); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Une variable par ligne |
||
|
||
return new UpdateBuilder() | ||
.addDelete(annotationNode,p,o) | ||
.addDelete(s,p2,annotationNode) | ||
.addWhere(annotationNode, p, o) // add the <s,p,annotation_uri> UNION <annotation_uri,p,o> | ||
.addUnion(new WhereBuilder().addWhere(s,p2,annotationNode) | ||
); | ||
} | ||
|
||
/** | ||
* @apiNote | ||
* WARNING : delete an annotation trigger the deletion of all annotation which only have the annotation as target . | ||
*/ | ||
@Override | ||
protected void deleteAll(List<String> annotationUris) throws RepositoryException, UpdateExecutionException { | ||
|
||
RepositoryConnection conn = getConnection(); | ||
for(String uri : annotationUris) { | ||
String removeIncomingsAnnotationQuery = getRemoveAllSuperAnnotationQuery(uri).buildRequest().toString(); | ||
String removeAnnotationQuery = getRemoveAllAnnotationTripleQuery(uri).buildRequest().toString(); | ||
|
||
Update update = conn.prepareUpdate(QueryLanguage.SPARQL,removeIncomingsAnnotationQuery); | ||
update.execute(); // first delete all annotation which has the annotationUri as target | ||
update = conn.prepareUpdate(QueryLanguage.SPARQL,removeAnnotationQuery); | ||
update.execute(); // then delete the annotation itself | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Met les commentaires sur leur propre ligne |
||
} | ||
} | ||
|
||
@Override | ||
public void delete(List<Annotation> annotations) throws DAOPersistenceException, Exception, IllegalAccessException, IllegalAccessException { | ||
|
||
ArrayList<String> uris = annotations.stream().map(annotation -> annotation.getUri()) // get all annotation URIs into an ArrayList via Stream API | ||
.collect(Collectors.toCollection(ArrayList::new)); | ||
checkAndDeleteAll(uris); | ||
} | ||
|
||
@Override | ||
public List<Annotation> update(List<Annotation> objects) throws DAOPersistenceException, Exception { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,8 +8,14 @@ | |
package opensilex.service.dao; | ||
|
||
import java.util.ArrayList; | ||
import java.util.LinkedList; | ||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
|
||
import org.apache.jena.arq.querybuilder.ExprFactory; | ||
import org.apache.jena.arq.querybuilder.SelectBuilder; | ||
import org.apache.jena.arq.querybuilder.UpdateBuilder; | ||
import org.apache.jena.arq.querybuilder.WhereBuilder; | ||
import org.apache.jena.graph.Node; | ||
import org.apache.jena.graph.NodeFactory; | ||
import org.apache.jena.rdf.model.Resource; | ||
|
@@ -21,6 +27,8 @@ | |
import org.eclipse.rdf4j.query.QueryLanguage; | ||
import org.eclipse.rdf4j.query.TupleQuery; | ||
import org.eclipse.rdf4j.query.TupleQueryResult; | ||
import org.eclipse.rdf4j.query.Update; | ||
import org.eclipse.rdf4j.repository.RepositoryConnection; | ||
import org.eclipse.rdf4j.repository.RepositoryException; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
@@ -33,6 +41,7 @@ | |
import opensilex.service.dao.manager.Rdf4jDAO; | ||
import opensilex.service.model.User; | ||
import opensilex.service.ontology.Contexts; | ||
import opensilex.service.ontology.Oa; | ||
import opensilex.service.ontology.Oeev; | ||
import opensilex.service.ontology.Rdf; | ||
import opensilex.service.ontology.Rdfs; | ||
|
@@ -634,10 +643,124 @@ public void addDeleteWhenUpdatingToUpdateBuilder(UpdateBuilder updateBuilder, Ev | |
Oeev.concerns.getURI(), | ||
event.getConcernedItems()); | ||
} | ||
|
||
@Override | ||
public void delete(List<Event> objects) throws DAOPersistenceException, Exception { | ||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. | ||
public void delete(List<Event> events) throws DAOPersistenceException, Exception { | ||
|
||
List<String> uris = events.stream().map(event -> event.getUri()) // get all events URIs into an ArrayList via Stream API | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Commentaire sur sa ligne propre |
||
.collect(Collectors.toCollection(ArrayList::new)); | ||
checkAndDeleteAll(uris); | ||
} | ||
|
||
/** | ||
* @apiNote | ||
* WARNING : delete an event trigger the deletion of all annotation which only have the event as target . | ||
*/ | ||
@Override | ||
protected void deleteAll(List<String> uris) throws RepositoryException { | ||
|
||
AnnotationDAO annotationDAO = new AnnotationDAO(user); | ||
RepositoryConnection conn = getConnection(); | ||
annotationDAO.setConnection(conn); // make sure the two DAO use the same connection | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Commentaire sur sa ligne propre |
||
|
||
for(String eventUri : uris) { | ||
List<String> annotationUris = getAllAnnotationUrisWithEventAsTarget(eventUri); | ||
|
||
UpdateBuilder deleteEventQuery = deleteEventTriples(eventUri); | ||
Update deleteEventUpdate = conn.prepareUpdate(QueryLanguage.SPARQL,deleteEventQuery.build().toString()); | ||
deleteEventUpdate.execute(); | ||
|
||
if(! annotationUris.isEmpty()) | ||
annotationDAO.deleteAll(annotationUris); | ||
} | ||
} | ||
|
||
/** | ||
* @return the {@link List} of {@link Annotation} which only have the given event uri as target. | ||
* @example | ||
* select distinct ?a <br> | ||
* where { <br> | ||
* ?a oa:hasTarget "http://www.phenome-fppn.fr/id/event/5a1b3c0d-58af-4cfb-811e-e141b11453b1". <br> | ||
* ?a oa:hasTarget ?t2. <br> | ||
* FILTER ( | ||
* "http://www.phenome-fppn.fr/id/event/5a1b3c0d-58af-4cfb-811e-e141b11453b1" = ?t2) <br> | ||
* } <br> | ||
* @param eventUri | ||
*/ | ||
protected List<String> getAllAnnotationUrisWithEventAsTarget(String eventUri) { | ||
|
||
Node a = NodeFactory.createVariable("a"), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Utilises des noms de variables qui ont du sens |
||
t = NodeFactory.createVariable("t"), | ||
oaTargetPred = NodeFactory.createURI(Oa.RELATION_HAS_TARGET.toString()), | ||
eventNode = NodeFactory.createURI(eventUri), | ||
annotationGraph = NodeFactory.createURI(Contexts.ANNOTATIONS.toString()); | ||
|
||
String removeAnnotationQuery = new SelectBuilder() | ||
.addVar(a) | ||
.addGraph(annotationGraph, new WhereBuilder() // specify the graph to query | ||
.addWhere(a,oaTargetPred,eventNode) | ||
.addMinus(new WhereBuilder() | ||
.addWhere(a,oaTargetPred,t) | ||
.addFilter(new ExprFactory().ne(eventNode, t))) | ||
) | ||
.buildString(); | ||
|
||
|
||
List<String> annotationUris = new LinkedList<>(); | ||
TupleQuery getAnnotationQuery = getConnection().prepareTupleQuery(removeAnnotationQuery); | ||
TupleQueryResult res = getAnnotationQuery.evaluate(); | ||
|
||
while(res.hasNext()) { | ||
BindingSet bs = res.next(); | ||
annotationUris.add(bs.getValue("a").stringValue()); | ||
} | ||
return annotationUris; | ||
} | ||
|
||
/** | ||
* @return an {@link UpdateBuilder} producing a SPARQL query which remove all event triples | ||
* @example | ||
* PREFIX oeso: <http://www.opensilex.org/vocabulary/oeso#> | ||
* PREFIX time: <http://www.w3.org/2006/time#> | ||
* | ||
* DELETE { | ||
* http://www.phenome-fppn.fr/id/event/5a1b3c0d-58af-4cfb-811e-e141b11453b1> ?p ?o . | ||
* ?s ?p1 <http://www.phenome-fppn.fr/id/event/5a1b3c0d-58af-4cfb-811e-e141b11453b1> . | ||
* ?time ?time_pred ?time_object | ||
* | ||
* } WHERE { | ||
* ?s ?p1 <http://www.phenome-fppn.fr/id/event/5a1b3c0d-58af-4cfb-811e-e141b11453b1> | ||
* <http://www.phenome-fppn.fr/id/event/5a1b3c0d-58af-4cfb-811e-e141b11453b1> ?p ?o ; | ||
* time:hasTime ?time. | ||
* ?time ?time_pred ?time_object . | ||
* } | ||
* } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indentation et met tes requêtes entre balise |
||
* @param eventUri : the URI of the {@link Event} to delete | ||
*/ | ||
protected UpdateBuilder deleteEventTriples(String eventUri) { | ||
|
||
Node p = NodeFactory.createVariable("p"), // Query variables | ||
o = NodeFactory.createVariable("o"), | ||
s = NodeFactory.createVariable("s"), | ||
p1 = NodeFactory.createVariable("o1"), | ||
time = NodeFactory.createVariable("time"), | ||
timePred = NodeFactory.createVariable("time_pred"), | ||
timeObj = NodeFactory.createVariable("time_object"); | ||
|
||
Node hasTimePred = NodeFactory.createURI(Time.hasTime.getURI()), // Query uris | ||
eventNode = NodeFactory.createURI(eventUri); | ||
// eventGraph = NodeFactory.createURI(Contexts.EVENTS.toString()); | ||
|
||
return new UpdateBuilder() | ||
.addDelete(eventNode,p,o) | ||
.addDelete(time,timePred,timeObj) | ||
.addDelete(s,p1,eventNode) | ||
.addWhere(eventNode, p, o) // add the <s,p,annotation_uri> UNION <annotation_uri,p,o> | ||
.addWhere(eventNode,hasTimePred,time) | ||
.addWhere(time,timePred,timeObj) | ||
.addUnion(new WhereBuilder() | ||
.addWhere(s,p1,eventNode) | ||
); | ||
} | ||
|
||
@Override | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Une variable par ligne