This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository coselmar. See http://git.codelutin.com/coselmar.git commit 70fce4124319f97e788d6eb0dac2ec81e93d5416 Author: Yannick Martel <martel@©odelutin.com> Date: Fri Jan 8 16:20:44 2016 +0100 fixes #7893 ajout de deux methodes pour récupérer les arbres des ancêtres et descendants d'un projet --- .../ifremer/coselmar/beans/QuestionTreeNode.java | 92 +++++++++++ .../coselmar/services/v1/QuestionsWebService.java | 170 +++++++++++++++++++++ coselmar-rest/src/main/resources/mapping | 2 + 3 files changed, 264 insertions(+) diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/beans/QuestionTreeNode.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/beans/QuestionTreeNode.java new file mode 100644 index 0000000..b95cbb0 --- /dev/null +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/beans/QuestionTreeNode.java @@ -0,0 +1,92 @@ +package fr.ifremer.coselmar.beans; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; +import java.util.Set; + +/** + * @author ymartel (martel@codelutin.com) + */ +public class QuestionTreeNode implements Serializable { + + protected String id; + + protected String title; + + protected Date submissionDate; + + protected Date deadline; + + protected Set<String> themes; + + protected String type; + + protected List<QuestionTreeNode> ancestors; + + protected List<QuestionTreeNode> descendants; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Date getSubmissionDate() { + return submissionDate; + } + + public void setSubmissionDate(Date submissionDate) { + this.submissionDate = submissionDate; + } + + public Date getDeadline() { + return deadline; + } + + public void setDeadline(Date deadline) { + this.deadline = deadline; + } + + public Set<String> getThemes() { + return themes; + } + + public void setThemes(Set<String> themes) { + this.themes = themes; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public List<QuestionTreeNode> getAncestors() { + return ancestors; + } + + public void setAncestors(List<QuestionTreeNode> ancestors) { + this.ancestors = ancestors; + } + + public List<QuestionTreeNode> getDescendants() { + return descendants; + } + + public void setDescendants(List<QuestionTreeNode> descendants) { + this.descendants = descendants; + } +} diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/QuestionsWebService.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/QuestionsWebService.java index b390f49..90f3333 100644 --- a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/QuestionsWebService.java +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/QuestionsWebService.java @@ -27,6 +27,7 @@ package fr.ifremer.coselmar.services.v1; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.Date; import java.util.HashSet; import java.util.List; @@ -36,12 +37,14 @@ import com.google.common.base.Function; import com.google.common.base.Preconditions; import com.google.common.collect.Collections2; import com.google.common.collect.Lists; +import com.google.common.collect.Sets; import fr.ifremer.coselmar.beans.DocumentBean; import fr.ifremer.coselmar.beans.LinkBean; import fr.ifremer.coselmar.beans.QuestionBean; import fr.ifremer.coselmar.beans.QuestionExportModel; import fr.ifremer.coselmar.beans.QuestionSearchBean; import fr.ifremer.coselmar.beans.QuestionSearchExample; +import fr.ifremer.coselmar.beans.QuestionTreeNode; import fr.ifremer.coselmar.beans.UserBean; import fr.ifremer.coselmar.beans.UserWebToken; import fr.ifremer.coselmar.converter.BeanEntityConverter; @@ -915,6 +918,87 @@ public class QuestionsWebService extends CoselmarWebServiceSupport { } + public List<QuestionTreeNode> getAncestors(String questionId, int depth) throws InvalidCredentialException, UnauthorizedException { + + // Check authentication + String authorization = getContext().getHeader("Authorization"); + CoselmarUser currentUser = checkUserAuthentication(authorization); + + // Supervisor can get all the question elements + // Expert can get all the question elements if public or if he is participant of the question + // Client can get the question (not the documents) if he is client of the question. + + // Member cannot access to question + if (CoselmarUserRole.MEMBER == currentUser.getRole()) { + String message = String.format("User %s %s ('%s') is not allowed to view question", + currentUser.getFirstname(), currentUser.getName(), getShortIdFromFull(currentUser.getTopiaId())); + if (log.isWarnEnabled()) { + log.warn(message); + } + throw new UnauthorizedException(message); + + } + + // Retrieve Question + String fullQuestionId = getFullIdFromShort(Question.class, questionId); + Question question = getQuestionDao().forTopiaIdEquals(fullQuestionId).findUnique(); + + if (CoselmarUserRole.CLIENT == currentUser.getRole()) { + // Client User can access if it is client of question + checkIsClientAllowed(question, currentUser); + + } + + List<QuestionTreeNode> result; + if (depth > 0) { + result = buildAncestorsTree(fullQuestionId, depth); + } else { + result = Collections.emptyList(); + } + + return result; + } + + public List<QuestionTreeNode> getDescendants(String questionId, int depth) throws InvalidCredentialException, UnauthorizedException { + + // Check authentication + String authorization = getContext().getHeader("Authorization"); + CoselmarUser currentUser = checkUserAuthentication(authorization); + + // Supervisor can get all the question elements + // Expert can get all the question elements if public or if he is participant of the question + // Client can get the question (not the documents) if he is client of the question. + + // Member cannot access to question + if (CoselmarUserRole.MEMBER == currentUser.getRole()) { + String message = String.format("User %s %s ('%s') is not allowed to view question", + currentUser.getFirstname(), currentUser.getName(), getShortIdFromFull(currentUser.getTopiaId())); + if (log.isWarnEnabled()) { + log.warn(message); + } + throw new UnauthorizedException(message); + + } + + // Retrieve Question + String fullQuestionId = getFullIdFromShort(Question.class, questionId); + Question question = getQuestionDao().forTopiaIdEquals(fullQuestionId).findUnique(); + + if (CoselmarUserRole.CLIENT == currentUser.getRole()) { + // Client User can access if it is client of question + checkIsClientAllowed(question, currentUser); + + } + + List<QuestionTreeNode> result; + if (depth > 0) { + result = buildDescendantsTree(fullQuestionId, depth); + } else { + result = Collections.emptyList(); + } + + return result; + } //////////////////////////////////////////////////////////////////////////// /////////////////////// Internal Parts ///////////////////////////// @@ -1207,4 +1291,90 @@ public class QuestionsWebService extends CoselmarWebServiceSupport { return questions; } + protected List<QuestionTreeNode> buildAncestorsTree(String questionId, int depth) { + // Depth = 0 : it is the end of the tree ! + if (depth == 0) { + return Collections.emptyList(); + } + + Question question = getQuestionDao().forTopiaIdEquals(questionId).findUnique(); + Set<Question> parents = question.getParents(); + + List<QuestionTreeNode> result; + + if (parents == null || parents.isEmpty()) { + result = Collections.emptyList(); + + } else { + result = new ArrayList<>(parents.size()); + + // Convert parent to QuestionTreeNode + for (Question parent : parents) { + QuestionTreeNode ancestor = new QuestionTreeNode(); + String parentId = parent.getTopiaId(); + ancestor.setId(parentId); + ancestor.setTitle(parent.getTitle()); + ancestor.setThemes(Sets.newHashSet(parent.getTheme())); + Date deadline = parent.getDeadline(); + if (deadline != null) { + ancestor.setDeadline(new Date(deadline.getTime())); + } + Date submissionDate = parent.getSubmissionDate(); + if (submissionDate != null) { + ancestor.setSubmissionDate((new Date (submissionDate.getTime()))); + } + ancestor.setType(parent.getType()); + // Get ancestors of this parent + List<QuestionTreeNode> parentAncestors = buildAncestorsTree(parentId, depth - 1); + ancestor.setAncestors(parentAncestors); + result.add(ancestor); + } + } + + return result; + } + + protected List<QuestionTreeNode> buildDescendantsTree(String questionId, int depth) { + // Depth = 0 : it is the end of the tree ! + if (depth == 0) { + return Collections.emptyList(); + } + + Question question = getQuestionDao().forTopiaIdEquals(questionId).findUnique(); + List<Question> children = getQuestionDao().forParentsContains(question).findAll(); + + List<QuestionTreeNode> result; + + if (children == null || children.isEmpty()) { + result = Collections.emptyList(); + + } else { + result = new ArrayList<>(children.size()); + + // Convert child to QuestionTreeNode + for (Question child : children) { + QuestionTreeNode descendant = new QuestionTreeNode(); + String parentId = child.getTopiaId(); + descendant.setId(parentId); + descendant.setTitle(child.getTitle()); + descendant.setThemes(Sets.newHashSet(child.getTheme())); + Date deadline = child.getDeadline(); + if (deadline != null) { + descendant.setDeadline(new Date(deadline.getTime())); + } + Date submissionDate = child.getSubmissionDate(); + if (submissionDate != null) { + descendant.setSubmissionDate((new Date (submissionDate.getTime()))); + } + descendant.setType(child.getType()); + // Get descendants of this child + List<QuestionTreeNode> childDescendants = buildDescendantsTree(parentId, depth - 1); + descendant.setDescendants(childDescendants); + result.add(descendant); + } + } + + return result; + } + } diff --git a/coselmar-rest/src/main/resources/mapping b/coselmar-rest/src/main/resources/mapping index a980514..9352587 100644 --- a/coselmar-rest/src/main/resources/mapping +++ b/coselmar-rest/src/main/resources/mapping @@ -63,6 +63,8 @@ POST /v1/questions/{questionId} QuestionsWebService.saveQuestion POST /v1/questions/{questionId}/documents QuestionsWebService.addDocuments POST /v1/questions QuestionsWebService.addQuestion DELETE /v1/questions/{questionId} QuestionsWebService.deleteQuestion +GET /v1/questions/{questionId}/ancestors QuestionsWebService.getAncestors depth=2 +GET /v1/questions/{questionId}/descendants QuestionsWebService.getDescendants depth=2 # Transverse Api -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.