From 9d4e8644714c6af31a967b3535c1be6b66249541 Mon Sep 17 00:00:00 2001 From: renaud colin Date: Wed, 4 Dec 2019 11:48:14 +0100 Subject: [PATCH 01/14] update Rdf4j connection methods by ensuring that the connection is in a good state. Signed-off-by: renaud colin --- .../service/dao/manager/Rdf4jDAO.java | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/phis2-ws/src/main/java/opensilex/service/dao/manager/Rdf4jDAO.java b/phis2-ws/src/main/java/opensilex/service/dao/manager/Rdf4jDAO.java index 7b42af238..d8b9c4661 100644 --- a/phis2-ws/src/main/java/opensilex/service/dao/manager/Rdf4jDAO.java +++ b/phis2-ws/src/main/java/opensilex/service/dao/manager/Rdf4jDAO.java @@ -163,7 +163,15 @@ public Rdf4jDAO(String repositoryID) { } } + /** + * + * @return the {@link RepositoryConnection} used by the DAO. + * Initialize the connection if not done yet. + * see {@link #initConnection()}. + */ public RepositoryConnection getConnection() { + if(connection == null || ! connection.isOpen()) + initConnection(); return connection; } @@ -588,27 +596,33 @@ public List findLabelsForUri(String uri) { } @Override - protected void initConnection() { - getConnection().begin(); + protected void initConnection() { + if(connection == null || ! connection.isOpen()) + connection = rep.getConnection(); } @Override protected void closeConnection() { - getConnection().close(); + if(connection != null && connection.isOpen()) + connection.close(); } @Override protected void startTransaction() { - // transactions starts automatically in SPARQL. + initConnection(); // init the connection if not done + if(! connection.isActive()) + connection.begin(); } @Override protected void commitTransaction() { - getConnection().commit(); + if(connection != null && connection.isActive()) + connection.commit(); } @Override protected void rollbackTransaction() { - getConnection().rollback(); + if(connection != null && connection.isActive()) + connection.rollback(); } } From 2209a0a647231615d5e8e1d8fcdfdddd743ad51a Mon Sep 17 00:00:00 2001 From: renaud colin Date: Wed, 4 Dec 2019 11:53:30 +0100 Subject: [PATCH 02/14] add Rdf4j deletions methods Signed-off-by: renaud colin --- .../service/dao/manager/Rdf4jDAO.java | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/phis2-ws/src/main/java/opensilex/service/dao/manager/Rdf4jDAO.java b/phis2-ws/src/main/java/opensilex/service/dao/manager/Rdf4jDAO.java index d8b9c4661..1ffb58997 100644 --- a/phis2-ws/src/main/java/opensilex/service/dao/manager/Rdf4jDAO.java +++ b/phis2-ws/src/main/java/opensilex/service/dao/manager/Rdf4jDAO.java @@ -13,6 +13,8 @@ import java.util.Map; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; + +import org.apache.commons.lang3.StringUtils; import org.apache.jena.arq.querybuilder.UpdateBuilder; import org.apache.jena.graph.Node; import org.apache.jena.graph.NodeFactory; @@ -42,6 +44,7 @@ import opensilex.service.configuration.DateFormat; import opensilex.service.configuration.DefaultBrapiPaginationValues; import opensilex.service.configuration.URINamespaces; +import opensilex.service.dao.UserDAO; import opensilex.service.dao.exception.DAOPersistenceException; import opensilex.service.documentation.StatusCodeMsg; import opensilex.service.model.User; @@ -594,6 +597,65 @@ public List findLabelsForUri(String uri) { return labels; } + + /** + * Delete a list of objects into the TripleStore. + * @param uris : a {@link List} of objects URI + * @throws RepositoryException + * @throws UpdateExecutionException + */ + protected void deleteAll(List uris) throws RepositoryException, UpdateExecutionException { + + } + + /** + * Delete a list of objects into the TripleStore. + * @param uris : the list of URI to delete + * @throws IllegalArgumentException if the {@link #user} is not an Admin user or if a given URI is not present + * into the TripleStore. + * @throws DAOPersistenceException : if an {@link Exception} related to the {@link Repository} is encountered. + * @throws Exception : for any other encountered {@link Exception} + * @see #deleteAll(List) + * @see UserDAO#isAdmin(User) + */ + public void checkAndDeleteAll(List uris) throws IllegalArgumentException, DAOPersistenceException, Exception { + + if(user == null || StringUtils.isEmpty(user.getAdmin())) { + throw new IllegalArgumentException("No user/bad user provided"); + } + if(! new UserDAO().isAdmin(user)) { // the user is not an admin + throw new IllegalArgumentException("Error : only an admin user can delete an object"); + } + + StringBuilder errorMsgs = new StringBuilder(); + boolean allUriExists = true; + for(String uri : uris) { + if(! existUri(uri)) { + errorMsgs.append(uri+" , "); + allUriExists = false; + } + } + if(!allUriExists) { + throw new IllegalArgumentException(errorMsgs.append(" don't belongs to the TripleStore").toString()); + } + + Exception returnedException = null; + try { + startTransaction(); + deleteAll(uris); + commitTransaction(); + } catch (RepositoryException | UpdateExecutionException e) { + rollbackTransaction(); + returnedException = new DAOPersistenceException(e); + } catch(Exception e) { + rollbackTransaction(); + returnedException = e; + } + finally { + if(returnedException != null) + throw returnedException; + } + } @Override protected void initConnection() { From cf152efdca534f64eb57941fea4962beab5a328e Mon Sep 17 00:00:00 2001 From: renaud colin Date: Wed, 4 Dec 2019 12:02:57 +0100 Subject: [PATCH 03/14] add deletes method into AnnotationDAO Signed-off-by: renaud colin --- .../opensilex/service/dao/AnnotationDAO.java | 109 +++++++++++++++++- 1 file changed, 105 insertions(+), 4 deletions(-) diff --git a/phis2-ws/src/main/java/opensilex/service/dao/AnnotationDAO.java b/phis2-ws/src/main/java/opensilex/service/dao/AnnotationDAO.java index 58e3a95aa..d6276596b 100644 --- a/phis2-ws/src/main/java/opensilex/service/dao/AnnotationDAO.java +++ b/phis2-ws/src/main/java/opensilex/service/dao/AnnotationDAO.java @@ -10,8 +10,13 @@ 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; @@ -19,6 +24,9 @@ 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 getAnnotationsWithoutBodyValuesFromResult(TupleQue return annotations; } - @Override - public void delete(List 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".
+ * ?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)+ + + return new UpdateBuilder() // build the query + .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); + + return new UpdateBuilder() + .addDelete(annotationNode,p,o) + .addDelete(s,p2,annotationNode) + .addWhere(annotationNode, p, o) // add the UNION + .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 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 + } + } + + @Override + public void delete(List annotations) throws DAOPersistenceException, Exception, IllegalAccessException, IllegalAccessException { + + ArrayList 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 update(List objects) throws DAOPersistenceException, Exception { From d982c329d18ad2d29d3ceedf2ac854d52b60a5f6 Mon Sep 17 00:00:00 2001 From: renaud colin Date: Wed, 4 Dec 2019 12:03:24 +0100 Subject: [PATCH 04/14] add delete method into EventDAO Signed-off-by: renaud colin --- .../java/opensilex/service/dao/EventDAO.java | 129 +++++++++++++++++- 1 file changed, 126 insertions(+), 3 deletions(-) diff --git a/phis2-ws/src/main/java/opensilex/service/dao/EventDAO.java b/phis2-ws/src/main/java/opensilex/service/dao/EventDAO.java index 003ed7d0f..842d29083 100644 --- a/phis2-ws/src/main/java/opensilex/service/dao/EventDAO.java +++ b/phis2-ws/src/main/java/opensilex/service/dao/EventDAO.java @@ -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 objects) throws DAOPersistenceException, Exception { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + public void delete(List events) throws DAOPersistenceException, Exception { + + List uris = events.stream().map(event -> event.getUri()) // get all events URIs into an ArrayList via Stream API + .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 uris) throws RepositoryException { + + AnnotationDAO annotationDAO = new AnnotationDAO(user); + RepositoryConnection conn = getConnection(); + annotationDAO.setConnection(conn); // make sure the two DAO use the same connection + + for(String eventUri : uris) { + List 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
+ * where {
+ * ?a oa:hasTarget "http://www.phenome-fppn.fr/id/event/5a1b3c0d-58af-4cfb-811e-e141b11453b1".
+ * ?a oa:hasTarget ?t2.
+ * FILTER ( + * "http://www.phenome-fppn.fr/id/event/5a1b3c0d-58af-4cfb-811e-e141b11453b1" = ?t2)
+ * }
+ * @param eventUri + */ + protected List getAllAnnotationUrisWithEventAsTarget(String eventUri) { + + Node a = NodeFactory.createVariable("a"), + 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 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: + * PREFIX time: + * + * DELETE { + * http://www.phenome-fppn.fr/id/event/5a1b3c0d-58af-4cfb-811e-e141b11453b1> ?p ?o . + * ?s ?p1 . + * ?time ?time_pred ?time_object + * + * } WHERE { + * ?s ?p1 + * ?p ?o ; + * time:hasTime ?time. + * ?time ?time_pred ?time_object . + * } + * } + * @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 UNION + .addWhere(eventNode,hasTimePred,time) + .addWhere(time,timePred,timeObj) + .addUnion(new WhereBuilder() + .addWhere(s,p1,eventNode) + ); } @Override From 7d654044928ec8e4314669becc6de9354aa235c2 Mon Sep 17 00:00:00 2001 From: renaud colin Date: Wed, 4 Dec 2019 12:05:08 +0100 Subject: [PATCH 05/14] add a DeleteDTO Signed-off-by: renaud colin --- .../service/resource/dto/DeleteDTO.java | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 phis2-ws/src/main/java/opensilex/service/resource/dto/DeleteDTO.java diff --git a/phis2-ws/src/main/java/opensilex/service/resource/dto/DeleteDTO.java b/phis2-ws/src/main/java/opensilex/service/resource/dto/DeleteDTO.java new file mode 100644 index 000000000..b76108da1 --- /dev/null +++ b/phis2-ws/src/main/java/opensilex/service/resource/dto/DeleteDTO.java @@ -0,0 +1,52 @@ +//****************************************************************************** +// DeleteDTO.java +// SILEX-PHIS +// Copyright © INRA 2019 +// Creation date: 25 oct. 2019 +// Contact: renaud.colin@inra.fr, anne.tireau@inra.fr, pascal.neveu@inra.fr +//****************************************************************************** + + +package opensilex.service.resource.dto; + +import java.util.List; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import opensilex.service.resource.dto.manager.AbstractVerifiedClass; +import opensilex.service.resource.validation.interfaces.URL; + +/** + * @author renaud.colin@inra.fr + * + */ +@ApiModel +public class DeleteDTO extends AbstractVerifiedClass { + + /** + * URI(s) of objects to delete + * @example http://www.phenome-fppn.fr/platform/id/annotation/8247af37-769c-495b-8e7e-78b1141176c2 + */ + private List uris; + + @Override + public Object createObjectFromDTO() throws Exception { + throw new UnsupportedOperationException("No object could be created from a DeleteDTO"); + } + + @URL + @NotNull + @NotEmpty + @ApiModelProperty(notes = "Need to be a list of URI") + public List getUris() { + return uris; + } + + public void setUris(List uris) { + this.uris = uris; + } + +} From fb69982f7f87f0c18b435045e8b33e097ea52e67 Mon Sep 17 00:00:00 2001 From: renaud colin Date: Wed, 4 Dec 2019 12:21:09 +0100 Subject: [PATCH 06/14] add method into Resource Service in order to build a Response from a DeleteDTO and a Rdf4jDAO. Signed-off-by: renaud colin --- .../service/resource/ResourceService.java | 48 ++++++++++++++++++- .../opensilex/service/view/brapi/Status.java | 6 ++- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/phis2-ws/src/main/java/opensilex/service/resource/ResourceService.java b/phis2-ws/src/main/java/opensilex/service/resource/ResourceService.java index 8d0b042c0..d348dc7c1 100644 --- a/phis2-ws/src/main/java/opensilex/service/resource/ResourceService.java +++ b/phis2-ws/src/main/java/opensilex/service/resource/ResourceService.java @@ -9,6 +9,8 @@ import java.util.ArrayList; import java.util.List; +import java.util.Objects; + import javax.ws.rs.core.Response; import opensilex.service.PropertiesFileManager; import opensilex.service.authentication.Session; @@ -16,9 +18,12 @@ import opensilex.service.dao.exception.DAOPersistenceException; import opensilex.service.dao.exception.ResourceAccessDeniedException; import opensilex.service.dao.manager.DAO; +import opensilex.service.dao.manager.Rdf4jDAO; import opensilex.service.documentation.StatusCodeMsg; import opensilex.service.injection.SessionInject; import static opensilex.service.resource.DocumentResourceService.LOGGER; + +import opensilex.service.resource.dto.DeleteDTO; import opensilex.service.resource.dto.manager.AbstractVerifiedClass; import opensilex.service.view.brapi.Status; import opensilex.service.result.ResultForm; @@ -159,7 +164,7 @@ protected Response getGETResponseWhenNoResult() { * @return */ protected Response getGETByUriResponseFromDAOResults(DAO dao, String uri) { - ArrayList objects = new ArrayList(); + ArrayList objects = new ArrayList<>(); try { Object object = dao.findById(uri); objects.add(object); @@ -346,4 +351,45 @@ private Response getPostPutResponseFromMultipleOperationStatus (Response.Status private Response buildResponse(Response.Status status, AbstractResultForm resultForm) { return Response.status(status).entity(resultForm).build(); } + + /** + * + * @param e + * @return + */ + protected Response buildResponseFromException(Exception e) { + + Response.Status status = null; + if(e instanceof IllegalArgumentException) { + status = Response.Status.BAD_REQUEST; + } + else if(e instanceof IllegalAccessException) { + status = Response.Status.FORBIDDEN; + } + else { + status = Response.Status.INTERNAL_SERVER_ERROR; + } + AbstractResultForm putResponse = new ResponseFormPOST(new Status(e.getMessage())); + return Response.status(status).entity(putResponse).build(); + } + + /** + * @param dao : a {@link Rdf4jDAO} used to delete a {@link List} of String URI. + * @param deleteDTO : a {@link DeleteDTO} which contains a {@link List} of URI. + * @param msg : delete msg + * @return + */ + protected Response buildDeleteObjectsByUriResponse(Rdf4jDAO dao, DeleteDTO deleteDTO, String msg) { + + Objects.requireNonNull(dao); + Objects.requireNonNull(deleteDTO); + try { + dao.checkAndDeleteAll(deleteDTO.getUris()); + ResponseFormPOST resp = new ResponseFormPOST(new Status(msg,null)); + return buildResponse(Response.Status.OK,resp); + } catch(Exception e) { + return buildResponseFromException(e); + } + + } } diff --git a/phis2-ws/src/main/java/opensilex/service/view/brapi/Status.java b/phis2-ws/src/main/java/opensilex/service/view/brapi/Status.java index 284c29222..33804e86f 100644 --- a/phis2-ws/src/main/java/opensilex/service/view/brapi/Status.java +++ b/phis2-ws/src/main/java/opensilex/service/view/brapi/Status.java @@ -18,8 +18,12 @@ public class Status { public Status() { } + + public Status(String message) { + this.message = message; + } - public Status(String message, StatusException exception) { + public Status(String message, StatusException exception) { this.exception = exception; this.message = message; } From a507fd98f99630f35f4279182bb21a71c36293c3 Mon Sep 17 00:00:00 2001 From: renaud colin Date: Wed, 4 Dec 2019 12:22:49 +0100 Subject: [PATCH 07/14] add getter/setters for User and RemoteUserAdress into DAO Signed-off-by: renaud colin --- .../java/opensilex/service/dao/manager/DAO.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/phis2-ws/src/main/java/opensilex/service/dao/manager/DAO.java b/phis2-ws/src/main/java/opensilex/service/dao/manager/DAO.java index 622b0ce54..5d3d51377 100644 --- a/phis2-ws/src/main/java/opensilex/service/dao/manager/DAO.java +++ b/phis2-ws/src/main/java/opensilex/service/dao/manager/DAO.java @@ -25,6 +25,23 @@ public abstract class DAO { */ 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. From fef65777111171c91ca674b6b0c8e7dc3ec70a6b Mon Sep 17 00:00:00 2001 From: renaud colin Date: Wed, 4 Dec 2019 12:23:11 +0100 Subject: [PATCH 08/14] add Event and Annotation resource services Signed-off-by: renaud colin --- .../DocumentationAnnotation.java | 2 + .../resource/AnnotationResourceService.java | 59 ++++++++++++++++++- .../resource/EventResourceService.java | 56 +++++++++++++++++- 3 files changed, 112 insertions(+), 5 deletions(-) diff --git a/phis2-ws/src/main/java/opensilex/service/documentation/DocumentationAnnotation.java b/phis2-ws/src/main/java/opensilex/service/documentation/DocumentationAnnotation.java index 1044a5749..2d0b091d7 100644 --- a/phis2-ws/src/main/java/opensilex/service/documentation/DocumentationAnnotation.java +++ b/phis2-ws/src/main/java/opensilex/service/documentation/DocumentationAnnotation.java @@ -30,6 +30,7 @@ public final class DocumentationAnnotation { public static final String PAGE_SIZE_MONGO = "Number of elements per page (limited to 1000000)"; // User messages + public static final String INTERNAL_SERVER_ERROR = "Internal server error."; public static final String ERROR_SEND_DATA = "Server error. Cannot send data."; public static final String ERROR_FETCH_DATA = "Server error. Cannot fetch data."; public static final String BAD_USER_INFORMATION = "Bad informations send by user"; @@ -299,6 +300,7 @@ public final class DocumentationAnnotation { public static final String EXAMPLE_CALL_DATATYPE = "json"; + public static final String ANNOTATION_URI_DEFINITION = "An annotation URI (Unique Resource Identifier)"; public static final String EXAMPLE_ANNOTATION_URI = "http://www.opensilex.org/platform/id/annotation/8247af37-769c-495b-8e7e-78b1141176c2"; public static final String EXAMPLE_ANNOTATION_TARGET = "http://www.opensilex.org/demo/id/variable/v0000001"; public static final String EXAMPLE_ANNOTATION_MOTIVATED_BY = "http://www.w3.org/ns/oa#commenting"; diff --git a/phis2-ws/src/main/java/opensilex/service/resource/AnnotationResourceService.java b/phis2-ws/src/main/java/opensilex/service/resource/AnnotationResourceService.java index f7414232f..e79835df4 100644 --- a/phis2-ws/src/main/java/opensilex/service/resource/AnnotationResourceService.java +++ b/phis2-ws/src/main/java/opensilex/service/resource/AnnotationResourceService.java @@ -19,6 +19,9 @@ import javax.servlet.http.HttpServletRequest; import javax.validation.Valid; import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; import javax.ws.rs.POST; @@ -36,6 +39,7 @@ import opensilex.service.documentation.DocumentationAnnotation; import opensilex.service.documentation.StatusCodeMsg; import opensilex.service.view.brapi.form.ResponseFormPOST; +import opensilex.service.resource.dto.DeleteDTO; import opensilex.service.resource.dto.annotation.AnnotationDTO; import opensilex.service.resource.dto.annotation.AnnotationPostDTO; import opensilex.service.resource.validation.interfaces.URL; @@ -250,7 +254,7 @@ public Response getAnnotationByUri( @Override protected ArrayList getDTOsFromObjects(List objects) { - ArrayList dtos = new ArrayList(); + ArrayList dtos = new ArrayList<>(); // Generate DTOs objects.forEach((object) -> { dtos.add(new AnnotationDTO((Annotation)object)); @@ -261,7 +265,7 @@ protected ArrayList getDTOsFromObjects(List getObjectsFromDTOs (List dtos) throws Exception { - List objects = new ArrayList<>(); + List objects = new ArrayList<>(dtos.size()); for (AbstractVerifiedClass objectDto : dtos) { objects.add((Annotation)objectDto.createObjectFromDTO()); } @@ -270,10 +274,59 @@ protected List getObjectsFromDTOs (List getUrisFromObjects (List createdObjects) { - List createdUris = new ArrayList<>(); + List createdUris = new ArrayList<>(createdObjects.size()); createdObjects.forEach(object -> { createdUris.add(((Annotation)object).getUri()); }); return createdUris; } + + /** + * @example + *[ + * http://www.phenome-fppn.fr/platform/id/annotation/8247af37-769c-495b-8e7e-78b1141176c2, + * http://www.phenome-fppn.fr/platform/id/annotation/8247gt37-769c-495b-8e7e-91jh633151k4 + *] + * + */ + @DELETE + @Path("{uri}") + @ApiOperation( + value = "Delete a list of annotation", + notes = "Delete a list of annotation. Need URL encoded annotation URI" + + ) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "Annotation(s) deleted", response = ResponseFormPOST.class), + @ApiResponse(code = 400, message = DocumentationAnnotation.BAD_USER_INFORMATION), + @ApiResponse(code = 401, message = DocumentationAnnotation.USER_NOT_AUTHORIZED), + @ApiResponse(code = 500, message = DocumentationAnnotation.INTERNAL_SERVER_ERROR), + }) + @ApiImplicitParams({ + @ApiImplicitParam( + name = GlobalWebserviceValues.AUTHORIZATION, + required = true, + dataType = GlobalWebserviceValues.DATA_TYPE_STRING, + paramType = GlobalWebserviceValues.HEADER, + value = DocumentationAnnotation.ACCES_TOKEN, + example = GlobalWebserviceValues.AUTHENTICATION_SCHEME + " ") + }) + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response deleteAnnotationByUri( + @ApiParam( + value = DocumentationAnnotation.ANNOTATION_URI_DEFINITION, + required = true, + example = DocumentationAnnotation.EXAMPLE_ANNOTATION_URI + ) + @Valid @NotNull DeleteDTO deleteDTO, @Context HttpServletRequest context) { + + AnnotationDAO annotationDAO = new AnnotationDAO(userSession.getUser()); + if (context.getRemoteAddr() != null) { + annotationDAO.setRemoteUserAdress(context.getRemoteAddr()); + } + Response response = buildDeleteObjectsByUriResponse(annotationDAO, deleteDTO,"Annotation(s) deleted"); + annotationDAO.getConnection().close(); + return response; + } } diff --git a/phis2-ws/src/main/java/opensilex/service/resource/EventResourceService.java b/phis2-ws/src/main/java/opensilex/service/resource/EventResourceService.java index 0e5f9a9e3..8f8224d36 100644 --- a/phis2-ws/src/main/java/opensilex/service/resource/EventResourceService.java +++ b/phis2-ws/src/main/java/opensilex/service/resource/EventResourceService.java @@ -19,7 +19,9 @@ import javax.servlet.http.HttpServletRequest; import javax.validation.Valid; import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; import javax.ws.rs.POST; @@ -40,6 +42,7 @@ import opensilex.service.dao.exception.DAOPersistenceException; import opensilex.service.documentation.DocumentationAnnotation; import opensilex.service.documentation.StatusCodeMsg; +import opensilex.service.resource.dto.DeleteDTO; import opensilex.service.resource.dto.event.EventGetDTO; import opensilex.service.resource.dto.event.EventPostDTO; import opensilex.service.resource.dto.rdfResourceDefinition.RdfResourceDefinitionDTO; @@ -435,7 +438,7 @@ public Response put( @Override protected ArrayList getDTOsFromObjects(List objects) { - ArrayList dtos = new ArrayList(); + ArrayList dtos = new ArrayList<>(objects.size()); objects.forEach((object) -> { dtos.add(new EventGetDTO((Event)object)); }); @@ -445,7 +448,7 @@ protected ArrayList getDTOsFromObjects(List getObjectsFromDTOs (List dtos) throws Exception { - List objects = new ArrayList<>(); + List objects = new ArrayList<>(dtos.size()); for (AbstractVerifiedClass objectDto : dtos) { objects.add((Event)objectDto.createObjectFromDTO()); } @@ -460,4 +463,53 @@ protected List getUrisFromObjects (List createdObjects }); return createdUris; } + + /** + * @example + *[ + * http://www.phenome-fppn.fr/platform/id/event/8247af37-769c-495b-8e7e-78b1141176c2, + * http://www.phenome-fppn.fr/platform/id/event/8247gt37-769c-495b-8e7e-91jh633151k4 + *] + * + */ + @DELETE + @Path("{uri}") + @ApiOperation( + value = "Delete a list of event", + notes = "Delete a list of event. Need URL encoded event URI" + + ) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "Event(s) deleted", response = ResponseFormPOST.class), + @ApiResponse(code = 400, message = DocumentationAnnotation.BAD_USER_INFORMATION), + @ApiResponse(code = 401, message = DocumentationAnnotation.USER_NOT_AUTHORIZED), + @ApiResponse(code = 500, message = DocumentationAnnotation.INTERNAL_SERVER_ERROR), + }) + @ApiImplicitParams({ + @ApiImplicitParam( + name = GlobalWebserviceValues.AUTHORIZATION, + required = true, + dataType = GlobalWebserviceValues.DATA_TYPE_STRING, + paramType = GlobalWebserviceValues.HEADER, + value = DocumentationAnnotation.ACCES_TOKEN, + example = GlobalWebserviceValues.AUTHENTICATION_SCHEME + " ") + }) + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response deleteEventUri( + @ApiParam( + value = DocumentationAnnotation.EVENT_URI_DEFINITION, + required = true, + example = DocumentationAnnotation.EXAMPLE_EVENT_URI + ) + @Valid @NotNull DeleteDTO deleteDTO, @Context HttpServletRequest context) { + + EventDAO eventDao = new EventDAO(userSession.getUser()); + if (context.getRemoteAddr() != null) { + eventDao.setRemoteUserAdress(context.getRemoteAddr()); + } + Response response = buildDeleteObjectsByUriResponse(eventDao, deleteDTO,"Event(s) deleted"); + eventDao.getConnection().close(); + return response; + } } From ad42345fe26dda8355215339ff01268d17aaa7e3 Mon Sep 17 00:00:00 2001 From: renaud colin Date: Wed, 4 Dec 2019 13:23:10 +0100 Subject: [PATCH 09/14] add annotation/event delete unit tests Signed-off-by: renaud colin --- .../service/dao/AnnotationDAOTest.java | 155 ++++++++++++++++++ .../opensilex/service/dao/EventDAOTest.java | 127 ++++++++++++++ 2 files changed, 282 insertions(+) create mode 100644 phis2-ws/src/test/java/opensilex/service/dao/AnnotationDAOTest.java create mode 100644 phis2-ws/src/test/java/opensilex/service/dao/EventDAOTest.java diff --git a/phis2-ws/src/test/java/opensilex/service/dao/AnnotationDAOTest.java b/phis2-ws/src/test/java/opensilex/service/dao/AnnotationDAOTest.java new file mode 100644 index 000000000..2238514e3 --- /dev/null +++ b/phis2-ws/src/test/java/opensilex/service/dao/AnnotationDAOTest.java @@ -0,0 +1,155 @@ +//****************************************************************************** +// AnnotationDAOTest.java +// SILEX-PHIS +// Copyright © INRA 2019 +// Creation date: 22 oct. 2019 +// Contact: renaud.colin@inra.fr, anne.tireau@inra.fr, pascal.neveu@inra.fr +//****************************************************************************** + + +package opensilex.service.dao; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +import org.joda.time.DateTime; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import opensilex.service.dao.exception.DAOPersistenceException; +import opensilex.service.dao.manager.Rdf4jDAO; +import opensilex.service.dao.manager.Rdf4jDAOTest; +import opensilex.service.model.Annotation; +import opensilex.service.model.Event; +import opensilex.service.model.Experiment; +import opensilex.service.model.Project; +import opensilex.service.model.ScientificObject; +import opensilex.service.ontology.Oa; + +public class AnnotationDAOTest extends Rdf4jDAOTest { + + /** + * The {@link Rdf4jDAO} to test + */ + private static AnnotationDAO annotationDao; + private static List events; + private static ScientificObject so; + + @BeforeAll + public static void setup() throws DAOPersistenceException, Exception { + annotationDao = new AnnotationDAO(userDao.findById(userUri)); + initDaoWithInMemoryStoreConnection(annotationDao); + events = new LinkedList<>(); + } + + @Override + protected Rdf4jDAO getDao() { + return annotationDao; + } + + + @BeforeEach + protected void initDao() throws DAOPersistenceException, Exception { + + Project createdProject = createAndGetProject(); + Experiment xp = createAndGetExperiment(createdProject); + so = createAndGetScientificObject(xp); + events.clear(); + events.add(createAndGetEvent(so.getUri())); + } + + + @Test + /** + * Try to delete an annotation about one event + */ + void test_delete_annotation() throws DAOPersistenceException, Exception { + + long initialSize = annotationDao.getConnection().size(); + Annotation a = createAndGetAnnotation(events.get(0).getUri()); + annotationDao.delete(Arrays.asList(a)); + assertEquals(annotationDao.getConnection().size(), initialSize); + assertFalse(annotationDao.existUri(a.getUri())); + } + + @Test + /** + * Try to delete an annotation about one event. This annotation also have severals annotation. + */ + void test_delete_annotation_with_one_super_annotation() throws DAOPersistenceException, Exception { + + long initialSize = annotationDao.getConnection().size(); + + Annotation a = createAndGetAnnotation(events.get(0).getUri()); + Annotation a1 = createAndGetAnnotation(a.getUri()); // create annotation on the last created annotation + + annotationDao.delete(Arrays.asList(a)); + assertEquals(annotationDao.getConnection().size(), initialSize); + assertFalse(annotationDao.existUri(a.getUri())); + assertFalse(annotationDao.existUri(a1.getUri())); + + } + + @Test + /** + * Try to delete an annotation about one event. This annotation is annotated + * by a annotation a1 which also have an annotation. + * A simple RDF representation would be + * , , ... , + * + */ + void test_delete_annotation_with_recursive_annotation_chain() throws DAOPersistenceException, Exception { + + long initialSize = annotationDao.getConnection().size(); + + int k = 2; + String userUri = "http://www.opensilex.org/demo/id/agent/admin_phis"; + + Annotation a = new Annotation(null,DateTime.now(),userUri,Arrays.asList("annotate an event"), + Oa.INSTANCE_DESCRIBING.toString(),Arrays.asList(events.get(0).getUri())); + + List annotationList = new ArrayList<>(); + annotationList.addAll(annotationDao.create(Arrays.asList(a))); // create the first annotation A and add it + + int nbTripleCreated = 6; + for(int i=1;i getDao() { + return eventDao; + } + + @BeforeAll + public static void setUp() throws Exception { + eventDao = new EventDAO(userDao.findById(userUri)); + initDaoWithInMemoryStoreConnection(eventDao); + } + + @BeforeEach + protected void initDao() throws DAOPersistenceException, Exception { + Project createdProject = createAndGetProject(); + xp = createAndGetExperiment(createdProject); + so = createAndGetScientificObject(xp); + } + + @Test + void test_delete_event_on_one_scientific_object() throws DAOPersistenceException, Exception { + + long initialSize = eventDao.getConnection().size(); + Event event = createAndGetEvent(so.getUri()); // create one event on one ScientificObject + eventDao.delete(Arrays.asList(event)); + + assertEquals(initialSize,eventDao.getConnection().size()); + assertFalse(eventDao.existUri(event.getUri())); + assertTrue(eventDao.existUri(so.getUri())); + } + + + @Test + void test_delete_event_on_multiple_scientific_object() throws DAOPersistenceException, Exception { + int k = 3; + String[] soUris = new String[k]; + for(int i=0;i Date: Wed, 4 Dec 2019 15:33:16 +0100 Subject: [PATCH 10/14] update unit test to use ArrayList instead of String var args in order to create event(s) and/or annotation(s) Signed-off-by: renaud colin --- .../service/dao/AnnotationDAOTest.java | 55 +++++++++++++------ .../opensilex/service/dao/EventDAOTest.java | 39 +++++++------ 2 files changed, 60 insertions(+), 34 deletions(-) diff --git a/phis2-ws/src/test/java/opensilex/service/dao/AnnotationDAOTest.java b/phis2-ws/src/test/java/opensilex/service/dao/AnnotationDAOTest.java index 2238514e3..1cfcacca1 100644 --- a/phis2-ws/src/test/java/opensilex/service/dao/AnnotationDAOTest.java +++ b/phis2-ws/src/test/java/opensilex/service/dao/AnnotationDAOTest.java @@ -41,20 +41,19 @@ public class AnnotationDAOTest extends Rdf4jDAOTest { private static AnnotationDAO annotationDao; private static List events; private static ScientificObject so; + private static String userUri; @BeforeAll public static void setup() throws DAOPersistenceException, Exception { + + UserDAO userDao = new UserDAO(); + userUri = "http://www.opensilex.org/demo/id/agent/admin_phis"; + annotationDao = new AnnotationDAO(userDao.findById(userUri)); initDaoWithInMemoryStoreConnection(annotationDao); events = new LinkedList<>(); } - @Override - protected Rdf4jDAO getDao() { - return annotationDao; - } - - @BeforeEach protected void initDao() throws DAOPersistenceException, Exception { @@ -62,7 +61,9 @@ protected void initDao() throws DAOPersistenceException, Exception { Experiment xp = createAndGetExperiment(createdProject); so = createAndGetScientificObject(xp); events.clear(); - events.add(createAndGetEvent(so.getUri())); + + ArrayList concernedUris = new ArrayList<>(Arrays.asList(so.getUri())); + events.add(createAndGetEvent(concernedUris)); } @@ -73,8 +74,11 @@ protected void initDao() throws DAOPersistenceException, Exception { void test_delete_annotation() throws DAOPersistenceException, Exception { long initialSize = annotationDao.getConnection().size(); - Annotation a = createAndGetAnnotation(events.get(0).getUri()); + + ArrayList annotatedEventUris = new ArrayList<>(Arrays.asList(events.get(0).getUri())); + Annotation a = createAndGetAnnotation(annotatedEventUris,userUri); annotationDao.delete(Arrays.asList(a)); + assertEquals(annotationDao.getConnection().size(), initialSize); assertFalse(annotationDao.existUri(a.getUri())); } @@ -87,14 +91,16 @@ void test_delete_annotation_with_one_super_annotation() throws DAOPersistenceExc long initialSize = annotationDao.getConnection().size(); - Annotation a = createAndGetAnnotation(events.get(0).getUri()); - Annotation a1 = createAndGetAnnotation(a.getUri()); // create annotation on the last created annotation + ArrayList annotatedEventUris = new ArrayList<>(Arrays.asList(events.get(0).getUri())); + Annotation a = createAndGetAnnotation(annotatedEventUris,userUri); + + ArrayList annotationUris = new ArrayList<>(Arrays.asList(a.getUri())); + Annotation a1 = createAndGetAnnotation(annotationUris,userUri); // create annotation on the last created annotation annotationDao.delete(Arrays.asList(a)); assertEquals(annotationDao.getConnection().size(), initialSize); assertFalse(annotationDao.existUri(a.getUri())); assertFalse(annotationDao.existUri(a1.getUri())); - } @Test @@ -112,16 +118,25 @@ void test_delete_annotation_with_recursive_annotation_chain() throws DAOPersiste int k = 2; String userUri = "http://www.opensilex.org/demo/id/agent/admin_phis"; - Annotation a = new Annotation(null,DateTime.now(),userUri,Arrays.asList("annotate an event"), - Oa.INSTANCE_DESCRIBING.toString(),Arrays.asList(events.get(0).getUri())); + ArrayList bodyValues = new ArrayList<>(); + bodyValues.add("annotate an event"); + ArrayList targets = new ArrayList<>(); + targets.add(events.get(0).getUri()); + + Annotation a = new Annotation(null,DateTime.now(),userUri,bodyValues,Oa.INSTANCE_DESCRIBING.toString(),targets); List annotationList = new ArrayList<>(); annotationList.addAll(annotationDao.create(Arrays.asList(a))); // create the first annotation A and add it int nbTripleCreated = 6; for(int i=1;i annotatedEventUris = new ArrayList<>(Arrays.asList(events.get(0).getUri())); + Annotation a = createAndGetAnnotation(annotatedEventUris,userUri); + + ArrayList concernedUris = new ArrayList<>(Arrays.asList(so.getUri())); + events.add(createAndGetEvent(concernedUris)); // create a new event - Annotation a1 = createAndGetAnnotation(a.getUri(),events.get(1).getUri()); + ArrayList annotationsUris = new ArrayList<>(Arrays.asList(a.getUri(),events.get(1).getUri())); // annotation on a another annotation and on an event + Annotation a1 = createAndGetAnnotation(annotationsUris,userUri); annotationDao.delete(Arrays.asList(a)); assertFalse(annotationDao.existUri(a.getUri())); diff --git a/phis2-ws/src/test/java/opensilex/service/dao/EventDAOTest.java b/phis2-ws/src/test/java/opensilex/service/dao/EventDAOTest.java index 6ff94f887..b4da450f7 100644 --- a/phis2-ws/src/test/java/opensilex/service/dao/EventDAOTest.java +++ b/phis2-ws/src/test/java/opensilex/service/dao/EventDAOTest.java @@ -11,15 +11,13 @@ import static org.junit.jupiter.api.Assertions.*; +import java.util.ArrayList; import java.util.Arrays; -import java.util.List; - import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import opensilex.service.dao.exception.DAOPersistenceException; -import opensilex.service.dao.manager.Rdf4jDAO; import opensilex.service.dao.manager.Rdf4jDAOTest; import opensilex.service.model.Annotation; import opensilex.service.model.Event; @@ -37,14 +35,13 @@ class EventDAOTest extends Rdf4jDAOTest{ protected static EventDAO eventDao; protected ScientificObject so; protected Experiment xp; + private static String userUri; - @Override - protected Rdf4jDAO getDao() { - return eventDao; - } - @BeforeAll public static void setUp() throws Exception { + UserDAO userDao = new UserDAO(); + userUri = "http://www.opensilex.org/demo/id/agent/admin_phis"; + eventDao = new EventDAO(userDao.findById(userUri)); initDaoWithInMemoryStoreConnection(eventDao); } @@ -60,7 +57,9 @@ protected void initDao() throws DAOPersistenceException, Exception { void test_delete_event_on_one_scientific_object() throws DAOPersistenceException, Exception { long initialSize = eventDao.getConnection().size(); - Event event = createAndGetEvent(so.getUri()); // create one event on one ScientificObject + + ArrayList concernedUris = new ArrayList<>(Arrays.asList(so.getUri())); + Event event = createAndGetEvent(concernedUris); // create one event on one ScientificObject eventDao.delete(Arrays.asList(event)); assertEquals(initialSize,eventDao.getConnection().size()); @@ -71,12 +70,14 @@ void test_delete_event_on_one_scientific_object() throws DAOPersistenceException @Test void test_delete_event_on_multiple_scientific_object() throws DAOPersistenceException, Exception { + int k = 3; - String[] soUris = new String[k]; + ArrayList soUris = new ArrayList<>(k); for(int i=0;i concernedUris = new ArrayList<>(Arrays.asList(so.getUri())); + Event event = createAndGetEvent(concernedUris); // create one event on one ScientificObject + + ArrayList eventUris = new ArrayList<>(Arrays.asList(event.getUri())); + Annotation a = createAndGetAnnotation(eventUris,userUri); eventDao.delete(Arrays.asList(event)); assertFalse(eventDao.existUri(event.getUri())); @@ -108,10 +112,13 @@ void test_delete_event_with_one_annotation_on_multiple_events() throws DAOPersis long initialSize = eventDao.getConnection().size(); - Event event = createAndGetEvent(so.getUri()); // create one event on one ScientificObject - Event event1 = createAndGetEvent(so.getUri()); + ArrayList concernedUris = new ArrayList<>(Arrays.asList(so.getUri())); + Event event = createAndGetEvent(concernedUris); // create one event on one ScientificObject + Event event1 = createAndGetEvent(concernedUris); - Annotation a = createAndGetAnnotation(event.getUri(),event1.getUri()); // delete the first event, the annotation should not be removed + ArrayList eventUris = new ArrayList<>(Arrays.asList(event.getUri(),event1.getUri())); + + Annotation a = createAndGetAnnotation(eventUris,userUri); // delete the first event, the annotation should not be removed eventDao.delete(Arrays.asList(event)); assertFalse(eventDao.existUri(event.getUri())); From bc94e2a3d8c7684f8b06d56686827eee5ddf1e8a Mon Sep 17 00:00:00 2001 From: renaud colin Date: Wed, 4 Dec 2019 16:38:15 +0100 Subject: [PATCH 11/14] finally use varargs instead of ArrayList for unit tests object creation Signed-off-by: renaud colin --- .../service/dao/AnnotationDAOTest.java | 24 ++++++------------- .../opensilex/service/dao/EventDAOTest.java | 23 +++++++----------- 2 files changed, 15 insertions(+), 32 deletions(-) diff --git a/phis2-ws/src/test/java/opensilex/service/dao/AnnotationDAOTest.java b/phis2-ws/src/test/java/opensilex/service/dao/AnnotationDAOTest.java index 1cfcacca1..f84381489 100644 --- a/phis2-ws/src/test/java/opensilex/service/dao/AnnotationDAOTest.java +++ b/phis2-ws/src/test/java/opensilex/service/dao/AnnotationDAOTest.java @@ -62,8 +62,7 @@ protected void initDao() throws DAOPersistenceException, Exception { so = createAndGetScientificObject(xp); events.clear(); - ArrayList concernedUris = new ArrayList<>(Arrays.asList(so.getUri())); - events.add(createAndGetEvent(concernedUris)); + events.add(createAndGetEvent(so.getUri())); } @@ -75,8 +74,7 @@ void test_delete_annotation() throws DAOPersistenceException, Exception { long initialSize = annotationDao.getConnection().size(); - ArrayList annotatedEventUris = new ArrayList<>(Arrays.asList(events.get(0).getUri())); - Annotation a = createAndGetAnnotation(annotatedEventUris,userUri); + Annotation a = createAndGetAnnotation(userUri,events.get(0).getUri()); annotationDao.delete(Arrays.asList(a)); assertEquals(annotationDao.getConnection().size(), initialSize); @@ -91,11 +89,8 @@ void test_delete_annotation_with_one_super_annotation() throws DAOPersistenceExc long initialSize = annotationDao.getConnection().size(); - ArrayList annotatedEventUris = new ArrayList<>(Arrays.asList(events.get(0).getUri())); - Annotation a = createAndGetAnnotation(annotatedEventUris,userUri); - - ArrayList annotationUris = new ArrayList<>(Arrays.asList(a.getUri())); - Annotation a1 = createAndGetAnnotation(annotationUris,userUri); // create annotation on the last created annotation + Annotation a = createAndGetAnnotation(userUri,events.get(0).getUri()); + Annotation a1 = createAndGetAnnotation(userUri,a.getUri()); // create annotation on the last created annotation annotationDao.delete(Arrays.asList(a)); assertEquals(annotationDao.getConnection().size(), initialSize); @@ -154,14 +149,9 @@ void test_delete_annotation_with_recursive_annotation_chain() throws DAOPersiste */ void test_delete_annotation_with_one_super_annotation_with_another_target() throws DAOPersistenceException, Exception { - ArrayList annotatedEventUris = new ArrayList<>(Arrays.asList(events.get(0).getUri())); - Annotation a = createAndGetAnnotation(annotatedEventUris,userUri); - - ArrayList concernedUris = new ArrayList<>(Arrays.asList(so.getUri())); - events.add(createAndGetEvent(concernedUris)); // create a new event - - ArrayList annotationsUris = new ArrayList<>(Arrays.asList(a.getUri(),events.get(1).getUri())); // annotation on a another annotation and on an event - Annotation a1 = createAndGetAnnotation(annotationsUris,userUri); + Annotation a = createAndGetAnnotation(userUri,events.get(0).getUri()); + events.add(createAndGetEvent(so.getUri())); // create a new event + Annotation a1 = createAndGetAnnotation(userUri,a.getUri(),events.get(1).getUri()); // annotation on a another annotation and on an event annotationDao.delete(Arrays.asList(a)); assertFalse(annotationDao.existUri(a.getUri())); diff --git a/phis2-ws/src/test/java/opensilex/service/dao/EventDAOTest.java b/phis2-ws/src/test/java/opensilex/service/dao/EventDAOTest.java index b4da450f7..3d0fac363 100644 --- a/phis2-ws/src/test/java/opensilex/service/dao/EventDAOTest.java +++ b/phis2-ws/src/test/java/opensilex/service/dao/EventDAOTest.java @@ -11,7 +11,6 @@ import static org.junit.jupiter.api.Assertions.*; -import java.util.ArrayList; import java.util.Arrays; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; @@ -58,8 +57,7 @@ void test_delete_event_on_one_scientific_object() throws DAOPersistenceException long initialSize = eventDao.getConnection().size(); - ArrayList concernedUris = new ArrayList<>(Arrays.asList(so.getUri())); - Event event = createAndGetEvent(concernedUris); // create one event on one ScientificObject + Event event = createAndGetEvent(so.getUri()); // create one event on one ScientificObject eventDao.delete(Arrays.asList(event)); assertEquals(initialSize,eventDao.getConnection().size()); @@ -72,9 +70,9 @@ void test_delete_event_on_one_scientific_object() throws DAOPersistenceException void test_delete_event_on_multiple_scientific_object() throws DAOPersistenceException, Exception { int k = 3; - ArrayList soUris = new ArrayList<>(k); + String[] soUris = new String[k]; for(int i=0;i concernedUris = new ArrayList<>(Arrays.asList(so.getUri())); - Event event = createAndGetEvent(concernedUris); // create one event on one ScientificObject + Event event = createAndGetEvent(so.getUri()); // create one event on one ScientificObject - ArrayList eventUris = new ArrayList<>(Arrays.asList(event.getUri())); - Annotation a = createAndGetAnnotation(eventUris,userUri); + Annotation a = createAndGetAnnotation(userUri,event.getUri()); eventDao.delete(Arrays.asList(event)); assertFalse(eventDao.existUri(event.getUri())); @@ -112,13 +108,10 @@ void test_delete_event_with_one_annotation_on_multiple_events() throws DAOPersis long initialSize = eventDao.getConnection().size(); - ArrayList concernedUris = new ArrayList<>(Arrays.asList(so.getUri())); - Event event = createAndGetEvent(concernedUris); // create one event on one ScientificObject - Event event1 = createAndGetEvent(concernedUris); + Event event = createAndGetEvent(so.getUri()); // create one event on one ScientificObject + Event event1 = createAndGetEvent(so.getUri()); - ArrayList eventUris = new ArrayList<>(Arrays.asList(event.getUri(),event1.getUri())); - - Annotation a = createAndGetAnnotation(eventUris,userUri); // delete the first event, the annotation should not be removed + Annotation a = createAndGetAnnotation(userUri,event.getUri(),event1.getUri()); // delete the first event, the annotation should not be removed eventDao.delete(Arrays.asList(event)); assertFalse(eventDao.existUri(event.getUri())); From fd88e11e3b7825afe489574a9bf326a536227064 Mon Sep 17 00:00:00 2001 From: renaud colin Date: Fri, 13 Dec 2019 00:52:57 +0100 Subject: [PATCH 12/14] improve Event and Annotation coding style and code comprehension --- .../opensilex/service/dao/AnnotationDAO.java | 82 +++++++++------- .../java/opensilex/service/dao/EventDAO.java | 93 ++++++++++--------- 2 files changed, 96 insertions(+), 79 deletions(-) diff --git a/phis2-ws/src/main/java/opensilex/service/dao/AnnotationDAO.java b/phis2-ws/src/main/java/opensilex/service/dao/AnnotationDAO.java index d6276596b..e90f7a118 100644 --- a/phis2-ws/src/main/java/opensilex/service/dao/AnnotationDAO.java +++ b/phis2-ws/src/main/java/opensilex/service/dao/AnnotationDAO.java @@ -516,68 +516,74 @@ private ArrayList getAnnotationsWithoutBodyValuesFromResult(TupleQue * @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".
- * ?s ?p ?o - * MINUS { - * ?s oa:hasTarget ?s2, ?s3 . + *
+     * DELETE { ?src_a ?src_a_pred ?src_a_obj . } 
+     * WHERE { 
+     *     ?src_a oa:hasTarget+ "http://www.phenome-fppn.fr/test/id/annotation/1e331ca4-2e63-4728-8373-050a2b51c3dc". 
+     *     ?src_a ?src_a_pred ?src_a_obj
+     * 	   MINUS { 
+     *     	  ?src_a oa:hasTarget ?s2, ?s3 . 
      *     	  FILTER( ?s2 != ?s3) 
      * 	  } 
      * } 
-     * @param annotationUri 
+     * 
+ * @param annotationUri : the annotation on which we check if there exist an another annotation * @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); + Node srcAnnotation = NodeFactory.createVariable("src_a"), + srcAnnotationTarget = NodeFactory.createVariable("src_a_target"), + srcAnnotationTarget2 = NodeFactory.createVariable("src_a_target2"), + srcAnnotationPredicate = NodeFactory.createVariable("src_a_pred"), + srcAnnotationObject = NodeFactory.createVariable("src_a_obj"), + oaTargetPred = NodeFactory.createURI(Oa.RELATION_HAS_TARGET.toString()), + targetAnnotation = NodeFactory.createURI(annotationUri); Path oaTargetPath = PathFactory.pathOneOrMore1(PathFactory.pathLink(oaTargetPred)); // create the property path (oa:target)+ - return new UpdateBuilder() // build the query - .addDelete(s, p, o) - .addWhere(new TriplePath(s, oaTargetPath, annotationNode) )// add the two WHERE basic graph pattern ( b.g.p.) - .addWhere(s, p, o) + return new UpdateBuilder() + .addDelete(srcAnnotation, srcAnnotationPredicate, srcAnnotationObject) + .addWhere(new TriplePath(srcAnnotation, oaTargetPath, targetAnnotation) ) + .addWhere(srcAnnotation, srcAnnotationPredicate, srcAnnotationObject) .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, + .addWhere(srcAnnotation, oaTargetPred, srcAnnotationTarget) + .addWhere(srcAnnotation, oaTargetPred, srcAnnotationTarget2) + .addFilter(new ExprFactory().ne(srcAnnotationTarget, srcAnnotationTarget2)) ); } /** - * @return an {@link UpdateBuilder} producing a SPARQL query which remove all annotation triples + * @return an {@link UpdateBuilder} producing a SPARQL query which remove all incoming and outcoming + * 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  
+      *   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 + * @throws RepositoryException */ 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); + Node subject = NodeFactory.createVariable("s"), + outPredicate = NodeFactory.createVariable("p_out"), + inPredicate = NodeFactory.createVariable("p_in"), + object = NodeFactory.createVariable("o"), + annotation = NodeFactory.createURI(annotationUri); return new UpdateBuilder() - .addDelete(annotationNode,p,o) - .addDelete(s,p2,annotationNode) - .addWhere(annotationNode, p, o) // add the UNION - .addUnion(new WhereBuilder().addWhere(s,p2,annotationNode) - ); + .addDelete(annotation,outPredicate,object) + .addDelete(subject,inPredicate,annotation) + .addWhere(annotation, outPredicate, object) + .addUnion(new WhereBuilder().addWhere(subject,inPredicate,annotation)); } /** @@ -588,12 +594,16 @@ protected UpdateBuilder getRemoveAllAnnotationTripleQuery(String annotationUri) protected void deleteAll(List annotationUris) throws RepositoryException, UpdateExecutionException { RepositoryConnection conn = getConnection(); - for(String uri : annotationUris) { + + for(String uri : annotationUris) { + String removeIncomingsAnnotationQuery = getRemoveAllSuperAnnotationQuery(uri).buildRequest().toString(); String removeAnnotationQuery = getRemoveAllAnnotationTripleQuery(uri).buildRequest().toString(); + // first delete all annotation which has the annotationUri as target Update update = conn.prepareUpdate(QueryLanguage.SPARQL,removeIncomingsAnnotationQuery); - update.execute(); // first delete all annotation which has the annotationUri as target + update.execute(); + // then delete the annotation itself update = conn.prepareUpdate(QueryLanguage.SPARQL,removeAnnotationQuery); update.execute(); // then delete the annotation itself } @@ -602,7 +612,9 @@ protected void deleteAll(List annotationUris) throws RepositoryException @Override public void delete(List annotations) throws DAOPersistenceException, Exception, IllegalAccessException, IllegalAccessException { - ArrayList uris = annotations.stream().map(annotation -> annotation.getUri()) // get all annotation URIs into an ArrayList via Stream API + // get all annotation URIs into an ArrayList via Stream API + ArrayList uris = annotations.stream() + .map(annotation -> annotation.getUri()) .collect(Collectors.toCollection(ArrayList::new)); checkAndDeleteAll(uris); } diff --git a/phis2-ws/src/main/java/opensilex/service/dao/EventDAO.java b/phis2-ws/src/main/java/opensilex/service/dao/EventDAO.java index 842d29083..55c80efe9 100644 --- a/phis2-ws/src/main/java/opensilex/service/dao/EventDAO.java +++ b/phis2-ws/src/main/java/opensilex/service/dao/EventDAO.java @@ -647,7 +647,9 @@ public void addDeleteWhenUpdatingToUpdateBuilder(UpdateBuilder updateBuilder, Ev @Override public void delete(List events) throws DAOPersistenceException, Exception { - List uris = events.stream().map(event -> event.getUri()) // get all events URIs into an ArrayList via Stream API + // get all events URIs into an ArrayList via Stream API + List uris = events.stream() + .map(event -> event.getUri()) .collect(Collectors.toCollection(ArrayList::new)); checkAndDeleteAll(uris); } @@ -660,16 +662,21 @@ public void delete(List events) throws DAOPersistenceException, Exception protected void deleteAll(List uris) throws RepositoryException { AnnotationDAO annotationDAO = new AnnotationDAO(user); - RepositoryConnection conn = getConnection(); - annotationDAO.setConnection(conn); // make sure the two DAO use the same connection + RepositoryConnection conn = getConnection(); + + // make sure the two DAO use the same connection + annotationDAO.setConnection(conn); for(String eventUri : uris) { + + // get all annotation on event before deleting the event itself List annotationUris = getAllAnnotationUrisWithEventAsTarget(eventUri); UpdateBuilder deleteEventQuery = deleteEventTriples(eventUri); Update deleteEventUpdate = conn.prepareUpdate(QueryLanguage.SPARQL,deleteEventQuery.build().toString()); deleteEventUpdate.execute(); - + + // delete all annotation which have the given event as target if(! annotationUris.isEmpty()) annotationDAO.deleteAll(annotationUris); } @@ -678,41 +685,42 @@ protected void deleteAll(List uris) throws RepositoryException { /** * @return the {@link List} of {@link Annotation} which only have the given event uri as target. * @example - * select distinct ?a
- * where {
- * ?a oa:hasTarget "http://www.phenome-fppn.fr/id/event/5a1b3c0d-58af-4cfb-811e-e141b11453b1".
- * ?a oa:hasTarget ?t2.
- * FILTER ( - * "http://www.phenome-fppn.fr/id/event/5a1b3c0d-58af-4cfb-811e-e141b11453b1" = ?t2)
- * }
+ * SELECT DISTINCT ?a + * WHERE { + * ?annotation oa:hasTarget "http://www.phenome-fppn.fr/id/event/5a1b3c0d-58af-4cfb-811e-e141b11453b1". + * MINUS { + * ?annotation oa:hasTarget ?target. + * FILTER ("http://www.phenome-fppn.fr/id/event/5a1b3c0d-58af-4cfb-811e-e141b11453b1" = ?target) + * } + * + * } * @param eventUri */ protected List getAllAnnotationUrisWithEventAsTarget(String eventUri) { - Node a = NodeFactory.createVariable("a"), - t = NodeFactory.createVariable("t"), + Node annotation = NodeFactory.createVariable("annotation"), + target = NodeFactory.createVariable("target"), oaTargetPred = NodeFactory.createURI(Oa.RELATION_HAS_TARGET.toString()), - eventNode = NodeFactory.createURI(eventUri), + event = 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) + .addVar(annotation) + .addGraph(annotationGraph, new WhereBuilder() + .addWhere(annotation,oaTargetPred,event) .addMinus(new WhereBuilder() - .addWhere(a,oaTargetPred,t) - .addFilter(new ExprFactory().ne(eventNode, t))) + .addWhere(annotation,oaTargetPred,target) + .addFilter(new ExprFactory().ne(event, target))) ) .buildString(); - - + List 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()); + annotationUris.add(bs.getValue(annotation.getName()).stringValue()); } return annotationUris; } @@ -720,47 +728,44 @@ protected List getAllAnnotationUrisWithEventAsTarget(String eventUri) { /** * @return an {@link UpdateBuilder} producing a SPARQL query which remove all event triples * @example - * PREFIX oeso: - * PREFIX 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" ?p ?o .
+     * 	    ?s ?p_in "http://www.phenome-fppn.fr/id/event/5a1b3c0d-58af-4cfb-811e-e141b11453b1" .
      *  	?time ?time_pred ?time_object 
-     *  
-     * }  WHERE { 
-     * 			?s ?p1 
-     *          ?p ?o ;
+     * } WHERE { 
+     *		{ "http://www.phenome-fppn.fr/id/event/5a1b3c0d-58af-4cfb-811e-e141b11453b1" ?p_out ?o ;
      *          																time:hasTime ?time. 
-     *         ?time ?time_pred ?time_object .
+     *       ?time ?time_pred ?time_object . }
+     *       UNION { ?s ?p_in "http://www.phenome-fppn.fr/id/event/5a1b3c0d-58af-4cfb-811e-e141b11453b1" }
      *     }   
      * }
+     * 
* @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"), + Node outPredicate = NodeFactory.createVariable("p_out"), + object = NodeFactory.createVariable("o"), + subject = NodeFactory.createVariable("s"), + inPredicate = NodeFactory.createVariable("p_in"), time = NodeFactory.createVariable("time"), timePred = NodeFactory.createVariable("time_pred"), timeObj = NodeFactory.createVariable("time_object"); - Node hasTimePred = NodeFactory.createURI(Time.hasTime.getURI()), // Query uris + Node hasTimePred = NodeFactory.createURI(Time.hasTime.getURI()), eventNode = NodeFactory.createURI(eventUri); - // eventGraph = NodeFactory.createURI(Contexts.EVENTS.toString()); return new UpdateBuilder() - .addDelete(eventNode,p,o) + .addDelete(eventNode,outPredicate,object) .addDelete(time,timePred,timeObj) - .addDelete(s,p1,eventNode) - .addWhere(eventNode, p, o) // add the UNION + .addDelete(subject,inPredicate,eventNode) + + .addWhere(eventNode,outPredicate,object) .addWhere(eventNode,hasTimePred,time) .addWhere(time,timePred,timeObj) - .addUnion(new WhereBuilder() - .addWhere(s,p1,eventNode) - ); + .addUnion( + new WhereBuilder().addWhere(subject,inPredicate,eventNode)); } @Override From f27f30e1a179a01f9d9cb3949f8dc23a07ae31a4 Mon Sep 17 00:00:00 2001 From: renaud colin Date: Tue, 17 Dec 2019 10:23:49 +0100 Subject: [PATCH 13/14] Improve documentation about Event and Annotation DAO SPARQL queries. Improve corresponding Services and unit tests documentation and code style. --- .../opensilex/service/dao/AnnotationDAO.java | 24 ++++++++-------- .../java/opensilex/service/dao/EventDAO.java | 2 +- .../service/dao/manager/Rdf4jDAO.java | 28 ++++++++----------- .../resource/AnnotationResourceService.java | 6 ++++ .../resource/EventResourceService.java | 10 +++++-- .../service/resource/ResourceService.java | 2 +- .../service/dao/AnnotationDAOTest.java | 25 ++++++++++------- 7 files changed, 55 insertions(+), 42 deletions(-) diff --git a/phis2-ws/src/main/java/opensilex/service/dao/AnnotationDAO.java b/phis2-ws/src/main/java/opensilex/service/dao/AnnotationDAO.java index e90f7a118..d506dfd7b 100644 --- a/phis2-ws/src/main/java/opensilex/service/dao/AnnotationDAO.java +++ b/phis2-ws/src/main/java/opensilex/service/dao/AnnotationDAO.java @@ -534,12 +534,12 @@ private ArrayList getAnnotationsWithoutBodyValuesFromResult(TupleQue protected UpdateBuilder getRemoveAllSuperAnnotationQuery(String annotationUri) throws RepositoryException, UpdateExecutionException { Node srcAnnotation = NodeFactory.createVariable("src_a"), - srcAnnotationTarget = NodeFactory.createVariable("src_a_target"), - srcAnnotationTarget2 = NodeFactory.createVariable("src_a_target2"), - srcAnnotationPredicate = NodeFactory.createVariable("src_a_pred"), - srcAnnotationObject = NodeFactory.createVariable("src_a_obj"), - oaTargetPred = NodeFactory.createURI(Oa.RELATION_HAS_TARGET.toString()), - targetAnnotation = NodeFactory.createURI(annotationUri); + srcAnnotationTarget = NodeFactory.createVariable("src_a_target"), + srcAnnotationTarget2 = NodeFactory.createVariable("src_a_target2"), + srcAnnotationPredicate = NodeFactory.createVariable("src_a_pred"), + srcAnnotationObject = NodeFactory.createVariable("src_a_obj"), + oaTargetPred = NodeFactory.createURI(Oa.RELATION_HAS_TARGET.toString()), + targetAnnotation = NodeFactory.createURI(annotationUri); Path oaTargetPath = PathFactory.pathOneOrMore1(PathFactory.pathLink(oaTargetPred)); // create the property path (oa:target)+ @@ -547,7 +547,9 @@ protected UpdateBuilder getRemoveAllSuperAnnotationQuery(String annotationUri) t .addDelete(srcAnnotation, srcAnnotationPredicate, srcAnnotationObject) .addWhere(new TriplePath(srcAnnotation, oaTargetPath, targetAnnotation) ) .addWhere(srcAnnotation, srcAnnotationPredicate, srcAnnotationObject) - .addMinus(new WhereBuilder() // add the minus clause in order to check if the annotation has more than one target + + // add the minus clause in order to check if the annotation has more than one target + .addMinus(new WhereBuilder() .addWhere(srcAnnotation, oaTargetPred, srcAnnotationTarget) .addWhere(srcAnnotation, oaTargetPred, srcAnnotationTarget2) .addFilter(new ExprFactory().ne(srcAnnotationTarget, srcAnnotationTarget2)) @@ -595,7 +597,7 @@ protected void deleteAll(List annotationUris) throws RepositoryException RepositoryConnection conn = getConnection(); - for(String uri : annotationUris) { + for(String uri : annotationUris) { String removeIncomingsAnnotationQuery = getRemoveAllSuperAnnotationQuery(uri).buildRequest().toString(); String removeAnnotationQuery = getRemoveAllAnnotationTripleQuery(uri).buildRequest().toString(); @@ -605,7 +607,7 @@ protected void deleteAll(List annotationUris) throws RepositoryException update.execute(); // then delete the annotation itself update = conn.prepareUpdate(QueryLanguage.SPARQL,removeAnnotationQuery); - update.execute(); // then delete the annotation itself + update.execute(); } } @@ -614,8 +616,8 @@ public void delete(List annotations) throws DAOPersistenceException, // get all annotation URIs into an ArrayList via Stream API ArrayList uris = annotations.stream() - .map(annotation -> annotation.getUri()) - .collect(Collectors.toCollection(ArrayList::new)); + .map(annotation -> annotation.getUri()) + .collect(Collectors.toCollection(ArrayList::new)); checkAndDeleteAll(uris); } diff --git a/phis2-ws/src/main/java/opensilex/service/dao/EventDAO.java b/phis2-ws/src/main/java/opensilex/service/dao/EventDAO.java index 55c80efe9..507034aad 100644 --- a/phis2-ws/src/main/java/opensilex/service/dao/EventDAO.java +++ b/phis2-ws/src/main/java/opensilex/service/dao/EventDAO.java @@ -765,7 +765,7 @@ protected UpdateBuilder deleteEventTriples(String eventUri) { .addWhere(eventNode,hasTimePred,time) .addWhere(time,timePred,timeObj) .addUnion( - new WhereBuilder().addWhere(subject,inPredicate,eventNode)); + new WhereBuilder().addWhere(subject,inPredicate,eventNode)); } @Override diff --git a/phis2-ws/src/main/java/opensilex/service/dao/manager/Rdf4jDAO.java b/phis2-ws/src/main/java/opensilex/service/dao/manager/Rdf4jDAO.java index 1ffb58997..d2208da4c 100644 --- a/phis2-ws/src/main/java/opensilex/service/dao/manager/Rdf4jDAO.java +++ b/phis2-ws/src/main/java/opensilex/service/dao/manager/Rdf4jDAO.java @@ -14,6 +14,7 @@ import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; +import org.apache.commons.lang3.NotImplementedException; import org.apache.commons.lang3.StringUtils; import org.apache.jena.arq.querybuilder.UpdateBuilder; import org.apache.jena.graph.Node; @@ -605,7 +606,7 @@ public List findLabelsForUri(String uri) { * @throws UpdateExecutionException */ protected void deleteAll(List uris) throws RepositoryException, UpdateExecutionException { - + throw new NotImplementedException(""); } /** @@ -613,17 +614,19 @@ protected void deleteAll(List uris) throws RepositoryException, UpdateEx * @param uris : the list of URI to delete * @throws IllegalArgumentException if the {@link #user} is not an Admin user or if a given URI is not present * into the TripleStore. - * @throws DAOPersistenceException : if an {@link Exception} related to the {@link Repository} is encountered. - * @throws Exception : for any other encountered {@link Exception} + * + * @throws Exception + * * @see #deleteAll(List) * @see UserDAO#isAdmin(User) */ - public void checkAndDeleteAll(List uris) throws IllegalArgumentException, DAOPersistenceException, Exception { + public void checkAndDeleteAll(List uris) throws IllegalArgumentException, Exception { if(user == null || StringUtils.isEmpty(user.getAdmin())) { throw new IllegalArgumentException("No user/bad user provided"); } - if(! new UserDAO().isAdmin(user)) { // the user is not an admin + // check if the user has the right to delete objects + if(! new UserDAO().isAdmin(user)) { throw new IllegalArgumentException("Error : only an admin user can delete an object"); } @@ -639,22 +642,14 @@ public void checkAndDeleteAll(List uris) throws IllegalArgumentException throw new IllegalArgumentException(errorMsgs.append(" don't belongs to the TripleStore").toString()); } - Exception returnedException = null; - try { + try { startTransaction(); deleteAll(uris); commitTransaction(); - } catch (RepositoryException | UpdateExecutionException e) { - rollbackTransaction(); - returnedException = new DAOPersistenceException(e); } catch(Exception e) { rollbackTransaction(); - returnedException = e; + throw e; } - finally { - if(returnedException != null) - throw returnedException; - } } @Override @@ -671,7 +666,8 @@ protected void closeConnection() { @Override protected void startTransaction() { - initConnection(); // init the connection if not done + // initialize the connection if not done + initConnection(); if(! connection.isActive()) connection.begin(); } diff --git a/phis2-ws/src/main/java/opensilex/service/resource/AnnotationResourceService.java b/phis2-ws/src/main/java/opensilex/service/resource/AnnotationResourceService.java index e79835df4..eb1de1878 100644 --- a/phis2-ws/src/main/java/opensilex/service/resource/AnnotationResourceService.java +++ b/phis2-ws/src/main/java/opensilex/service/resource/AnnotationResourceService.java @@ -313,6 +313,12 @@ protected List getUrisFromObjects (List createdObjects }) @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) + /** + * Delete each {@link Annotation} URI from {@link DeleteDTO#getUris()} + * @param deleteDTO : the DTO which contains the list of Annotation URI to delete + * @param context + * @return + */ public Response deleteAnnotationByUri( @ApiParam( value = DocumentationAnnotation.ANNOTATION_URI_DEFINITION, diff --git a/phis2-ws/src/main/java/opensilex/service/resource/EventResourceService.java b/phis2-ws/src/main/java/opensilex/service/resource/EventResourceService.java index 8f8224d36..4daefc1d2 100644 --- a/phis2-ws/src/main/java/opensilex/service/resource/EventResourceService.java +++ b/phis2-ws/src/main/java/opensilex/service/resource/EventResourceService.java @@ -476,9 +476,7 @@ protected List getUrisFromObjects (List createdObjects @Path("{uri}") @ApiOperation( value = "Delete a list of event", - notes = "Delete a list of event. Need URL encoded event URI" - - ) + notes = "Delete a list of event. Need URL encoded event URI") @ApiResponses(value = { @ApiResponse(code = 200, message = "Event(s) deleted", response = ResponseFormPOST.class), @ApiResponse(code = 400, message = DocumentationAnnotation.BAD_USER_INFORMATION), @@ -496,6 +494,12 @@ protected List getUrisFromObjects (List createdObjects }) @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) + /** + * Delete each {@link Event} URI from {@link DeleteDTO#getUris()} + * @param deleteDTO : the DTO which contains the list of Event URI to delete + * @param context + * @return + */ public Response deleteEventUri( @ApiParam( value = DocumentationAnnotation.EVENT_URI_DEFINITION, diff --git a/phis2-ws/src/main/java/opensilex/service/resource/ResourceService.java b/phis2-ws/src/main/java/opensilex/service/resource/ResourceService.java index d348dc7c1..83ce56c0c 100644 --- a/phis2-ws/src/main/java/opensilex/service/resource/ResourceService.java +++ b/phis2-ws/src/main/java/opensilex/service/resource/ResourceService.java @@ -376,7 +376,7 @@ else if(e instanceof IllegalAccessException) { /** * @param dao : a {@link Rdf4jDAO} used to delete a {@link List} of String URI. * @param deleteDTO : a {@link DeleteDTO} which contains a {@link List} of URI. - * @param msg : delete msg + * @param msg : delete message * @return */ protected Response buildDeleteObjectsByUriResponse(Rdf4jDAO dao, DeleteDTO deleteDTO, String msg) { diff --git a/phis2-ws/src/test/java/opensilex/service/dao/AnnotationDAOTest.java b/phis2-ws/src/test/java/opensilex/service/dao/AnnotationDAOTest.java index f84381489..8e368e0ca 100644 --- a/phis2-ws/src/test/java/opensilex/service/dao/AnnotationDAOTest.java +++ b/phis2-ws/src/test/java/opensilex/service/dao/AnnotationDAOTest.java @@ -68,9 +68,10 @@ protected void initDao() throws DAOPersistenceException, Exception { @Test /** - * Try to delete an annotation about one event + * Try to delete an annotation about one event . + * So the event annotation should be deleted */ - void test_delete_annotation() throws DAOPersistenceException, Exception { + void testDeleteAnnotation() throws DAOPersistenceException, Exception { long initialSize = annotationDao.getConnection().size(); @@ -83,9 +84,10 @@ void test_delete_annotation() throws DAOPersistenceException, Exception { @Test /** - * Try to delete an annotation about one event. This annotation also have severals annotation. + * Try to delete an annotation about one event. This annotation also have severals annotation. + * So the event annotation should not be deleted */ - void test_delete_annotation_with_one_super_annotation() throws DAOPersistenceException, Exception { + void testDeleteAnnotation_with_one_super_annotation() throws DAOPersistenceException, Exception { long initialSize = annotationDao.getConnection().size(); @@ -104,9 +106,10 @@ void test_delete_annotation_with_one_super_annotation() throws DAOPersistenceExc * by a annotation a1 which also have an annotation. * A simple RDF representation would be * , , ... , + * * */ - void test_delete_annotation_with_recursive_annotation_chain() throws DAOPersistenceException, Exception { + void testDeleteAnnotationWithRecursiveAnnotationChain() throws DAOPersistenceException, Exception { long initialSize = annotationDao.getConnection().size(); @@ -143,19 +146,21 @@ void test_delete_annotation_with_recursive_annotation_chain() throws DAOPersiste @Test /** - * @throws Exception - * @throws DAOPersistenceException + * Try to delete an annotation "a" on an event "e". + * Then add an annotation a2 on "a" and on a scientific object "so". + * + * We delete a, so the relation between a and a2 must be deleted but a2 must still exists. * */ - void test_delete_annotation_with_one_super_annotation_with_another_target() throws DAOPersistenceException, Exception { + void testDeleteAnnotationWithOneSuperAnnotationWithAnotherTarget() throws DAOPersistenceException, Exception { Annotation a = createAndGetAnnotation(userUri,events.get(0).getUri()); events.add(createAndGetEvent(so.getUri())); // create a new event - Annotation a1 = createAndGetAnnotation(userUri,a.getUri(),events.get(1).getUri()); // annotation on a another annotation and on an event + Annotation a2 = createAndGetAnnotation(userUri,a.getUri(),events.get(1).getUri()); // annotation on a another annotation and on an event annotationDao.delete(Arrays.asList(a)); assertFalse(annotationDao.existUri(a.getUri())); - assertTrue(annotationDao.existUri(a1.getUri())); + assertTrue(annotationDao.existUri(a2.getUri())); } From 5f337ce28b68b045cdcfb101bc89b73cdf963e98 Mon Sep 17 00:00:00 2001 From: renaud colin Date: Thu, 19 Dec 2019 11:25:35 +0100 Subject: [PATCH 14/14] move the javadoc documentation before services specifications annotations Signed-off-by: renaud colin --- .../resource/AnnotationResourceService.java | 179 +++++++++--------- .../resource/EventResourceService.java | 11 +- 2 files changed, 94 insertions(+), 96 deletions(-) diff --git a/phis2-ws/src/main/java/opensilex/service/resource/AnnotationResourceService.java b/phis2-ws/src/main/java/opensilex/service/resource/AnnotationResourceService.java index eb1de1878..d2193cca8 100644 --- a/phis2-ws/src/main/java/opensilex/service/resource/AnnotationResourceService.java +++ b/phis2-ws/src/main/java/opensilex/service/resource/AnnotationResourceService.java @@ -61,9 +61,9 @@ @Path("/annotations") public class AnnotationResourceService extends ResourceService { final static Logger LOGGER = LoggerFactory.getLogger(SensorResourceService.class); - + public final static String EMPTY_ANNOTATION_LIST = "the annotation list to add is empty"; - + /** * Inserts the given annotations in the triplestore. * @param annotationsDtos annotationsDtos @@ -86,36 +86,36 @@ public class AnnotationResourceService extends ResourceService { @POST @ApiOperation(value = "Post annotations", notes = "Register new annotations in the triplestore") @ApiResponses(value = { - @ApiResponse(code = 201, message = "Annotations saved", response = ResponseFormPOST.class), - @ApiResponse(code = 400, message = DocumentationAnnotation.BAD_USER_INFORMATION), - @ApiResponse(code = 401, message = DocumentationAnnotation.USER_NOT_AUTHORIZED), - @ApiResponse(code = 500, message = DocumentationAnnotation.ERROR_SEND_DATA) + @ApiResponse(code = 201, message = "Annotations saved", response = ResponseFormPOST.class), + @ApiResponse(code = 400, message = DocumentationAnnotation.BAD_USER_INFORMATION), + @ApiResponse(code = 401, message = DocumentationAnnotation.USER_NOT_AUTHORIZED), + @ApiResponse(code = 500, message = DocumentationAnnotation.ERROR_SEND_DATA) }) @ApiImplicitParams({ - @ApiImplicitParam(name = GlobalWebserviceValues.AUTHORIZATION, required = true, - dataType = GlobalWebserviceValues.DATA_TYPE_STRING, paramType = GlobalWebserviceValues.HEADER, - value = DocumentationAnnotation.ACCES_TOKEN, - example = GlobalWebserviceValues.AUTHENTICATION_SCHEME + " ") + @ApiImplicitParam(name = GlobalWebserviceValues.AUTHORIZATION, required = true, + dataType = GlobalWebserviceValues.DATA_TYPE_STRING, paramType = GlobalWebserviceValues.HEADER, + value = DocumentationAnnotation.ACCES_TOKEN, + example = GlobalWebserviceValues.AUTHENTICATION_SCHEME + " ") }) public Response post( - @ApiParam(value = DocumentationAnnotation.ANNOTATION_POST_DATA_DEFINITION) + @ApiParam(value = DocumentationAnnotation.ANNOTATION_POST_DATA_DEFINITION) @Valid ArrayList annotationsDtos, - @Context HttpServletRequest context) { - + @Context HttpServletRequest context) { + // Set DAO AnnotationDAO objectDao = new AnnotationDAO(userSession.getUser()); if (context.getRemoteAddr() != null) { objectDao.remoteUserAdress = context.getRemoteAddr(); } - + return getPostResponse(objectDao, annotationsDtos, context.getRemoteAddr(), StatusCodeMsg.EMPTY_ANNOTATION_LIST); } /** * Searches annotations by URI, creator, comment, date of creation, target. - * @example { - * "metadata": { - * "pagination": { + * @example { + * "metadata": { + * "pagination": { * "pageSize": 20, * "currentPage": 0, * "totalCount": 297, @@ -124,8 +124,8 @@ public Response post( * "status": [], * "datafiles": [] * }, - * "result": { - * "data": [ { + * "result": { + * "data": [ { * "uri": "http://www.phenome-fppn.fr/platform/id/annotation/8247af37-769c-495b-8e7e-78b1141176c2", * "creator": "http://www.phenome-fppn.fr/diaphen/id/agent/arnaud_charleroy", * "creationDate": "2018-06-22 14:54:42+0200", @@ -147,16 +147,16 @@ public Response post( @ApiOperation(value = "Get all annotations corresponding to the search params given", notes = "Retrieve all annotations authorized for the user corresponding to the searched params given") @ApiResponses(value = { - @ApiResponse(code = 200, message = "Retrieve all annotations", response = AnnotationDTO.class, responseContainer = "List"), - @ApiResponse(code = 400, message = DocumentationAnnotation.BAD_USER_INFORMATION), - @ApiResponse(code = 401, message = DocumentationAnnotation.USER_NOT_AUTHORIZED), - @ApiResponse(code = 500, message = DocumentationAnnotation.ERROR_FETCH_DATA) + @ApiResponse(code = 200, message = "Retrieve all annotations", response = AnnotationDTO.class, responseContainer = "List"), + @ApiResponse(code = 400, message = DocumentationAnnotation.BAD_USER_INFORMATION), + @ApiResponse(code = 401, message = DocumentationAnnotation.USER_NOT_AUTHORIZED), + @ApiResponse(code = 500, message = DocumentationAnnotation.ERROR_FETCH_DATA) }) @ApiImplicitParams({ - @ApiImplicitParam(name = GlobalWebserviceValues.AUTHORIZATION, required = true, - dataType = GlobalWebserviceValues.DATA_TYPE_STRING, paramType = GlobalWebserviceValues.HEADER, - value = DocumentationAnnotation.ACCES_TOKEN, - example = GlobalWebserviceValues.AUTHENTICATION_SCHEME + " ") + @ApiImplicitParam(name = GlobalWebserviceValues.AUTHORIZATION, required = true, + dataType = GlobalWebserviceValues.DATA_TYPE_STRING, paramType = GlobalWebserviceValues.HEADER, + value = DocumentationAnnotation.ACCES_TOKEN, + example = GlobalWebserviceValues.AUTHENTICATION_SCHEME + " ") }) @Produces(MediaType.APPLICATION_JSON) public Response getAnnotationsBySearch( @@ -172,8 +172,8 @@ public Response getAnnotationsBySearch( ArrayList annotations; try { annotations = annotationDao.find(uri, creator, target, bodyValue, motivatedBy, page, pageSize); - - // handle search exceptions + + // handle search exceptions } catch (DAOPersistenceException ex) { LOGGER.error(ex.getMessage(), ex); return getResponseWhenPersistenceError(ex); @@ -189,8 +189,8 @@ public Response getAnnotationsBySearch( try { int totalCount = annotationDao.count(uri, creator, target, bodyValue, motivatedBy); return getGETResponseWhenSuccess(annotations, pageSize, page, totalCount); - - // handle count exceptions + + // handle count exceptions } catch (DAOPersistenceException ex) { LOGGER.error(ex.getMessage(), ex); return getResponseWhenPersistenceError(ex); @@ -206,8 +206,8 @@ public Response getAnnotationsBySearch( * @example * { * "metadata": { "pagination": null, "status": [], "datafiles": [] }, - * "result": { - * "data": [ { + * "result": { + * "data": [ { * "uri": "http://www.phenome-fppn.fr/platform/id/annotation/8247af37-769c-495b-8e7e-78b1141176c2", * "creator": "http://www.phenome-fppn.fr/diaphen/id/agent/arnaud_charleroy", * "creationDate": "2018-06-22 14:54:42+0200", @@ -226,29 +226,29 @@ public Response getAnnotationsBySearch( @ApiOperation(value = "Get a annotation", notes = "Retrieve a annotation. Need URL encoded annotation URI") @ApiResponses(value = { - @ApiResponse( - code = 200, - message = "Retrieve a annotation", - response = AnnotationDTO.class, - responseContainer = "List"), - @ApiResponse(code = 400, message = DocumentationAnnotation.BAD_USER_INFORMATION), - @ApiResponse(code = 401, message = DocumentationAnnotation.USER_NOT_AUTHORIZED), - @ApiResponse(code = 500, message = DocumentationAnnotation.ERROR_FETCH_DATA) + @ApiResponse( + code = 200, + message = "Retrieve a annotation", + response = AnnotationDTO.class, + responseContainer = "List"), + @ApiResponse(code = 400, message = DocumentationAnnotation.BAD_USER_INFORMATION), + @ApiResponse(code = 401, message = DocumentationAnnotation.USER_NOT_AUTHORIZED), + @ApiResponse(code = 500, message = DocumentationAnnotation.ERROR_FETCH_DATA) }) @ApiImplicitParams({ - @ApiImplicitParam(name = GlobalWebserviceValues.AUTHORIZATION, required = true, - dataType = GlobalWebserviceValues.DATA_TYPE_STRING, paramType = GlobalWebserviceValues.HEADER, - value = DocumentationAnnotation.ACCES_TOKEN, - example = GlobalWebserviceValues.AUTHENTICATION_SCHEME + " ") + @ApiImplicitParam(name = GlobalWebserviceValues.AUTHORIZATION, required = true, + dataType = GlobalWebserviceValues.DATA_TYPE_STRING, paramType = GlobalWebserviceValues.HEADER, + value = DocumentationAnnotation.ACCES_TOKEN, + example = GlobalWebserviceValues.AUTHENTICATION_SCHEME + " ") }) @Produces(MediaType.APPLICATION_JSON) public Response getAnnotationByUri( @ApiParam( - value = DocumentationAnnotation.SENSOR_URI_DEFINITION, - required = true, - example = DocumentationAnnotation.EXAMPLE_SENSOR_URI) - @URL @PathParam("uri") String uri) { - + value = DocumentationAnnotation.SENSOR_URI_DEFINITION, + required = true, + example = DocumentationAnnotation.EXAMPLE_SENSOR_URI) + @URL @PathParam("uri") String uri) { + return getGETByUriResponseFromDAOResults(new AnnotationDAO(userSession.getUser()), uri); } @@ -261,7 +261,7 @@ protected ArrayList getDTOsFromObjects(List getObjectsFromDTOs (List dtos) throws Exception { @@ -271,7 +271,7 @@ protected List getObjectsFromDTOs (List getUrisFromObjects (List createdObjects) { List createdUris = new ArrayList<>(createdObjects.size()); @@ -280,59 +280,58 @@ protected List getUrisFromObjects (List createdObjects }); return createdUris; } - + /** + * Delete each {@link Annotation} URI from {@link DeleteDTO#getUris()} + * @param deleteDTO : the DTO which contains the list of Annotation URI to delete + * @param context + * @return + * * @example *[ * http://www.phenome-fppn.fr/platform/id/annotation/8247af37-769c-495b-8e7e-78b1141176c2, * http://www.phenome-fppn.fr/platform/id/annotation/8247gt37-769c-495b-8e7e-91jh633151k4 *] - * + * */ @DELETE @Path("{uri}") @ApiOperation( - value = "Delete a list of annotation", - notes = "Delete a list of annotation. Need URL encoded annotation URI" - - ) + value = "Delete a list of annotation", + notes = "Delete a list of annotation. Need URL encoded annotation URI" + + ) @ApiResponses(value = { - @ApiResponse(code = 200, message = "Annotation(s) deleted", response = ResponseFormPOST.class), - @ApiResponse(code = 400, message = DocumentationAnnotation.BAD_USER_INFORMATION), - @ApiResponse(code = 401, message = DocumentationAnnotation.USER_NOT_AUTHORIZED), - @ApiResponse(code = 500, message = DocumentationAnnotation.INTERNAL_SERVER_ERROR), + @ApiResponse(code = 200, message = "Annotation(s) deleted", response = ResponseFormPOST.class), + @ApiResponse(code = 400, message = DocumentationAnnotation.BAD_USER_INFORMATION), + @ApiResponse(code = 401, message = DocumentationAnnotation.USER_NOT_AUTHORIZED), + @ApiResponse(code = 500, message = DocumentationAnnotation.INTERNAL_SERVER_ERROR), }) @ApiImplicitParams({ - @ApiImplicitParam( - name = GlobalWebserviceValues.AUTHORIZATION, - required = true, - dataType = GlobalWebserviceValues.DATA_TYPE_STRING, - paramType = GlobalWebserviceValues.HEADER, - value = DocumentationAnnotation.ACCES_TOKEN, - example = GlobalWebserviceValues.AUTHENTICATION_SCHEME + " ") + @ApiImplicitParam( + name = GlobalWebserviceValues.AUTHORIZATION, + required = true, + dataType = GlobalWebserviceValues.DATA_TYPE_STRING, + paramType = GlobalWebserviceValues.HEADER, + value = DocumentationAnnotation.ACCES_TOKEN, + example = GlobalWebserviceValues.AUTHENTICATION_SCHEME + " ") }) @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) - /** - * Delete each {@link Annotation} URI from {@link DeleteDTO#getUris()} - * @param deleteDTO : the DTO which contains the list of Annotation URI to delete - * @param context - * @return - */ - public Response deleteAnnotationByUri( - @ApiParam( - value = DocumentationAnnotation.ANNOTATION_URI_DEFINITION, - required = true, - example = DocumentationAnnotation.EXAMPLE_ANNOTATION_URI - ) - @Valid @NotNull DeleteDTO deleteDTO, @Context HttpServletRequest context) { - - AnnotationDAO annotationDAO = new AnnotationDAO(userSession.getUser()); - if (context.getRemoteAddr() != null) { - annotationDAO.setRemoteUserAdress(context.getRemoteAddr()); - } - Response response = buildDeleteObjectsByUriResponse(annotationDAO, deleteDTO,"Annotation(s) deleted"); - annotationDAO.getConnection().close(); - return response; + public Response deleteAnnotationByUri( + @ApiParam( + value = DocumentationAnnotation.ANNOTATION_URI_DEFINITION, + required = true, + example = DocumentationAnnotation.EXAMPLE_ANNOTATION_URI + ) + @Valid @NotNull DeleteDTO deleteDTO, @Context HttpServletRequest context) { + + AnnotationDAO annotationDAO = new AnnotationDAO(userSession.getUser()); + if (context.getRemoteAddr() != null) { + annotationDAO.setRemoteUserAdress(context.getRemoteAddr()); + } + Response response = buildDeleteObjectsByUriResponse(annotationDAO, deleteDTO,"Annotation(s) deleted"); + annotationDAO.getConnection().close(); + return response; } } diff --git a/phis2-ws/src/main/java/opensilex/service/resource/EventResourceService.java b/phis2-ws/src/main/java/opensilex/service/resource/EventResourceService.java index 4daefc1d2..f45606228 100644 --- a/phis2-ws/src/main/java/opensilex/service/resource/EventResourceService.java +++ b/phis2-ws/src/main/java/opensilex/service/resource/EventResourceService.java @@ -465,6 +465,11 @@ protected List getUrisFromObjects (List createdObjects } /** + * Delete each {@link Event} URI from {@link DeleteDTO#getUris()} + * @param deleteDTO : the DTO which contains the list of Event URI to delete + * @param context + * @return + * * @example *[ * http://www.phenome-fppn.fr/platform/id/event/8247af37-769c-495b-8e7e-78b1141176c2, @@ -494,12 +499,6 @@ protected List getUrisFromObjects (List createdObjects }) @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) - /** - * Delete each {@link Event} URI from {@link DeleteDTO#getUris()} - * @param deleteDTO : the DTO which contains the list of Event URI to delete - * @param context - * @return - */ public Response deleteEventUri( @ApiParam( value = DocumentationAnnotation.EVENT_URI_DEFINITION,