Skip to content
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

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
109 changes: 105 additions & 4 deletions phis2-ws/src/main/java/opensilex/service/dao/AnnotationDAO.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Une variable par ligne


Path oaTargetPath = PathFactory.pathOneOrMore1(PathFactory.pathLink(oaTargetPred)); // create the property path (oa:target)+
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commentaire sur sa ligne propre


return new UpdateBuilder() // build the query
Copy link
Member

Choose a reason for hiding this comment

The 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);
Copy link
Member

Choose a reason for hiding this comment

The 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
Copy link
Member

Choose a reason for hiding this comment

The 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 {
Expand Down
129 changes: 126 additions & 3 deletions phis2-ws/src/main/java/opensilex/service/dao/EventDAO.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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
Copy link
Member

Choose a reason for hiding this comment

The 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
Copy link
Member

Choose a reason for hiding this comment

The 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"),
Copy link
Member

Choose a reason for hiding this comment

The 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 .
* }
* }
Copy link
Member

Choose a reason for hiding this comment

The 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
Expand Down
17 changes: 17 additions & 0 deletions phis2-ws/src/main/java/opensilex/service/dao/manager/DAO.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,23 @@ public abstract class DAO<T> {
*/
public String remoteUserAdress;
public User user;


public String getRemoteUserAdress() {
return remoteUserAdress;
}

public void setRemoteUserAdress(String remoteUserAdress) {
this.remoteUserAdress = remoteUserAdress;
}

public User getUser() {
return user;
}

public void setUser(User user) {
this.user = user;
}

/**
* Creates in the storage the list of objects given.
Expand Down
Loading