diff --git a/mozen/src/main/java/mozen/business/IModelManager.java b/mozen/src/main/java/mozen/business/IModelManager.java index d383f7e3cac169a85c0d150b5ded1cdb1f80415e..61de3c2273708badff2081a9ee3737105551b8bd 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 0000000000000000000000000000000000000000..6c4d92fd7277c8cb3dab4f5c387a41eb99f5b7ba --- /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 fd1daa802999a5d0247221cbd5678e79a6577879..349ad188bc724ef42ded9e03622fe75bacf8d636 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 0000000000000000000000000000000000000000..019ce728fd964c57d1d5bea563a7eccf1a32112c --- /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 b8895ecccf2ad1dcc671adf589b5960afb87e466..afd579fd6190c6083c05e2038ef315bfd8bdeeba 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 0000000000000000000000000000000000000000..fb2963d314793efe6659ba5a9c15eff6748d28b5 --- /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 a8eb93eccd962ce2cfdf83985366f3886fb0ce11..8ba18c82d10765501a1cf4dc63c4eb490dfc6e1f 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 4a2804437274334024fb1166115547ea8b73bb24..473af1d1466bda19432eb5e34728510c27e040b9 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 06c624a6c34ddb39b3ae5cc4dd0fec43def50a7b..4636076933d973332410aff64ab5a6cb61b843c0 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 49ccb20f4c6d8d11467795ecb25c44ba60eb1850..8d6c0fbfb8490154482cdf151272cc2ede9705b4 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 72f3f24fe10e7a66d258cafeb3b5d3d9fb562348..ad0913c66606e052582cd028f3e359fbb059d878 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