From 83eec8d3c36bb59f2d8c15167eab69c871343279 Mon Sep 17 00:00:00 2001 From: Thomas <gltron3000@gmail.com> Date: Tue, 26 May 2020 14:15:04 +0200 Subject: [PATCH] Added vote, fixed search --- .../java/mozen/business/IModelManager.java | 3 +- .../java/mozen/business/IVoteManager.java | 13 +++ .../java/mozen/business/ModelManager.java | 52 +++++----- .../main/java/mozen/business/VoteManager.java | 96 +++++++++++++++++++ .../java/mozen/messages/ModelMessage.java | 18 +++- .../mozen/messages/VoteStatusMessage.java | 25 +++++ mozen/src/main/java/mozen/model/Model.java | 16 +++- mozen/src/main/java/mozen/model/User.java | 38 +++++++- .../main/java/mozen/utils/DatabaseFiller.java | 1 + .../main/java/mozen/web/SearchController.java | 4 +- .../main/java/mozen/web/VoteController.java | 90 +++++++++++++++-- 11 files changed, 318 insertions(+), 38 deletions(-) create mode 100644 mozen/src/main/java/mozen/business/IVoteManager.java create mode 100644 mozen/src/main/java/mozen/business/VoteManager.java create mode 100644 mozen/src/main/java/mozen/messages/VoteStatusMessage.java diff --git a/mozen/src/main/java/mozen/business/IModelManager.java b/mozen/src/main/java/mozen/business/IModelManager.java index d383f7e..61de3c2 100644 --- a/mozen/src/main/java/mozen/business/IModelManager.java +++ b/mozen/src/main/java/mozen/business/IModelManager.java @@ -20,6 +20,5 @@ public interface IModelManager { Model getModel(long id); Collection<Model> getModels(); - SearchResult findModel(String name, int page, int size, String sort); - SearchResult findModelWithTags(String name, int page, int size, String sort, Collection<String> tags); + SearchResult findModel(String name, int page, int size, String sort, Collection<String> tagsName); } \ No newline at end of file diff --git a/mozen/src/main/java/mozen/business/IVoteManager.java b/mozen/src/main/java/mozen/business/IVoteManager.java new file mode 100644 index 0000000..6c4d92f --- /dev/null +++ b/mozen/src/main/java/mozen/business/IVoteManager.java @@ -0,0 +1,13 @@ +package mozen.business; + +import mozen.model.User; + +public interface IVoteManager { + void addUpvote(Long id, User user) throws Exception; + void addDownvote(Long id, User user) throws Exception; + + void removeUpvote(Long id, User user) throws Exception; + void removeDownvote(Long id, User user) throws Exception; + + String getStatus(Long id, User user) throws Exception; +} \ No newline at end of file diff --git a/mozen/src/main/java/mozen/business/ModelManager.java b/mozen/src/main/java/mozen/business/ModelManager.java index fd1daa8..349ad18 100644 --- a/mozen/src/main/java/mozen/business/ModelManager.java +++ b/mozen/src/main/java/mozen/business/ModelManager.java @@ -43,10 +43,18 @@ public class ModelManager implements IModelManager { model.setName(message.getName()); model.setShortDescription(message.getShortDescription()); model.setLongDescription(message.getLongDescription()); - model.setPerformanceUnit(message.getPerformanceUnit()); model.setPerformance(message.getPerformance()); + model.setPerformanceUnit(message.getPerformanceUnit()); model.setParameterCount(message.getParameterCount()); + // Standardise la mesure de performance. + // C'est bancale mais difficile de trier autrement en mélangeant les unitées de performances + if (message.getPerformanceLowerIsBetter()) { + model.setPerformanceIndex(message.getPerformance()); + } else { + model.setPerformanceIndex(100 - message.getPerformance()); + } + if (message.getTags() != null) { Set<Tag> tags = new HashSet<Tag>(); for (String tagName : message.getTags()) { @@ -140,30 +148,26 @@ public class ModelManager implements IModelManager { } @Override - public SearchResult findModel(String name, int page, int size, String sort) { - Pageable paging = PageRequest.of(page - 1, size, Sort.by(sort)); - Page<Model> resultPage = modelRepo.findByNameContainingIgnoreCase(name, paging); - - SearchResult result = new SearchResult(); - if (resultPage.hasContent()) { - result.setTotalResult((int) resultPage.getTotalElements()); - result.setTotalPage((int) resultPage.getTotalPages()); - result.setPage(resultPage.getNumber() + 1); - result.setModels(resultPage.getContent()); + public SearchResult findModel(String name, int page, int size, String sort, Collection<String> tagsName) { + Pageable paging; + + // Tri dans le bon sens selon l'attribut + switch (sort) { + case "votes": paging = PageRequest.of(page - 1, size, Sort.by(sort).descending()); break; + case "lastModified": paging = PageRequest.of(page - 1, size, Sort.by(sort).descending()); break; + case "performance": paging = PageRequest.of(page - 1, size, Sort.by("performanceIndex")); break; + case "parameterCount": paging = PageRequest.of(page - 1, size, Sort.by(sort)); break; + default: paging = PageRequest.of(page - 1, size, Sort.by("name")); + } + + Page<Model> resultPage; + if (tagsName == null) { + resultPage = modelRepo.findByNameContainingIgnoreCase(name, paging); } else { - result.setPage(0); - result.setTotalResult(0); - result.setTotalPage(0); + Collection<Tag> tags = tagRepo.findByNameIn(tagsName); + resultPage = modelRepo.findDistinctByNameContainingIgnoreCaseAndTagsIn(name, tags, paging); } - return result; - } - - @Override - public SearchResult findModelWithTags(String name, int page, int size, String sort, Collection<String> tagsName) { - Pageable paging = PageRequest.of(page - 1, size, Sort.by(sort)); - Collection<Tag> tags = tagRepo.findByNameIn(tagsName); - Page<Model> resultPage = modelRepo.findDistinctByNameContainingIgnoreCaseAndTagsIn(name, tags, paging); - + SearchResult result = new SearchResult(); if (resultPage.hasContent()) { result.setTotalResult((int) resultPage.getTotalElements()); @@ -177,7 +181,7 @@ public class ModelManager implements IModelManager { } return result; } - + @Override public Model getModel(long id) { Optional<Model> model = modelRepo.findById(id); diff --git a/mozen/src/main/java/mozen/business/VoteManager.java b/mozen/src/main/java/mozen/business/VoteManager.java new file mode 100644 index 0000000..019ce72 --- /dev/null +++ b/mozen/src/main/java/mozen/business/VoteManager.java @@ -0,0 +1,96 @@ +package mozen.business; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import mozen.model.Model; +import mozen.model.User; +import mozen.repos.ModelRepository; +import mozen.repos.UserRepository; + +@Service +public class VoteManager implements IVoteManager { + + @Autowired + private UserRepository userRepo; + + @Autowired + private ModelRepository modelRepo; + + @Override + public void addUpvote(Long id, User user) throws Exception { + Model model = modelRepo.findById(id).get(); + + if (model == null) + throw new Exception("Unknown model"); + if (user.getUpvotes().contains(model)) + throw new Exception("Up present"); + + model.setVotes(model.getVotes()+1); + user.getUpvotes().add(model); + + modelRepo.save(model); + userRepo.save(user); + } + + @Override + public void addDownvote(Long id, User user) throws Exception { + Model model = modelRepo.findById(id).get(); + + if (model == null) + throw new Exception("Unknown model"); + if (user.getDownvotes().contains(model)) + throw new Exception("Downvote present"); + + model.setVotes(model.getVotes()-1); + user.getDownvotes().add(model); + + modelRepo.save(model); + userRepo.save(user); + } + + @Override + public void removeUpvote(Long id, User user) throws Exception { + Model model = modelRepo.findById(id).get(); + + if (model == null) + throw new Exception("Unknown model"); + if (!user.getUpvotes().contains(model)) + throw new Exception("No upvote"); + + model.setVotes(model.getVotes()-1); + user.getUpvotes().remove(model); + + modelRepo.save(model); + userRepo.save(user); + } + + @Override + public void removeDownvote(Long id, User user) throws Exception { + Model model = modelRepo.findById(id).get(); + + if (model == null) + throw new Exception("Unknown model"); + if (!user.getDownvotes().contains(model)) + throw new Exception("No downvote"); + + model.setVotes(model.getVotes()+1); + user.getDownvotes().remove(model); + + modelRepo.save(model); + userRepo.save(user); + } + + @Override + public String getStatus(Long id, User user) throws Exception { + Model model = modelRepo.findById(id).get(); + + if (model == null) + throw new Exception("Unknown model"); + + if (user.getUpvotes().contains(model)) return "up"; + if (user.getDownvotes().contains(model)) return "down"; + return "none"; + } + +} \ No newline at end of file diff --git a/mozen/src/main/java/mozen/messages/ModelMessage.java b/mozen/src/main/java/mozen/messages/ModelMessage.java index b8895ec..afd579f 100644 --- a/mozen/src/main/java/mozen/messages/ModelMessage.java +++ b/mozen/src/main/java/mozen/messages/ModelMessage.java @@ -26,12 +26,14 @@ public class ModelMessage implements Serializable { private String performanceUnit; + private boolean performanceLowerIsBetter; + private int parameterCount; public ModelMessage() { } - public ModelMessage(String name, String shortDescription, String longDescription, String[] tags, String[] customLayers, double performance, String performanceUnit, int parameterCount) { + public ModelMessage(String name, String shortDescription, String longDescription, String[] tags, String[] customLayers, double performance, String performanceUnit, boolean performanceLowerIsBetter, int parameterCount) { this.name = name; this.shortDescription = shortDescription; this.longDescription = longDescription; @@ -39,10 +41,10 @@ public class ModelMessage implements Serializable { this.customLayers = customLayers; this.performance = performance; this.performanceUnit = performanceUnit; + this.performanceLowerIsBetter = performanceLowerIsBetter; this.parameterCount = parameterCount; } - public String getName() { return this.name; } @@ -99,6 +101,18 @@ public class ModelMessage implements Serializable { this.performanceUnit = performanceUnit; } + public boolean isPerformanceLowerIsBetter() { + return this.performanceLowerIsBetter; + } + + public boolean getPerformanceLowerIsBetter() { + return this.performanceLowerIsBetter; + } + + public void setPerformanceLowerIsBetter(boolean performanceLowerIsBetter) { + this.performanceLowerIsBetter = performanceLowerIsBetter; + } + public int getParameterCount() { return this.parameterCount; } diff --git a/mozen/src/main/java/mozen/messages/VoteStatusMessage.java b/mozen/src/main/java/mozen/messages/VoteStatusMessage.java new file mode 100644 index 0000000..fb2963d --- /dev/null +++ b/mozen/src/main/java/mozen/messages/VoteStatusMessage.java @@ -0,0 +1,25 @@ +package mozen.messages; + +import java.io.Serializable; + +public class VoteStatusMessage implements Serializable{ + private static final long serialVersionUID = 1L; + + private String status; + + public VoteStatusMessage() { + } + + public VoteStatusMessage(String status) { + this.status = status; + } + + public String getStatus() { + return this.status; + } + + public void setStatus(String status) { + this.status = status; + } +} + \ No newline at end of file diff --git a/mozen/src/main/java/mozen/model/Model.java b/mozen/src/main/java/mozen/model/Model.java index a8eb93e..8ba18c8 100644 --- a/mozen/src/main/java/mozen/model/Model.java +++ b/mozen/src/main/java/mozen/model/Model.java @@ -72,6 +72,10 @@ public class Model implements Serializable{ @Column private String performanceUnit; + @Basic + @Column + private double performanceIndex; + @Basic @Column private int parameterCount; @@ -113,7 +117,7 @@ public class Model implements Serializable{ public Model() { } - public Model(Long id, String name, String shortDescription, String longDescription, Date added, Date lastModified, int votes, double performance, String performanceUnit, int parameterCount, byte[] file, String fileType, String checksum, boolean isVerified, User author, Set<Tag> tags, Set<CustomLayer> customLayers, Set<Comment> comments) { + public Model(Long id, String name, String shortDescription, String longDescription, Date added, Date lastModified, int votes, double performance, String performanceUnit, double performanceIndex, int parameterCount, byte[] file, String fileType, String checksum, boolean isVerified, User author, Set<Tag> tags, Set<CustomLayer> customLayers, Set<Comment> comments) { this.id = id; this.name = name; this.shortDescription = shortDescription; @@ -123,6 +127,7 @@ public class Model implements Serializable{ this.votes = votes; this.performance = performance; this.performanceUnit = performanceUnit; + this.performanceIndex = performanceIndex; this.parameterCount = parameterCount; this.file = file; this.fileType = fileType; @@ -134,6 +139,15 @@ public class Model implements Serializable{ this.comments = comments; } + @JsonIgnore + public double getPerformanceIndex() { + return this.performanceIndex; + } + + public void setPerformanceIndex(double performanceIndex) { + this.performanceIndex = performanceIndex; + } + public Long getId() { return this.id; } diff --git a/mozen/src/main/java/mozen/model/User.java b/mozen/src/main/java/mozen/model/User.java index 4a28044..473af1d 100644 --- a/mozen/src/main/java/mozen/model/User.java +++ b/mozen/src/main/java/mozen/model/User.java @@ -13,6 +13,8 @@ import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; +import javax.persistence.JoinTable; +import javax.persistence.ManyToMany; import javax.persistence.OneToMany; import javax.persistence.Table; import javax.validation.constraints.NotNull; @@ -67,10 +69,23 @@ public class User implements Serializable{ @JsonIgnoreProperties({"hibernateLazyInitializer", "handler"}) private Set<Comment> comments; + @Basic + @ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST}) + @JoinTable(name = "model_vote_up") + @JsonIgnoreProperties({"hibernateLazyInitializer", "handler"}) + private Set<Model> upvotes; + + @Basic + @ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST}) + @JoinTable(name = "model_vote_down") + @JsonIgnoreProperties({"hibernateLazyInitializer", "handler"}) + private Set<Model> downvotes; + + public User() { } - public User(Long id, String username, String password, String email, Role role, Set<Model> models, Set<Comment> comments) { + public User(Long id, String username, String password, String email, Role role, Set<Model> models, Set<Comment> comments, Set<Model> upvotes, Set<Model> downvotes) { this.id = id; this.username = username; this.password = password; @@ -78,6 +93,8 @@ public class User implements Serializable{ this.role = role; this.models = models; this.comments = comments; + this.upvotes = upvotes; + this.downvotes = downvotes; } public Long getId() { @@ -139,4 +156,23 @@ public class User implements Serializable{ this.comments = comments; } + @JsonIgnore + public Set<Model> getUpvotes() { + return this.upvotes; + } + + public void setUpvotes(Set<Model> upvotes) { + this.upvotes = upvotes; + } + + @JsonIgnore + public Set<Model> getDownvotes() { + return this.downvotes; + } + + public void setDownvotes(Set<Model> downvotes) { + this.downvotes = downvotes; + } + + } \ No newline at end of file diff --git a/mozen/src/main/java/mozen/utils/DatabaseFiller.java b/mozen/src/main/java/mozen/utils/DatabaseFiller.java index 06c624a..4636076 100644 --- a/mozen/src/main/java/mozen/utils/DatabaseFiller.java +++ b/mozen/src/main/java/mozen/utils/DatabaseFiller.java @@ -69,6 +69,7 @@ public class DatabaseFiller { m1.setLongDescription("# README \n model testo"); m1.setVotes(0); m1.setParameterCount(10); + m1.setPerformanceIndex(1.5); m1.setPerformance(98.5); m1.setPerformanceUnit("accuracy"); m1.setAdded(new Date()); diff --git a/mozen/src/main/java/mozen/web/SearchController.java b/mozen/src/main/java/mozen/web/SearchController.java index 49ccb20..8d6c0fb 100644 --- a/mozen/src/main/java/mozen/web/SearchController.java +++ b/mozen/src/main/java/mozen/web/SearchController.java @@ -31,8 +31,8 @@ public class SearchController { { SearchResult result; - if (tags.isEmpty()) result = modelManager.findModel(name, page, size, sort); - else result = modelManager.findModelWithTags(name, page, size, sort, tags); + if (tags.isEmpty()) result = modelManager.findModel(name, page, size, sort, null); + else result = modelManager.findModel(name, page, size, sort, tags); return result; } diff --git a/mozen/src/main/java/mozen/web/VoteController.java b/mozen/src/main/java/mozen/web/VoteController.java index 72f3f24..ad0913c 100644 --- a/mozen/src/main/java/mozen/web/VoteController.java +++ b/mozen/src/main/java/mozen/web/VoteController.java @@ -5,11 +5,17 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import mozen.business.IModelManager; import mozen.business.IUserManager; +import mozen.business.IVoteManager; +import mozen.messages.ResponseMessage; +import mozen.messages.VoteStatusMessage; +import mozen.model.User; +import mozen.utils.UserHelper; + import org.springframework.web.bind.annotation.RequestParam; @RestController @@ -17,18 +23,90 @@ import org.springframework.web.bind.annotation.RequestParam; @CrossOrigin public class VoteController { @Autowired - IModelManager modelManager; + IVoteManager voteManager; @Autowired IUserManager userManager; @GetMapping - public ResponseEntity<?> addVote(@RequestParam(value = "id", required = false) Long id) { - return null; + public ResponseEntity<?> getVoteStatus(@RequestParam(value = "id", required = true) Long id) { + ResponseMessage response = new ResponseMessage(false, ""); + User user = UserHelper.getCurrentUser(userManager); + if(user == null) { + response.setError(true); + response.setMessage("User unknown"); + return ResponseEntity.badRequest().body(response); + } + + try { + String status = voteManager.getStatus(id, user); + return ResponseEntity.ok(new VoteStatusMessage(status)); + } catch (Exception e) { + response.setError(true); + response.setMessage(e.getMessage()); + return ResponseEntity.badRequest().body(response); + } + } + + @PutMapping + public ResponseEntity<?> addVote(@RequestParam(value = "id", required = true) Long id, @RequestParam(value = "isDown", required = true) boolean isDown) { + ResponseMessage response = new ResponseMessage(false, ""); + User user = UserHelper.getCurrentUser(userManager); + if(user == null) { + response.setError(true); + response.setMessage("User unknown"); + return ResponseEntity.badRequest().body(response); + } + + try { + if (isDown) { + voteManager.addDownvote(id, user); + } else { + voteManager.addUpvote(id, user); + } + } catch (Exception e) { + response.setError(true); + response.setMessage(e.getMessage()); + return ResponseEntity.badRequest().body(response); + } + + return ResponseEntity.ok(response); } @DeleteMapping - public ResponseEntity<?> removeVote(@RequestParam(value = "id", required = false) Long id) { - return null; + public ResponseEntity<?> removeVote(@RequestParam(value = "id", required = true) Long id, @RequestParam(value = "isDown", required = true) boolean isDown) { + ResponseMessage response = new ResponseMessage(false, ""); + User user = UserHelper.getCurrentUser(userManager); + if(user == null) { + response.setError(true); + response.setMessage("User unknown"); + return ResponseEntity.badRequest().body(response); + } + + try { + if (isDown) { + voteManager.removeDownvote(id, user); + } else { + voteManager.removeUpvote(id, user); + } + } catch (Exception e) { + response.setError(true); + response.setMessage(e.getMessage()); + return ResponseEntity.badRequest().body(response); + } + + return ResponseEntity.ok(response); + } + + @GetMapping("/likedModels") + public ResponseEntity<?> getLikedModels() { + ResponseMessage response = new ResponseMessage(false, ""); + User user = UserHelper.getCurrentUser(userManager); + if(user == null) { + response.setError(true); + response.setMessage("User unknown"); + return ResponseEntity.badRequest().body(response); + } + return ResponseEntity.ok(user.getUpvotes()); } } \ No newline at end of file -- GitLab