diff --git a/model/src/main/java/lcsb/mapviewer/model/map/Comment.java b/model/src/main/java/lcsb/mapviewer/model/map/Comment.java index be21199109311f34686493928f6bcb1367f73ed3..fac60ec25baf83375e1897becb406d23c16b7d1f 100644 --- a/model/src/main/java/lcsb/mapviewer/model/map/Comment.java +++ b/model/src/main/java/lcsb/mapviewer/model/map/Comment.java @@ -1,6 +1,16 @@ package lcsb.mapviewer.model.map; -import java.awt.geom.Point2D; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import lcsb.mapviewer.model.MinervaEntity; +import lcsb.mapviewer.model.map.model.Model; +import lcsb.mapviewer.model.map.model.ModelData; +import lcsb.mapviewer.model.map.reaction.Reaction; +import lcsb.mapviewer.model.map.species.Element; +import lcsb.mapviewer.model.user.User; +import lcsb.mapviewer.modelutils.serializer.model.map.ModelAsIdSerializer; +import org.hibernate.annotations.Type; import javax.persistence.Column; import javax.persistence.Entity; @@ -10,32 +20,18 @@ import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.ManyToOne; import javax.persistence.Version; - -import org.hibernate.annotations.Type; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; - -import lcsb.mapviewer.model.MinervaEntity; -import lcsb.mapviewer.model.map.model.Model; -import lcsb.mapviewer.model.map.model.ModelData; -import lcsb.mapviewer.model.map.reaction.Reaction; -import lcsb.mapviewer.model.map.species.Element; -import lcsb.mapviewer.model.user.User; -import lcsb.mapviewer.modelutils.serializer.model.map.CommentSerializer; +import java.awt.geom.Point2D; /** * Class representing comments on the map. - * + * * @author Piotr Gawron - * */ @Entity -@JsonSerialize(using = CommentSerializer.class) public class Comment implements MinervaEntity { /** - * + * */ private static final long serialVersionUID = 1L; @@ -48,6 +44,7 @@ public class Comment implements MinervaEntity { * What was the reason of removal. */ @Column(length = 255) + @JsonIgnore private String removeReason = ""; /** @@ -61,24 +58,28 @@ public class Comment implements MinervaEntity { * The model that was commented. */ @ManyToOne(fetch = FetchType.LAZY, optional = false) + @JsonSerialize(using = ModelAsIdSerializer.class) + @JsonProperty(value = "map") private ModelData model; /** * User who gave the feedback (if logged in). */ @ManyToOne(fetch = FetchType.LAZY) + @JsonIgnore private User user; /** * Email of the user who gave feedback. */ @Column(length = 255) + @JsonIgnore private String email; /** * Content of the feedback. */ - @Column(columnDefinition = "TEXT") + @Column(columnDefinition = "TEXT", nullable = false) private String content; /** @@ -88,14 +89,17 @@ public class Comment implements MinervaEntity { private Point2D coordinates; @ManyToOne(optional = true) + @JsonIgnore private Reaction reaction; @ManyToOne(optional = true) + @JsonIgnore private Element element; /** * Determines if comment should be visible on the map. */ + @JsonProperty(value = "visible") private boolean pinned = false; @Version @@ -111,8 +115,7 @@ public class Comment implements MinervaEntity { } /** - * @param coordinates - * the coordinates to set + * @param coordinates the coordinates to set * @see #coordinates */ public void setCoordinates(final Point2D coordinates) { @@ -128,8 +131,7 @@ public class Comment implements MinervaEntity { } /** - * @param content - * the content to set + * @param content the content to set * @see #content */ public void setContent(final String content) { @@ -145,8 +147,7 @@ public class Comment implements MinervaEntity { } /** - * @param email - * the email to set + * @param email the email to set * @see #email */ public void setEmail(final String email) { @@ -162,8 +163,7 @@ public class Comment implements MinervaEntity { } /** - * @param user - * the user to set + * @param user the user to set * @see #user */ public void setUser(final User user) { @@ -174,13 +174,13 @@ public class Comment implements MinervaEntity { * @return the model * @see #model */ + @JsonIgnore public ModelData getModelData() { return model; } /** - * @param model - * the model to set + * @param model the model to set * @see #model */ public void setModelData(final ModelData model) { @@ -197,8 +197,7 @@ public class Comment implements MinervaEntity { } /** - * @param id - * the id to set + * @param id the id to set * @see #id */ public void setId(final int id) { @@ -214,8 +213,7 @@ public class Comment implements MinervaEntity { } /** - * @param removeReason - * the removeReason to set + * @param removeReason the removeReason to set * @see #removeReason */ public void setRemoveReason(final String removeReason) { @@ -231,8 +229,7 @@ public class Comment implements MinervaEntity { } /** - * @param deleted - * the deleted to set + * @param deleted the deleted to set * @see #deleted */ public void setDeleted(final boolean deleted) { @@ -248,8 +245,7 @@ public class Comment implements MinervaEntity { } /** - * @param pinned - * the pinned to set + * @param pinned the pinned to set * @see #pinned */ public void setPinned(final boolean pinned) { @@ -258,9 +254,8 @@ public class Comment implements MinervaEntity { /** * Sets model. - * - * @param model2 - * model to set + * + * @param model2 model to set */ public void setModel(final Model model2) { this.model = model2.getModelData(); diff --git a/persist/src/main/java/lcsb/mapviewer/persist/dao/map/CommentDao.java b/persist/src/main/java/lcsb/mapviewer/persist/dao/map/CommentDao.java index d807fa424966ea403a352b712ae6240c70091e7d..b330b7af5841419604c1919c2136a8770e6b1895 100644 --- a/persist/src/main/java/lcsb/mapviewer/persist/dao/map/CommentDao.java +++ b/persist/src/main/java/lcsb/mapviewer/persist/dao/map/CommentDao.java @@ -1,24 +1,29 @@ package lcsb.mapviewer.persist.dao.map; -import java.util.ArrayList; -import java.util.List; - -import org.springframework.stereotype.Repository; - +import lcsb.mapviewer.common.exception.InvalidArgumentException; +import lcsb.mapviewer.model.Project; import lcsb.mapviewer.model.map.Comment; +import lcsb.mapviewer.model.map.model.Author; import lcsb.mapviewer.model.map.model.Model; import lcsb.mapviewer.model.map.model.ModelData; import lcsb.mapviewer.persist.dao.BaseDao; -import lcsb.mapviewer.persist.dao.MinervaEntityProperty; +import org.springframework.stereotype.Repository; + +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.Join; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; /** * Data access object class for Comment objects. - * + * * @author Piotr Gawron - * */ @Repository -public class CommentDao extends BaseDao<Comment, MinervaEntityProperty<Comment>> { +public class CommentDao extends BaseDao<Comment, CommentProperty> { /** * Default constructor. @@ -30,23 +35,20 @@ public class CommentDao extends BaseDao<Comment, MinervaEntityProperty<Comment>> /** * Returns list of comments for a model given in the parameter. The comments * are limited by the parameters. - * - * @param model - * in which model we want to find comments - * @param pinned - * this parameter defines what kind of comments we want to get: - * <ul> - * <li>null - all comments</li> - * <li>false - comments that are not visible on the map</li> - * <li>true - comments that are visible on the map</li> - * </ul> - * @param deleted - * this parameter defines what kind of comments we want to get: - * <ul> - * <li>null - all comments</li> - * <li>false - comments that are not deleted</li> - * <li>true - comments that are deleted</li> - * </ul> + * + * @param model in which model we want to find comments + * @param pinned this parameter defines what kind of comments we want to get: + * <ul> + * <li>null - all comments</li> + * <li>false - comments that are not visible on the map</li> + * <li>true - comments that are visible on the map</li> + * </ul> + * @param deleted this parameter defines what kind of comments we want to get: + * <ul> + * <li>null - all comments</li> + * <li>false - comments that are not deleted</li> + * <li>true - comments that are deleted</li> + * </ul> * @return list of comments that fulfill parameters constraints */ public List<Comment> getCommentByModel(final Model model, final Boolean pinned, final Boolean deleted) { @@ -56,28 +58,25 @@ public class CommentDao extends BaseDao<Comment, MinervaEntityProperty<Comment>> /** * Returns list of comments for a model given in the parameter. The comments * are limited by the parameters. - * - * @param modelId - * in which model we want to find comments - * @param pinned - * this parameter defines what kind of comments we want to get: - * <ul> - * <li>null - all comments</li> - * <li>false - comments that are not visible on the map</li> - * <li>true - comments that are visible on the map</li> - * </ul> - * @param deleted - * this parameter defines what kind of comments we want to get: - * <ul> - * <li>null - all comments</li> - * <li>false - comments that are not deleted</li> - * <li>true - comments that are deleted</li> - * </ul> + * + * @param modelId in which model we want to find comments + * @param pinned this parameter defines what kind of comments we want to get: + * <ul> + * <li>null - all comments</li> + * <li>false - comments that are not visible on the map</li> + * <li>true - comments that are visible on the map</li> + * </ul> + * @param deleted this parameter defines what kind of comments we want to get: + * <ul> + * <li>null - all comments</li> + * <li>false - comments that are not deleted</li> + * <li>true - comments that are deleted</li> + * </ul> * @return list of comments that fulfill parameters constraints */ private List<Comment> getCommentByModel(final int modelId, final Boolean pinned, final Boolean deleted) { List<Comment> comments = getElementsByParameter("model_id", modelId); - List<Comment> result = new ArrayList<Comment>(); + List<Comment> result = new ArrayList<>(); if (deleted != null) { for (final Comment comment : comments) { if (comment.isDeleted() == deleted) { @@ -92,7 +91,7 @@ public class CommentDao extends BaseDao<Comment, MinervaEntityProperty<Comment>> return result; } comments = result; - result = new ArrayList<Comment>(); + result = new ArrayList<>(); for (final Comment comment : comments) { if (comment.isPinned() == pinned) { result.add(comment); @@ -104,23 +103,20 @@ public class CommentDao extends BaseDao<Comment, MinervaEntityProperty<Comment>> /** * Returns list of comments for a model given in the parameter. The comments * are limited by the parameters. - * - * @param model - * in which model we want to find comments - * @param pinned - * this parameter defines what kind of comments we want to get: - * <ul> - * <li>null - all comments</li> - * <li>false - comments that are not visible on the map</li> - * <li>true - comments that are visible on the map</li> - * </ul> - * @param deleted - * this parameter defines what kind of comments we want to get: - * <ul> - * <li>null - all comments</li> - * <li>false - comments that are not deleted</li> - * <li>true - comments that are deleted</li> - * </ul> + * + * @param model in which model we want to find comments + * @param pinned this parameter defines what kind of comments we want to get: + * <ul> + * <li>null - all comments</li> + * <li>false - comments that are not visible on the map</li> + * <li>true - comments that are visible on the map</li> + * </ul> + * @param deleted this parameter defines what kind of comments we want to get: + * <ul> + * <li>null - all comments</li> + * <li>false - comments that are not deleted</li> + * <li>true - comments that are deleted</li> + * </ul> * @return list of comments that fulfill parameters constraints */ public List<Comment> getCommentByModel(final ModelData model, final Boolean pinned, final Boolean deleted) { @@ -137,10 +133,40 @@ public class CommentDao extends BaseDao<Comment, MinervaEntityProperty<Comment>> .setParameter("project_id", projectId) .setParameter("id", id) .list(); - if (list.size() > 0) { + if (!list.isEmpty()) { return list.get(0); } return null; } + protected Predicate createPredicate(final Map<CommentProperty, Object> filterOptions, final Root<Comment> root) { + CriteriaBuilder builder = getSession().getCriteriaBuilder(); + List<Predicate> predicates = new ArrayList<>(); + + for (CommentProperty key : filterOptions.keySet()) { + if (key.equals(CommentProperty.PROJECT_ID)) { + Join<Author, ModelData> modelJoin = root.join("model"); + Join<ModelData, Project> projectJoin = modelJoin.join("project"); + + Predicate predicate = builder.and( + builder.equal(projectJoin.get("projectId"), filterOptions.get(key))); + predicates.add(predicate); + } else if (key.equals(CommentProperty.MAP_ID)) { + Join<Author, ModelData> modelJoin = root.join("model"); + + Predicate predicate = builder.and( + builder.equal(modelJoin.get("id"), filterOptions.get(key))); + predicates.add(predicate); + } else if (key.equals(CommentProperty.ID)) { + + Predicate predicate = builder.and( + builder.equal(root.get("id"), filterOptions.get(key))); + predicates.add(predicate); + } else { + throw new InvalidArgumentException("Unknown property: " + key); + } + } + return builder.and(predicates.toArray(new Predicate[0])); + + } } diff --git a/persist/src/main/java/lcsb/mapviewer/persist/dao/map/CommentProperty.java b/persist/src/main/java/lcsb/mapviewer/persist/dao/map/CommentProperty.java new file mode 100644 index 0000000000000000000000000000000000000000..83e70ceb0b7450dfb847b2d34680ca211a81620f --- /dev/null +++ b/persist/src/main/java/lcsb/mapviewer/persist/dao/map/CommentProperty.java @@ -0,0 +1,12 @@ +package lcsb.mapviewer.persist.dao.map; + +import lcsb.mapviewer.model.map.Comment; +import lcsb.mapviewer.persist.dao.MinervaEntityProperty; + +public enum CommentProperty implements MinervaEntityProperty<Comment> { + PROJECT_ID, + MAP_ID, + ID, + DELETED, + VISIBLE, +} diff --git a/persist/src/test/java/lcsb/mapviewer/persist/PersistTestFunctionsNoTransaction.java b/persist/src/test/java/lcsb/mapviewer/persist/PersistTestFunctionsNoTransaction.java index 180be3fee5ab08cf7dd32142341ac393be2817e9..16895ca649e331bd321237789117fd958fd4570f 100644 --- a/persist/src/test/java/lcsb/mapviewer/persist/PersistTestFunctionsNoTransaction.java +++ b/persist/src/test/java/lcsb/mapviewer/persist/PersistTestFunctionsNoTransaction.java @@ -228,6 +228,8 @@ public abstract class PersistTestFunctionsNoTransaction extends TestUtils { protected Comment createComment(final Model model) { final Comment result = new Comment(); result.setModel(model); + result.setUser(model.getProject().getOwner()); + result.setContent("test content"); return result; } diff --git a/persist/src/test/java/lcsb/mapviewer/persist/dao/map/CommentDaoTest.java b/persist/src/test/java/lcsb/mapviewer/persist/dao/map/CommentDaoTest.java index a0453a3f9e03b7409ac5080d86bf8da504b85bc8..321df48b231e98a516970b7cdc7f70d37439948e 100644 --- a/persist/src/test/java/lcsb/mapviewer/persist/dao/map/CommentDaoTest.java +++ b/persist/src/test/java/lcsb/mapviewer/persist/dao/map/CommentDaoTest.java @@ -1,13 +1,5 @@ package lcsb.mapviewer.persist.dao.map; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.springframework.beans.factory.annotation.Autowired; - import lcsb.mapviewer.model.Project; import lcsb.mapviewer.model.map.Comment; import lcsb.mapviewer.model.map.MiriamData; @@ -26,6 +18,13 @@ import lcsb.mapviewer.model.map.species.field.Residue; import lcsb.mapviewer.persist.PersistTestFunctions; import lcsb.mapviewer.persist.dao.ProjectDao; import lcsb.mapviewer.persist.dao.user.UserDao; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; public class CommentDaoTest extends PersistTestFunctions { @@ -53,15 +52,14 @@ public class CommentDaoTest extends PersistTestFunctions { projectDao.add(project); return project; } - + @Test public void testGetById() throws Exception { Project project = createProject(); + int counter = (int) commentDao.getCount(); - Comment comment = new Comment(); - comment.setUser(project.getOwner()); - comment.setModel(project.getTopModel()); + Comment comment = createComment(project.getTopModel()); commentDao.add(comment); int counter2 = (int) commentDao.getCount(); assertEquals(counter + 1, counter2); @@ -74,18 +72,16 @@ public class CommentDaoTest extends PersistTestFunctions { public void testGetComments() { Project project = createProject(); - Comment comment = new Comment(); + Comment comment = createComment(project.getTopModel()); comment.setDeleted(true); - comment.setModel(project.getTopModel()); commentDao.add(comment); - Comment comment2 = new Comment(); + Comment comment2 = createComment(project.getTopModel()); comment2.setPinned(true); - comment2.setModel(project.getTopModel()); commentDao.add(comment2); Model model = project.getTopModel(); - + assertEquals(0, commentDao.getCommentByModel(model, true, true).size()); assertEquals(1, commentDao.getCommentByModel(model, false, true).size()); assertEquals(1, commentDao.getCommentByModel(model, null, true).size()); diff --git a/service/src/main/java/lcsb/mapviewer/services/impl/CommentService.java b/service/src/main/java/lcsb/mapviewer/services/impl/CommentService.java index 831426504c3f1f0831d09d8f922da2f9cc23f6ca..55f7f8fac1b0e90462d3f341d4a2335e15cf96e6 100644 --- a/service/src/main/java/lcsb/mapviewer/services/impl/CommentService.java +++ b/service/src/main/java/lcsb/mapviewer/services/impl/CommentService.java @@ -1,17 +1,6 @@ package lcsb.mapviewer.services.impl; -import java.awt.geom.Point2D; -import java.util.ArrayList; -import java.util.List; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.hibernate.Hibernate; -import org.hibernate.HibernateException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - +import lcsb.mapviewer.common.exception.NotImplementedException; import lcsb.mapviewer.model.Project; import lcsb.mapviewer.model.map.BioEntity; import lcsb.mapviewer.model.map.Comment; @@ -21,6 +10,7 @@ import lcsb.mapviewer.model.map.reaction.Reaction; import lcsb.mapviewer.model.map.species.Element; import lcsb.mapviewer.model.user.User; import lcsb.mapviewer.persist.dao.map.CommentDao; +import lcsb.mapviewer.persist.dao.map.CommentProperty; import lcsb.mapviewer.persist.dao.map.ModelDao; import lcsb.mapviewer.services.ObjectNotFoundException; import lcsb.mapviewer.services.interfaces.ICommentService; @@ -29,13 +19,26 @@ import lcsb.mapviewer.services.interfaces.IModelService; import lcsb.mapviewer.services.interfaces.IUserService; import lcsb.mapviewer.services.utils.EmailException; import lcsb.mapviewer.services.utils.EmailSender; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.hibernate.Hibernate; +import org.hibernate.HibernateException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.awt.geom.Point2D; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; /** * This class is responsible for all services connected with comments * functionality. * * @author Piotr Gawron - * */ @Transactional @@ -51,14 +54,14 @@ public class CommentService implements ICommentService { /** * Default class logger. */ - private static Logger logger = LogManager.getLogger(); + private static final Logger logger = LogManager.getLogger(); /** * Data access object fir comments. */ private CommentDao commentDao; - private ModelDao mapDao; + private final ModelDao mapDao; /** * Service for operations on Model object. @@ -77,10 +80,10 @@ public class CommentService implements ICommentService { @Autowired public CommentService(final CommentDao commentDao, - final IModelService modelService, - final IUserService userService, - final IConfigurationService configurationService, - final ModelDao mapDao) { + final IModelService modelService, + final IUserService userService, + final IConfigurationService configurationService, + final ModelDao mapDao) { this.commentDao = commentDao; this.modelService = modelService; this.userService = userService; @@ -90,7 +93,7 @@ public class CommentService implements ICommentService { @Override public Comment addComment(final String email, final String content, final Point2D coordinates, final BioEntity object, - final boolean pinned, final int mapId, final User owner) { + final boolean pinned, final int mapId, final User owner) { ModelData map = mapDao.getById(mapId); Comment comment = new Comment(); comment.setEmail(email); @@ -180,10 +183,11 @@ public class CommentService implements ICommentService { @Override public Comment getCommentById(final String projectId, final String commentId) { - int id = -1; + int id; try { id = Integer.parseInt(commentId); } catch (final NumberFormatException e) { + id = -1; } return getCommentById(projectId, id); } @@ -202,8 +206,7 @@ public class CommentService implements ICommentService { } /** - * @param commentDao - * the commentDao to set + * @param commentDao the commentDao to set * @see #commentDao */ public void setCommentDao(final CommentDao commentDao) { @@ -219,8 +222,7 @@ public class CommentService implements ICommentService { } /** - * @param modelService - * the modelService to set + * @param modelService the modelService to set * @see #modelService */ public void setModelService(final IModelService modelService) { @@ -236,8 +238,7 @@ public class CommentService implements ICommentService { } /** - * @param userService - * the userService to set + * @param userService the userService to set * @see #userService */ public void setUserService(final IUserService userService) { @@ -253,8 +254,7 @@ public class CommentService implements ICommentService { } /** - * @param configurationService - * the configurationService to set + * @param configurationService the configurationService to set * @see #configurationService */ public void setConfigurationService(final IConfigurationService configurationService) { @@ -264,12 +264,9 @@ public class CommentService implements ICommentService { /** * Checks if identifier of the points refer to the same point. * - * @param uniqueId - * identifier assigned by the java code - * @param objectId - * identifier assigned by the javascript code (browser) - * @return <code>true</code> if both identifiers refer to the same point, - * <code>false</code> otherwise + * @param uniqueId identifier assigned by the java code + * @param objectId identifier assigned by the javascript code (browser) + * @return <code>true</code> if both identifiers refer to the same point, <code>false</code> otherwise */ protected boolean equalPoints(final String uniqueId, final String objectId) { String tmp = uniqueId.substring(uniqueId.indexOf("[") + 1, uniqueId.indexOf("]")); @@ -292,14 +289,43 @@ public class CommentService implements ICommentService { if (comment == null || comment.getUser() == null) { return null; } - // fetch lazy data - comment.getUser().getLogin(); + Hibernate.initialize(comment.getUser()); return comment.getUser(); } @Override - public Comment add(final Comment comment) { - return commentDao.add(comment); + public Page<Comment> getAll(final Map<CommentProperty, Object> filter, final Pageable pageable) { + Page<Comment> page = commentDao.getAll(filter, pageable); + for (Comment comment : page.getContent()) { + Hibernate.initialize(comment.getUser()); + } + return page; + } + + @Override + public Comment getById(final int id) { + return commentDao.getById(id); + } + + @Override + public void update(final Comment object) { + throw new NotImplementedException(); + } + + @Override + public void remove(final Comment comment) { + comment.setDeleted(true); + commentDao.update(comment); + } + + @Override + public long getCount(final Map<CommentProperty, Object> filterOptions) { + throw new NotImplementedException(); + } + + @Override + public void add(final Comment comment) { + commentDao.add(comment); } } diff --git a/service/src/main/java/lcsb/mapviewer/services/impl/ModelService.java b/service/src/main/java/lcsb/mapviewer/services/impl/ModelService.java index 7cd68efd59887e4eb2e37fcfea6fd487a6772230..8d4fab3fae365bb56d056d33e9bc9b76b2c9f826 100644 --- a/service/src/main/java/lcsb/mapviewer/services/impl/ModelService.java +++ b/service/src/main/java/lcsb/mapviewer/services/impl/ModelService.java @@ -1,6 +1,5 @@ package lcsb.mapviewer.services.impl; -import lcsb.mapviewer.common.exception.NotImplementedException; import lcsb.mapviewer.model.map.MiriamType; import lcsb.mapviewer.model.map.compartment.Compartment; import lcsb.mapviewer.model.map.model.Model; @@ -158,7 +157,7 @@ public class ModelService implements IModelService { @Override public ModelData getById(final int id) { - throw new NotImplementedException(); + return modelDao.getById(id); } @Override diff --git a/service/src/main/java/lcsb/mapviewer/services/interfaces/ICommentService.java b/service/src/main/java/lcsb/mapviewer/services/interfaces/ICommentService.java index 15488ea297b1bab08542c3f51cd3bef8aa57c16a..c93b7fffa9b0d8bfc29a60ec365a4a0994455202 100644 --- a/service/src/main/java/lcsb/mapviewer/services/interfaces/ICommentService.java +++ b/service/src/main/java/lcsb/mapviewer/services/interfaces/ICommentService.java @@ -1,57 +1,46 @@ package lcsb.mapviewer.services.interfaces; -import java.awt.geom.Point2D; -import java.util.List; - -import org.hibernate.HibernateException; - import lcsb.mapviewer.model.Project; import lcsb.mapviewer.model.map.BioEntity; import lcsb.mapviewer.model.map.Comment; import lcsb.mapviewer.model.map.model.Model; import lcsb.mapviewer.model.map.model.ModelData; import lcsb.mapviewer.model.user.User; +import lcsb.mapviewer.persist.dao.map.CommentProperty; import lcsb.mapviewer.services.ObjectNotFoundException; +import org.hibernate.HibernateException; + +import java.awt.geom.Point2D; +import java.util.List; /** * Service responsible for comments functionality. - * + * * @author Piotr Gawron - * */ -public interface ICommentService { +public interface ICommentService extends CrudService<Comment, CommentProperty> { /** * Adds comment to the map. - * - * @param pinned - * parameter that defines if comment should be visible on the map. - * @param bioEntity - * determines which object is commented - it could be null; in this - * case it means that a comment is general one. - * @param email - * email of the person that comments - * @param content - * content of the comment - * @param mapId - * on which submodel we comment on - * @param coordinates - * where exactly the comment should be placed on - * + * + * @param pinned parameter that defines if comment should be visible on the map. + * @param bioEntity determines which object is commented - it could be null; in this + * case it means that a comment is general one. + * @param email email of the person that comments + * @param content content of the comment + * @param mapId on which submodel we comment on + * @param coordinates where exactly the comment should be placed on * @return comment object created based on the data provided as parameters */ Comment addComment(final String email, final String content, final Point2D coordinates, final BioEntity bioEntity, - final boolean pinned, final int mapId, final User owner); + final boolean pinned, final int mapId, final User owner); /** * This method remove comment. Comment is not removed from the system, only * 'deleted' flag is set. - * - * @param loggedUser - * user that wants to remove the comment - * @param commentId - * identifier of the comment that user wants to remove - * @param reason - * why user wants to remove the comment + * + * @param loggedUser user that wants to remove the comment + * @param commentId identifier of the comment that user wants to remove + * @param reason why user wants to remove the comment */ void deleteComment(final User loggedUser, final String commentId, final String reason); @@ -61,24 +50,22 @@ public interface ICommentService { /** * Returns number of comments in the system. - * + * * @return number of comments in the system */ long getCommentCount(); /** * Removes comments from the model. - * - * @param model - * from which model we want to remove comments + * + * @param model from which model we want to remove comments */ void removeCommentsForModel(final Model model); /** * Removes comments from the model. - * - * @param model - * from which model we want to remove comments + * + * @param model from which model we want to remove comments */ void removeCommentsForModel(final ModelData model); @@ -87,7 +74,4 @@ public interface ICommentService { Comment getCommentById(final String projectId, final Integer commentId); User getOwnerByCommentId(final String projectId, final String commentId); - - Comment add(Comment comment); - } diff --git a/web/src/main/java/lcsb/mapviewer/web/api/project/chemicals/NewChemicalController.java b/web/src/main/java/lcsb/mapviewer/web/api/project/chemicals/NewChemicalController.java index 5924f0f832470eaca1f600bb6170774aace6d187..96c2d61c8140c07649146d13a173176f6a63c63d 100644 --- a/web/src/main/java/lcsb/mapviewer/web/api/project/chemicals/NewChemicalController.java +++ b/web/src/main/java/lcsb/mapviewer/web/api/project/chemicals/NewChemicalController.java @@ -2,8 +2,10 @@ package lcsb.mapviewer.web.api.project.chemicals; import lcsb.mapviewer.annotation.data.Chemical; import lcsb.mapviewer.annotation.data.MeSH; +import lcsb.mapviewer.annotation.services.DrugSearchException; import lcsb.mapviewer.annotation.services.TaxonomyBackend; import lcsb.mapviewer.annotation.services.annotators.AnnotatorException; +import lcsb.mapviewer.annotation.services.dapi.ChemicalSearchException; import lcsb.mapviewer.api.BaseController; import lcsb.mapviewer.api.QueryException; import lcsb.mapviewer.common.Pair; @@ -82,7 +84,7 @@ public class NewChemicalController extends BaseController { } List<Chemical> data = new ArrayList<>(); - if (!query.equals("")) { + if (!query.isEmpty()) { MiriamData organism = project.getOrganism(); if (organism == null) { @@ -158,4 +160,15 @@ public class NewChemicalController extends BaseController { }); } + @PreAuthorize("hasAnyAuthority('IS_ADMIN', 'READ_PROJECT:' + #projectId)") + @GetMapping(value = "chemicals/suggestedQueryList") + public List<String> getSuggestedQueryList(final @PathVariable(value = "projectId") String projectId) + throws DrugSearchException, ObjectNotFoundException, ChemicalSearchException { + final Project project = projectService.getProjectByProjectId(projectId); + if (project == null) { + throw new ObjectNotFoundException("Project with given id doesn't exist"); + } + return chemicalService.getSuggestedQueryList(project, project.getDisease()); + } + } \ No newline at end of file diff --git a/web/src/main/java/lcsb/mapviewer/web/api/project/drugs/NewDrugController.java b/web/src/main/java/lcsb/mapviewer/web/api/project/drugs/NewDrugController.java index 17806b389542251b117dba7b4fbc567b97724d46..585716d533a2992245a7f0c5ceab0727441e874f 100644 --- a/web/src/main/java/lcsb/mapviewer/web/api/project/drugs/NewDrugController.java +++ b/web/src/main/java/lcsb/mapviewer/web/api/project/drugs/NewDrugController.java @@ -1,6 +1,7 @@ package lcsb.mapviewer.web.api.project.drugs; import lcsb.mapviewer.annotation.data.Drug; +import lcsb.mapviewer.annotation.services.DrugSearchException; import lcsb.mapviewer.annotation.services.TaxonomyBackend; import lcsb.mapviewer.api.BaseController; import lcsb.mapviewer.api.QueryException; @@ -67,7 +68,7 @@ public class NewDrugController extends BaseController { if (project == null) { throw new ObjectNotFoundException("Project with given id doesn't exist"); } - if (!query.equals("")) { + if (!query.isEmpty()) { MiriamData organism = project.getOrganism(); if (organism == null) { @@ -96,7 +97,6 @@ public class NewDrugController extends BaseController { private List<Element> getTargets(final String targetType, final Project project, final Integer dbId) throws QueryException, ObjectNotFoundException { - final List<Element> targets = new ArrayList<>(); if (targetType.equals(ElementIdentifierType.ALIAS.getJsName())) { final Map<ElementProperty, Object> properties = new HashMap<>(); properties.put(ElementProperty.ID, Collections.singletonList(dbId)); @@ -105,11 +105,21 @@ public class NewDrugController extends BaseController { if (elements.getNumberOfElements() == 0) { throw new ObjectNotFoundException("Element does not exist"); } - targets.addAll(elements.getContent()); + return new ArrayList<>(elements.getContent()); } else { throw new QueryException("Targeting for the type not implemented"); } - return targets; + } + + @PreAuthorize("hasAnyAuthority('IS_ADMIN', 'READ_PROJECT:' + #projectId)") + @GetMapping(value = "drugs/suggestedQueryList") + public List<String> getSuggestedQueryList(final @PathVariable(value = "projectId") String projectId) + throws DrugSearchException, ObjectNotFoundException { + final Project project = projectService.getProjectByProjectId(projectId); + if (project == null) { + throw new ObjectNotFoundException("Project with given id doesn't exist"); + } + return drugService.getSuggestedQueryList(project, project.getOrganism()); } } \ No newline at end of file diff --git a/web/src/main/java/lcsb/mapviewer/web/api/project/map/comment/AdminCommentResponseDecorator.java b/web/src/main/java/lcsb/mapviewer/web/api/project/map/comment/AdminCommentResponseDecorator.java new file mode 100644 index 0000000000000000000000000000000000000000..2f4f0831707779ac00f1bcc4c72a188a7e00ddd0 --- /dev/null +++ b/web/src/main/java/lcsb/mapviewer/web/api/project/map/comment/AdminCommentResponseDecorator.java @@ -0,0 +1,32 @@ +package lcsb.mapviewer.web.api.project.map.comment; + +import lcsb.mapviewer.common.Pair; +import lcsb.mapviewer.model.MinervaEntity; +import lcsb.mapviewer.model.map.Comment; +import lcsb.mapviewer.web.api.ResponseDecorator; + +import java.util.ArrayList; +import java.util.List; + +public class AdminCommentResponseDecorator implements ResponseDecorator { + @Override + public List<Pair<String, Object>> getDecoratedValues(final MinervaEntity object) { + List<Pair<String, Object>> properties = new ArrayList<>(); + if (object instanceof Comment) { + Comment comment = (Comment) object; + String author = null; + if (comment.getUser() != null) { + author = comment.getUser().getLogin(); + } + properties.add(new Pair<>("author", author)); + properties.add(new Pair<>("email", comment.getEmail())); + properties.add(new Pair<>("removeReason", comment.getRemoveReason())); + } + return properties; + } + + @Override + public List<Pair<String, Object>> getDecoratedValuesForRaw(final Object object) { + return new ArrayList<>(); + } +} diff --git a/web/src/main/java/lcsb/mapviewer/web/api/project/map/comment/NewCommentController.java b/web/src/main/java/lcsb/mapviewer/web/api/project/map/comment/NewCommentController.java new file mode 100644 index 0000000000000000000000000000000000000000..e657036201a982f373ad988a3bd41485a049dba7 --- /dev/null +++ b/web/src/main/java/lcsb/mapviewer/web/api/project/map/comment/NewCommentController.java @@ -0,0 +1,216 @@ +package lcsb.mapviewer.web.api.project.map.comment; + +import lcsb.mapviewer.api.BaseController; +import lcsb.mapviewer.api.QueryException; +import lcsb.mapviewer.common.Configuration; +import lcsb.mapviewer.model.map.Comment; +import lcsb.mapviewer.model.map.model.ModelData; +import lcsb.mapviewer.model.security.PrivilegeType; +import lcsb.mapviewer.model.user.User; +import lcsb.mapviewer.persist.dao.map.CommentProperty; +import lcsb.mapviewer.services.ObjectNotFoundException; +import lcsb.mapviewer.services.interfaces.ICommentService; +import lcsb.mapviewer.services.interfaces.IModelService; +import lcsb.mapviewer.services.interfaces.IUserService; +import lcsb.mapviewer.web.api.NewApiResponseSerializer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; +import javax.validation.constraints.Pattern; +import java.util.HashMap; +import java.util.Map; + +@RestController +@Validated +@RequestMapping( + value = { + "/minerva/new_api/projects/{projectId}/maps/{mapId}/comments", + }, + produces = MediaType.APPLICATION_JSON_VALUE) +public class NewCommentController extends BaseController { + + private final IUserService userService; + private final IModelService modelService; + private final ICommentService commentService; + private final NewApiResponseSerializer serializer; + + @Autowired + public NewCommentController(final IUserService userService, + final IModelService modelService, + final ICommentService commentService, + final NewApiResponseSerializer serializer) { + this.userService = userService; + this.modelService = modelService; + this.commentService = commentService; + this.serializer = serializer; + } + + @PreAuthorize("hasAnyAuthority('IS_ADMIN', 'READ_PROJECT:' + #projectId)") + @GetMapping + public ResponseEntity<?> getComments( + final Pageable pageable, + final Authentication authentication, + final @PathVariable(value = "projectId") String projectId, + final @Valid @Pattern(regexp = "^[-+]?\\d+$|^\\*$") @PathVariable(value = "mapId") String mapId, + final @RequestParam(value = "removed", required = false) Boolean removed) throws QueryException, ObjectNotFoundException { + + final boolean isAdminView = checkAdminView(authentication, projectId); + + Map<CommentProperty, Object> filterOptions = new HashMap<>(); + filterOptions.put(CommentProperty.PROJECT_ID, projectId); + filterOptions.put(CommentProperty.MAP_ID, mapId); + + if (removed != null) { + filterOptions.put(CommentProperty.DELETED, removed); + } + if (!isAdminView) { + filterOptions.put(CommentProperty.VISIBLE, true); + } + + Page<Comment> page = commentService.getAll(filterOptions, pageable); + + if (isAdminView) { + return serializer.prepareResponse(page, new AdminCommentResponseDecorator()); + } else { + return serializer.prepareResponse(page); + } + } + + private boolean checkAdminView(final Authentication authentication, final String projectId) { + final boolean isAdmin = authentication.getAuthorities() + .contains(new SimpleGrantedAuthority(PrivilegeType.IS_ADMIN.name())); + final boolean isProjectCurator = authentication.getAuthorities() + .contains(new SimpleGrantedAuthority(PrivilegeType.IS_CURATOR.name())) + && authentication.getAuthorities() + .contains(new SimpleGrantedAuthority(PrivilegeType.READ_PROJECT.name() + ":" + projectId)); + + return isAdmin || isProjectCurator; + } + + @PreAuthorize("hasAuthority('IS_ADMIN')" + + " or hasAuthority('IS_CURATOR') and hasAuthority('WRITE_PROJECT:' + #projectId)" + + " or @commentService.getOwnerByCommentId(#projectId, #commentId)?.login == authentication.name") + @DeleteMapping(value = "/{commentId}") + public Object removeComment( + final Authentication authentication, + final @RequestHeader(name = "If-Match", required = false) String oldETag, + final @RequestBody(required = false) NewRemoveCommentDTO body, + final @PathVariable(value = "projectId") String projectId, + final @PathVariable(value = "mapId") String mapId, + final @PathVariable(value = "commentId") Integer commentId) throws QueryException, ObjectNotFoundException { + + final boolean isAdminView = checkAdminView(authentication, projectId); + + Comment comment = getComment(projectId, mapId, commentId, isAdminView); + + if (comment == null) { + throw new ObjectNotFoundException("Comment with given id doesn't exist"); + } + + serializer.checkETag(oldETag, comment); + + if (body != null) { + body.saveToComment(comment); + } + commentService.remove(comment); + if (isAdminView) { + return serializer.prepareResponse(comment, new AdminCommentResponseDecorator()); + } else { + return serializer.prepareResponse(comment); + } + } + + @PreAuthorize("hasAnyAuthority('IS_ADMIN', 'READ_PROJECT:' + #projectId)") + @GetMapping(value = "/{commentId}") + public ResponseEntity<?> getComment( + final Authentication authentication, + final @PathVariable(value = "projectId") String projectId, + final @Valid @Pattern(regexp = "^[-+]?\\d+$|^\\*$") @PathVariable(value = "mapId") String mapId, + final @PathVariable(value = "commentId") Integer commentId) throws ObjectNotFoundException { + + final boolean isAdminView = checkAdminView(authentication, projectId); + + Comment comment = getComment(projectId, mapId, commentId, isAdminView); + + if (isAdminView) { + return serializer.prepareResponse(comment, new AdminCommentResponseDecorator()); + } else { + return serializer.prepareResponse(comment); + } + } + + private Comment getComment( + final String projectId, + final String mapId, + final Integer commentId, + final boolean isAdminView + ) throws ObjectNotFoundException { + Map<CommentProperty, Object> filterOptions = new HashMap<>(); + filterOptions.put(CommentProperty.PROJECT_ID, projectId); + filterOptions.put(CommentProperty.MAP_ID, mapId); + filterOptions.put(CommentProperty.ID, commentId); + + if (!isAdminView) { + filterOptions.put(CommentProperty.VISIBLE, true); + } + + Page<Comment> page = commentService.getAll(filterOptions, Pageable.unpaged()); + + if (page.getNumberOfElements() == 0) { + throw new ObjectNotFoundException("No comment found"); + } + return page.getContent().get(0); + } + + @PreAuthorize("hasAnyAuthority('IS_ADMIN', 'READ_PROJECT:' + #projectId)") + @PostMapping + public ResponseEntity<?> addCommentForElement( + final @PathVariable(value = "projectId") String projectId, + final @PathVariable(value = "mapId") Integer mapId, + final Authentication authentication, + final @Valid @RequestBody NewCommentDTO data + ) throws QueryException, ObjectNotFoundException { + final boolean isAdminView = checkAdminView(authentication, projectId); + + User user = userService.getUserByLogin(authentication.getName()); + if (user.getLogin().equals(Configuration.ANONYMOUS_LOGIN)) { + user = null; + } + final ModelData model = modelService.getModelByMapId(projectId, mapId); + if (model == null) { + throw new ObjectNotFoundException("Map with given id doesn't exist"); + } + + Comment comment = new Comment(); + comment.setUser(user); + comment.setModel(model); + data.saveToComment(comment); + + + commentService.add(comment); + + if (isAdminView) { + return serializer.prepareResponse(comment, new AdminCommentResponseDecorator()); + } else { + return serializer.prepareResponse(comment); + } + } + +} \ No newline at end of file diff --git a/web/src/main/java/lcsb/mapviewer/web/api/project/map/comment/NewCommentDTO.java b/web/src/main/java/lcsb/mapviewer/web/api/project/map/comment/NewCommentDTO.java new file mode 100644 index 0000000000000000000000000000000000000000..f8e0d2483cf4a24e23ba1ee519e2da2ccefdbe14 --- /dev/null +++ b/web/src/main/java/lcsb/mapviewer/web/api/project/map/comment/NewCommentDTO.java @@ -0,0 +1,64 @@ +package lcsb.mapviewer.web.api.project.map.comment; + +import lcsb.mapviewer.model.map.Comment; +import lcsb.mapviewer.web.api.AbstractDTO; +import org.hibernate.validator.constraints.NotBlank; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import java.awt.geom.Point2D; + +public class NewCommentDTO extends AbstractDTO { + + @NotBlank + @Size(max = 255) + private String content; + + @Size(max = 255) + private String email; + + @NotNull + private Point2D coordinates; + + @NotNull + private Boolean visible; + + public void saveToComment(final Comment comment) { + comment.setContent(content); + comment.setEmail(email); + comment.setCoordinates(coordinates); + comment.setPinned(visible); + } + + public Point2D getCoordinates() { + return coordinates; + } + + public void setCoordinates(final Point2D coordinates) { + this.coordinates = coordinates; + } + + public Boolean getVisible() { + return visible; + } + + public void setVisible(final Boolean visible) { + this.visible = visible; + } + + public String getContent() { + return content; + } + + public void setContent(final String content) { + this.content = content; + } + + public String getEmail() { + return email; + } + + public void setEmail(final String email) { + this.email = email; + } +} diff --git a/web/src/main/java/lcsb/mapviewer/web/api/project/map/comment/NewRemoveCommentDTO.java b/web/src/main/java/lcsb/mapviewer/web/api/project/map/comment/NewRemoveCommentDTO.java new file mode 100644 index 0000000000000000000000000000000000000000..43f3b056ba4e8fba9b09121a4713c37f78199abc --- /dev/null +++ b/web/src/main/java/lcsb/mapviewer/web/api/project/map/comment/NewRemoveCommentDTO.java @@ -0,0 +1,25 @@ +package lcsb.mapviewer.web.api.project.map.comment; + +import lcsb.mapviewer.api.QueryException; +import lcsb.mapviewer.model.map.Comment; +import lcsb.mapviewer.web.api.AbstractDTO; + +import javax.validation.constraints.Size; + +public class NewRemoveCommentDTO extends AbstractDTO { + + @Size(max = 255) + private String reason; + + public void saveToComment(final Comment comment) throws QueryException { + comment.setRemoveReason(reason); + } + + public String getReason() { + return reason; + } + + public void setReason(final String reason) { + this.reason = reason; + } +} diff --git a/web/src/main/java/lcsb/mapviewer/web/app/WebConfig.java b/web/src/main/java/lcsb/mapviewer/web/app/WebConfig.java index 3857526069c3553f0ab859313927609da874f7db..6ae09584e28bb61b5d3b4f4909c4f744ee45c052 100644 --- a/web/src/main/java/lcsb/mapviewer/web/app/WebConfig.java +++ b/web/src/main/java/lcsb/mapviewer/web/app/WebConfig.java @@ -7,6 +7,7 @@ import lcsb.mapviewer.api.CustomPageDeserialize; import lcsb.mapviewer.api.CustomPageSerializer; import lcsb.mapviewer.common.MinervaConfigurationHolder; import lcsb.mapviewer.model.map.BioEntity; +import lcsb.mapviewer.model.map.Comment; import lcsb.mapviewer.model.map.OverviewImage; import lcsb.mapviewer.model.map.OverviewImageLink; import lcsb.mapviewer.model.map.OverviewModelLink; @@ -19,6 +20,7 @@ import lcsb.mapviewer.modelutils.serializer.ColorSerializer; import lcsb.mapviewer.modelutils.serializer.Line2DDeserializer; import lcsb.mapviewer.modelutils.serializer.Line2DSerializer; import lcsb.mapviewer.modelutils.serializer.Point2DDeserializer; +import lcsb.mapviewer.modelutils.serializer.model.map.CommentSerializer; import lcsb.mapviewer.modelutils.serializer.model.map.MinifiedBioEntitySerializer; import lcsb.mapviewer.modelutils.serializer.model.map.OverviewImageLinkSerializer; import lcsb.mapviewer.modelutils.serializer.model.map.OverviewImageSerializer; @@ -121,6 +123,7 @@ public class WebConfig implements WebMvcConfigurer { module.addSerializer(ReactionNode.class, new ReactionNodeSerializer()); module.addSerializer(BioEntity.class, new MinifiedBioEntitySerializer()); module.addSerializer(CustomPage.class, new CustomPageSerializer()); + module.addSerializer(Comment.class, new CommentSerializer()); module.addDeserializer(Point2D.class, new Point2DDeserializer()); diff --git a/web/src/test/java/lcsb/mapviewer/web/CommentControllerIntegrationTest.java b/web/src/test/java/lcsb/mapviewer/web/CommentControllerIntegrationTest.java index cacb08235c181a06ae07ea5f0a8fae905fe8361b..de5a422215f3258dc04ec5b691264f47d55d82a5 100644 --- a/web/src/test/java/lcsb/mapviewer/web/CommentControllerIntegrationTest.java +++ b/web/src/test/java/lcsb/mapviewer/web/CommentControllerIntegrationTest.java @@ -34,9 +34,9 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.web.servlet.RequestBuilder; import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Map; @@ -373,7 +373,7 @@ public class CommentControllerIntegrationTest extends ControllerIntegrationTest .andExpect(status().is2xxSuccessful()); comment = commentService.getCommentById(TEST_PROJECT, comment.getId() + ""); - assertEquals(true, comment.isDeleted()); + assertTrue(comment.isDeleted()); } @Test @@ -390,7 +390,7 @@ public class CommentControllerIntegrationTest extends ControllerIntegrationTest comment = commentService.getCommentById(TEST_PROJECT, comment.getId() + ""); - assertEquals(true, comment.isDeleted()); + assertTrue(comment.isDeleted()); } @Test @@ -422,7 +422,7 @@ public class CommentControllerIntegrationTest extends ControllerIntegrationTest .andExpect(status().is2xxSuccessful()); comment = commentService.getCommentById(TEST_PROJECT, comment.getId() + ""); - assertEquals(true, comment.isDeleted()); + assertTrue(comment.isDeleted()); } @Test @@ -765,7 +765,7 @@ public class CommentControllerIntegrationTest extends ControllerIntegrationTest public void testAddElementCommentWithoutAllNecessaryData() throws Exception { MockHttpSession session = createSession(TEST_USER_LOGIN, TEST_USER_PASSWORD); - String body = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList( + String body = EntityUtils.toString(new UrlEncodedFormEntity(Collections.singletonList( new BasicNameValuePair("modelId", map.getId() + "")))); RequestBuilder request = post("/minerva/api/projects/{projectId}/comments/models/{mapId}/bioEntities/elements/{elementId}", @@ -988,19 +988,21 @@ public class CommentControllerIntegrationTest extends ControllerIntegrationTest .andExpect(status().is2xxSuccessful()); comment = commentService.getCommentById(TEST_PROJECT, comment.getId() + ""); - assertEquals(true, comment.isDeleted()); + assertTrue(comment.isDeleted()); } private Comment createReactionComment() throws Exception { Comment comment = createComment(map); comment.setReaction(reaction); - return commentService.add(comment); + commentService.add(comment); + return comment; } private Comment createElementComment() throws Exception { Comment comment = createComment(map); comment.setElement(element); - return commentService.add(comment); + commentService.add(comment); + return comment; } @Test @@ -1023,7 +1025,7 @@ public class CommentControllerIntegrationTest extends ControllerIntegrationTest } } - private String createContentBody(final String type, final String value) throws IOException, UnsupportedEncodingException { + private String createContentBody(final String type, final String value) throws IOException { List<BasicNameValuePair> params = new ArrayList<>(Arrays.asList( new BasicNameValuePair("email", "a@a.lu"), new BasicNameValuePair("content", "test content"), diff --git a/web/src/test/java/lcsb/mapviewer/web/ControllerIntegrationTest.java b/web/src/test/java/lcsb/mapviewer/web/ControllerIntegrationTest.java index d1426a44bbf8c8aa1fc2e74088042186ffb7d960..71452b8d64587ddd7b73faa3e7472dc084b0cfa9 100644 --- a/web/src/test/java/lcsb/mapviewer/web/ControllerIntegrationTest.java +++ b/web/src/test/java/lcsb/mapviewer/web/ControllerIntegrationTest.java @@ -886,7 +886,8 @@ public abstract class ControllerIntegrationTest extends TestUtils { protected Comment createAndPersistComment(final ModelData model, final User owner) { final Comment comment = createComment(model, owner); - return commentService.add(comment); + commentService.add(comment); + return comment; } protected ModelData getBuildInModel() { @@ -899,6 +900,7 @@ public abstract class ControllerIntegrationTest extends TestUtils { protected Comment createComment(final ModelData map, final User owner) { final Comment comment = new Comment(); + comment.setContent("it's cool"); comment.setModel(map); comment.setUser(owner); comment.setCoordinates(new Point2D.Double(10, 20)); @@ -917,6 +919,10 @@ public abstract class ControllerIntegrationTest extends TestUtils { return getMapPathParameters().and(parameterWithName("layerId").description("layer identifier")); } + protected PathParametersSnippet getCommentPathParameters() { + return getMapPathParameters().and(parameterWithName("commentId").description("comment identifier")); + } + protected PathParametersSnippet getLayerImagePathParameters() { return getLayerPathParameters().and(parameterWithName("imageId").description("image identifier")); } diff --git a/web/src/test/java/lcsb/mapviewer/web/api/NewApiDocs.java b/web/src/test/java/lcsb/mapviewer/web/api/NewApiDocs.java index c452810cdfd85158476ad9752f806aba1a1e2259..ccc2e40eb6d97bee5d7c5980125b9ab7ad6ec1ed 100644 --- a/web/src/test/java/lcsb/mapviewer/web/api/NewApiDocs.java +++ b/web/src/test/java/lcsb/mapviewer/web/api/NewApiDocs.java @@ -58,6 +58,10 @@ public class NewApiDocs { return new NewApiDocs().getLayerFields(prefix); } + public static List<FieldDescriptor> getCommentResponse(final String prefix) { + return new NewApiDocs().getCommentFields(prefix); + } + public static List<FieldDescriptor> getGlyphResponse(final String prefix) { return new NewApiDocs().getGlyphFields(prefix); } @@ -145,6 +149,26 @@ public class NewApiDocs { ); } + public static RequestFieldsSnippet getAddCommentRequest() { + return requestFields( + fieldWithPath("content") + .description("content") + .type(JsonFieldType.STRING), + fieldWithPath("coordinates.x") + .description("x coordinate on the map") + .type(JsonFieldType.NUMBER), + fieldWithPath("coordinates.y") + .description("y coordinate on the map") + .type(JsonFieldType.NUMBER), + fieldWithPath("visible") + .description("is content visible") + .type(JsonFieldType.BOOLEAN), + fieldWithPath("email") + .description("reported email address") + .type(JsonFieldType.STRING) + ); + } + public static RequestFieldsSnippet getAddLayerImageRequest() { return requestFields( fieldWithPath("x") @@ -1061,6 +1085,44 @@ public class NewApiDocs { return result; } + private List<FieldDescriptor> getCommentFields(final String prefix) { + return Arrays.asList( + fieldWithPath(prefix + "id") + .description("unique comment identifier") + .type(JsonFieldType.NUMBER), + fieldWithPath(prefix + "map") + .description("map identifier") + .type(JsonFieldType.NUMBER), + fieldWithPath(prefix + "content") + .description("comment content") + .type(JsonFieldType.STRING), + fieldWithPath(prefix + "author") + .description("login of the author") + .optional() + .type(JsonFieldType.STRING), + fieldWithPath(prefix + "email") + .description("email of the author") + .optional() + .type(JsonFieldType.STRING), + fieldWithPath(prefix + "removeReason") + .description("why the comment has been removed ") + .optional() + .type(JsonFieldType.STRING), + fieldWithPath(prefix + "coordinates.x") + .description("x coordinate where the comment is located on map") + .type(JsonFieldType.NUMBER), + fieldWithPath(prefix + "coordinates.y") + .description("y coordinate where the comment is located on map") + .type(JsonFieldType.NUMBER), + fieldWithPath(prefix + "deleted") + .description("is comment deleted") + .type(JsonFieldType.BOOLEAN), + fieldWithPath(prefix + "visible") + .description("is comment visible") + .type(JsonFieldType.BOOLEAN) + ); + } + private List<FieldDescriptor> getGlyphFields(final String prefix) { final List<FieldDescriptor> result = new ArrayList<>(); result.add( @@ -1205,6 +1267,17 @@ public class NewApiDocs { return responseFields(fields); } + public static Snippet getCommentsSearchResult() { + final String prefix = "content[]."; + final List<FieldDescriptor> fields = new ArrayList<>(); + fields.add(fieldWithPath("content") + .description("list of comments on the page") + .type(JsonFieldType.ARRAY)); + fields.addAll(getCommentResponse(prefix)); + fields.addAll(getPageableFields()); + return responseFields(fields); + } + public static Snippet getGlyphsSearchResult() { final String prefix = "content[]."; final List<FieldDescriptor> fields = new ArrayList<>(); diff --git a/web/src/test/java/lcsb/mapviewer/web/api/project/chemicals/NewChemicalControllerTest.java b/web/src/test/java/lcsb/mapviewer/web/api/project/chemicals/NewChemicalControllerTest.java index e0b60402256719b573a9adc4a798dc18c01d3cad..766934cedf667c70a38941514421c1c8d257bbc8 100644 --- a/web/src/test/java/lcsb/mapviewer/web/api/project/chemicals/NewChemicalControllerTest.java +++ b/web/src/test/java/lcsb/mapviewer/web/api/project/chemicals/NewChemicalControllerTest.java @@ -1,32 +1,38 @@ package lcsb.mapviewer.web.api.project.chemicals; -import static org.junit.Assume.assumeTrue; -import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - +import lcsb.mapviewer.model.Project; +import lcsb.mapviewer.model.map.MiriamData; +import lcsb.mapviewer.model.map.MiriamType; +import lcsb.mapviewer.services.interfaces.IProjectService; +import lcsb.mapviewer.web.ControllerIntegrationTest; +import lcsb.mapviewer.web.api.NewApiDocs; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.mock.web.MockHttpSession; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.web.servlet.RequestBuilder; -import lcsb.mapviewer.model.Project; -import lcsb.mapviewer.web.ControllerIntegrationTest; -import lcsb.mapviewer.web.api.NewApiDocs; +import static org.junit.Assume.assumeTrue; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @RunWith(SpringJUnit4ClassRunner.class) @ActiveProfiles("webCtdTestProfile") public class NewChemicalControllerTest extends ControllerIntegrationTest { - private static String TEST_PROJECT = "TEST_PROJECT"; + private static final String TEST_PROJECT = "TEST_PROJECT"; private Project project; + @Autowired + private IProjectService projectService; + @Before public void setup() { assumeTrue("DAPI credentials are not provided", isDapiConfigurationAvailable()); @@ -38,6 +44,7 @@ public class NewChemicalControllerTest extends ControllerIntegrationTest { if (project != null) { removeProject(project); } + removeProject(TEST_PROJECT_2); } @Test @@ -55,4 +62,27 @@ public class NewChemicalControllerTest extends ControllerIntegrationTest { .andExpect(status().is2xxSuccessful()) .andReturn().getResponse().getContentAsString(); } + + @Test + public void testSuggestedQueryList() throws Exception { + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); + final MiriamData bloodLossDisease = new MiriamData(MiriamType.MESH_2012, "D016063"); + + final Project project = createEmptyProject(TEST_PROJECT_2); + project.setDisease(bloodLossDisease); + projectService.update(project); + + final RequestBuilder request = get("/minerva/new_api/projects/{projectId}/chemicals/suggestedQueryList", TEST_PROJECT_2) + .session(session); + + + mockMvc.perform(request) + .andExpect(status().is2xxSuccessful()) + .andDo(document("new_api/projects/project_chemicals/suggestedQueryList", + getProjectPathParameters(), + responseFields(NewApiDocs.getSuggestedQueryListFields()))) + .andReturn().getResponse().getContentAsString(); + } + + } diff --git a/web/src/test/java/lcsb/mapviewer/web/api/project/drugs/NewDrugControllerTest.java b/web/src/test/java/lcsb/mapviewer/web/api/project/drugs/NewDrugControllerTest.java index aeff4a34fcd0eb34b5c97f9e485210d4ecb6e2ac..3ea076e86b8adfa5eeabd0492207a3b04193ab8c 100644 --- a/web/src/test/java/lcsb/mapviewer/web/api/project/drugs/NewDrugControllerTest.java +++ b/web/src/test/java/lcsb/mapviewer/web/api/project/drugs/NewDrugControllerTest.java @@ -1,10 +1,7 @@ package lcsb.mapviewer.web.api.project.drugs; -import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - +import lcsb.mapviewer.web.ControllerIntegrationTest; +import lcsb.mapviewer.web.api.NewApiDocs; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -13,8 +10,10 @@ import org.springframework.mock.web.MockHttpSession; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.web.servlet.RequestBuilder; -import lcsb.mapviewer.web.ControllerIntegrationTest; -import lcsb.mapviewer.web.api.NewApiDocs; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @RunWith(SpringJUnit4ClassRunner.class) public class NewDrugControllerTest extends ControllerIntegrationTest { @@ -44,4 +43,19 @@ public class NewDrugControllerTest extends ControllerIntegrationTest { responseFields(NewApiDocs.getDrugListResponse("")))); } + @Test + public void testSuggestedQueryList() throws Exception { + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); + final RequestBuilder request = get( + "/minerva/new_api/projects/{projectId}/drugs/suggestedQueryList", TEST_PROJECT) + .session(session); + + mockMvc.perform(request) + .andExpect(status().is2xxSuccessful()) + .andDo(document("new_api/projects/project_drugs/suggestedQueryList", + getProjectPathParameters(), + responseFields(NewApiDocs.getSuggestedQueryListFields()))) + .andReturn().getResponse().getContentAsString(); + } + } diff --git a/web/src/test/java/lcsb/mapviewer/web/api/project/map/comment/NewCommentControllerTest.java b/web/src/test/java/lcsb/mapviewer/web/api/project/map/comment/NewCommentControllerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..df51082e3b9224d623690e935c6f553f7ffdb36a --- /dev/null +++ b/web/src/test/java/lcsb/mapviewer/web/api/project/map/comment/NewCommentControllerTest.java @@ -0,0 +1,309 @@ +package lcsb.mapviewer.web.api.project.map.comment; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import lcsb.mapviewer.model.map.Comment; +import lcsb.mapviewer.model.map.model.ModelData; +import lcsb.mapviewer.model.user.User; +import lcsb.mapviewer.persist.dao.map.CommentProperty; +import lcsb.mapviewer.services.interfaces.ICommentService; +import lcsb.mapviewer.services.interfaces.IMinervaJobService; +import lcsb.mapviewer.services.interfaces.IModelService; +import lcsb.mapviewer.web.ControllerIntegrationTest; +import lcsb.mapviewer.web.api.NewApiDocs; +import lcsb.mapviewer.web.api.NewApiResponseSerializer; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.http.MediaType; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.mock.web.MockHttpSession; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.RequestBuilder; + +import javax.servlet.http.HttpServletResponse; +import java.awt.geom.Point2D; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringJUnit4ClassRunner.class) +public class NewCommentControllerTest extends ControllerIntegrationTest { + + @Autowired + private ICommentService commentService; + + @Autowired + private IModelService modelService; + + @Autowired + private IMinervaJobService minervaJobService; + + @Autowired + private NewApiResponseSerializer newApiResponseSerializer; + + private ObjectMapper objectMapper; + + private ModelData modelData; + private User user; + + @Before + public void setUp() throws Exception { + objectMapper = newApiResponseSerializer.getObjectMapper(); + + modelData = modelService.getById(BUILT_IN_MAP_ID); + + user = createUser(TEST_USER_LOGIN, TEST_USER_PASSWORD); + } + + @After + public void tearDown() throws Exception { + removeUser(user); + minervaJobService.waitForTasksToFinish(); + } + + @Test + public void testGetComment() throws Exception { + final MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); + + Comment comment = createComment(modelData); + commentService.add(comment); + + final RequestBuilder request = get("/minerva/new_api/projects/{projectId}/maps/{mapId}/comments/{commentId}", + BUILT_IN_PROJECT, + BUILT_IN_MAP_ID, + comment.getId()) + .session(session); + + final HttpServletResponse response = mockMvc.perform(request) + .andExpect(status().isOk()) + .andDo(document("new_api/projects/maps/comments/get_comment", + getCommentPathParameters(), + responseFields(NewApiDocs.getCommentResponse("")))) + .andReturn().getResponse(); + + assertNotNull(response.getHeader("ETag")); + } + + @Test + public void testGetNonExisting() throws Exception { + final MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); + + final RequestBuilder request = get("/minerva/new_api/projects/{projectId}/maps/{mapId}/comments/{commentId}", + BUILT_IN_PROJECT, + BUILT_IN_MAP_ID, + -1) + .session(session); + + mockMvc.perform(request) + .andExpect(status().isNotFound()); + } + + @Test + public void testGetCommentWithoutPermission() throws Exception { + final MockHttpSession session = createSession(TEST_USER_LOGIN, TEST_USER_PASSWORD); + + Comment comment = createComment(modelData); + commentService.add(comment); + + final RequestBuilder request = get("/minerva/new_api/projects/{projectId}/maps/{mapId}/comments/{commentId}", + BUILT_IN_PROJECT, + BUILT_IN_MAP_ID, + comment.getId()) + .session(session); + + mockMvc.perform(request) + .andExpect(status().isForbidden()); + } + + @Test + public void testCreateComment() throws Exception { + final MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); + + final NewCommentDTO data = createCommentDTO(); + + final RequestBuilder request = post("/minerva/new_api/projects/{projectId}/maps/{mapId}/comments/", + BUILT_IN_PROJECT, + BUILT_IN_MAP_ID) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(data)) + .session(session); + + final MockHttpServletResponse response = mockMvc.perform(request) + .andExpect(status().isOk()) + .andDo(document("new_api/projects/maps/comments/add_comment", + getMapPathParameters(), + NewApiDocs.getAddCommentRequest(), + responseFields(NewApiDocs.getCommentResponse("")))) + .andReturn().getResponse(); + assertNotNull(response.getHeader("ETag")); + final Map<String, Object> result = objectMapper.readValue(response.getContentAsString(), new TypeReference<Map<String, Object>>() { + }); + + final Map<CommentProperty, Object> filter = new HashMap<>(); + filter.put(CommentProperty.PROJECT_ID, BUILT_IN_PROJECT); + filter.put(CommentProperty.MAP_ID, BUILT_IN_MAP_ID); + filter.put(CommentProperty.ID, result.get("id")); + final Page<Comment> comments = commentService.getAll(filter, Pageable.unpaged()); + + assertEquals(1, comments.getNumberOfElements()); + } + + private NewCommentDTO createCommentDTO() { + final NewCommentDTO data = new NewCommentDTO(); + data.setContent("blah blah blah"); + data.setCoordinates(new Point2D.Double(10, 12)); + data.setEmail("test@test.com"); + data.setVisible(true); + return data; + } + + private NewRemoveCommentDTO createRemoveCommentDTO() { + final NewRemoveCommentDTO data = new NewRemoveCommentDTO(); + data.setReason("xyz"); + return data; + } + + + @Test + public void testDeleteComment() throws Exception { + final MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); + + Comment comment = createComment(modelData); + commentService.add(comment); + + NewRemoveCommentDTO removeCommentDTO = createRemoveCommentDTO(); + + final RequestBuilder request = delete("/minerva/new_api/projects/{projectId}/maps/{mapId}/comments/{commentId}", + BUILT_IN_PROJECT, + BUILT_IN_MAP_ID, + comment.getId()) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(removeCommentDTO)) + .session(session); + + mockMvc.perform(request) + .andExpect(status().isOk()) + .andDo(document("new_api/projects/maps/comments/delete_comment", + getCommentPathParameters())); + + comment = commentService.getById(comment.getId()); + assertTrue(comment.isDeleted()); + } + + @Test + public void testDeleteNotExistingComment() throws Exception { + final MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); + + final RequestBuilder request = delete("/minerva/new_api/projects/{projectId}/maps/{mapId}/comments/{commentId}", + BUILT_IN_PROJECT, + BUILT_IN_MAP_ID, + -1) + .session(session); + + mockMvc.perform(request) + .andExpect(status().isNotFound()); + } + + @Test + public void testDeleteNoAccessComment() throws Exception { + Comment comment = createComment(modelData); + commentService.add(comment); + + final RequestBuilder request = delete("/minerva/new_api/projects/{projectId}/maps/{mapId}/comments/{commentId}", + BUILT_IN_PROJECT, + BUILT_IN_MAP_ID, + comment.getId()); + + mockMvc.perform(request) + .andExpect(status().isForbidden()); + } + + @Test + public void testDeleteCommentWithGoodVersion() throws Exception { + final MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); + + Comment comment = createComment(modelData); + commentService.add(comment); + + final String originalVersion = comment.getEntityVersion() + ""; + + final RequestBuilder request = delete("/minerva/new_api/projects/{projectId}/maps/{mapId}/comments/{commentId}", + BUILT_IN_PROJECT, + BUILT_IN_MAP_ID, + comment.getId()) + .header("If-Match", originalVersion) + .session(session); + + mockMvc.perform(request) + .andExpect(status().isOk()); + comment = commentService.getById(comment.getId()); + assertTrue(comment.isDeleted()); + } + + @Test + public void testDeleteCommentWithWrongVersion() throws Exception { + final MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); + + Comment comment = createComment(modelData); + commentService.add(comment); + + final RequestBuilder request = delete("/minerva/new_api/projects/{projectId}/maps/{mapId}/comments/{commentId}", + BUILT_IN_PROJECT, + BUILT_IN_MAP_ID, + comment.getId()) + .header("If-Match", "-1") + .session(session); + + mockMvc.perform(request) + .andExpect(status().isPreconditionFailed()); + comment = commentService.getById(comment.getId()); + assertFalse(comment.isDeleted()); + } + + @Test + public void testListComments() throws Exception { + final MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); + + Comment comment = createComment(modelData); + commentService.add(comment); + + final RequestBuilder request = get("/minerva/new_api/projects/{projectId}/maps/{mapId}/comments/", + BUILT_IN_PROJECT, + BUILT_IN_MAP_ID) + .session(session); + + mockMvc.perform(request) + .andDo(document("new_api/projects/maps/comments/list_comments", + getMapPathParameters(), + NewApiDocs.getCommentsSearchResult())) + .andExpect(status().isOk()); + } + + @Test + public void testListCommentsWithoutAccess() throws Exception { + final MockHttpSession session = createSession(TEST_USER_LOGIN, TEST_USER_PASSWORD); + final RequestBuilder request = get("/minerva/new_api/projects/{projectId}/maps/{mapId}/comments/", + BUILT_IN_PROJECT, + BUILT_IN_MAP_ID) + .session(session); + + mockMvc.perform(request) + .andExpect(status().isForbidden()); + } + +}