From e7bb996f71b696a1f0cd76adffb489cc3fb6f13d Mon Sep 17 00:00:00 2001 From: Cedric Ong <67156011+cedricongjh@users.noreply.github.com> Date: Sun, 26 Feb 2023 09:15:46 +0900 Subject: [PATCH] Create FeedbackResponse and FeedbackResponseComment entities (#12135) --- .../teammates/common/util/HibernateUtil.java | 9 +- .../storage/sqlentity/BaseEntity.java | 19 ++ .../storage/sqlentity/FeedbackQuestion.java | 19 +- .../storage/sqlentity/FeedbackResponse.java | 179 +++++++++++++ .../sqlentity/FeedbackResponseComment.java | 240 ++++++++++++++++++ .../FeedbackNumericalScaleResponse.java | 46 ++++ .../responses/FeedbackTextResponse.java | 34 +++ .../sqlentity/responses/package-info.java | 4 + 8 files changed, 542 insertions(+), 8 deletions(-) create mode 100644 src/main/java/teammates/storage/sqlentity/FeedbackResponse.java create mode 100644 src/main/java/teammates/storage/sqlentity/FeedbackResponseComment.java create mode 100644 src/main/java/teammates/storage/sqlentity/responses/FeedbackNumericalScaleResponse.java create mode 100644 src/main/java/teammates/storage/sqlentity/responses/FeedbackTextResponse.java create mode 100644 src/main/java/teammates/storage/sqlentity/responses/package-info.java diff --git a/src/main/java/teammates/common/util/HibernateUtil.java b/src/main/java/teammates/common/util/HibernateUtil.java index 6169cfceb63..59674196711 100644 --- a/src/main/java/teammates/common/util/HibernateUtil.java +++ b/src/main/java/teammates/common/util/HibernateUtil.java @@ -15,6 +15,8 @@ import teammates.storage.sqlentity.Course; import teammates.storage.sqlentity.DeadlineExtension; import teammates.storage.sqlentity.FeedbackQuestion; +import teammates.storage.sqlentity.FeedbackResponse; +import teammates.storage.sqlentity.FeedbackResponseComment; import teammates.storage.sqlentity.FeedbackSession; import teammates.storage.sqlentity.Instructor; import teammates.storage.sqlentity.Notification; @@ -26,6 +28,7 @@ import teammates.storage.sqlentity.User; import teammates.storage.sqlentity.questions.FeedbackNumericalScaleQuestion; import teammates.storage.sqlentity.questions.FeedbackTextQuestion; +import teammates.storage.sqlentity.responses.FeedbackTextResponse; /** * Utility class for Hibernate related methods. @@ -49,7 +52,11 @@ public final class HibernateUtil { FeedbackQuestion.class, FeedbackNumericalScaleQuestion.class, FeedbackTextQuestion.class, - DeadlineExtension.class); + DeadlineExtension.class, + FeedbackResponse.class, + FeedbackTextResponse.class, + FeedbackNumericalScaleQuestion.class, + FeedbackResponseComment.class); private HibernateUtil() { // Utility class diff --git a/src/main/java/teammates/storage/sqlentity/BaseEntity.java b/src/main/java/teammates/storage/sqlentity/BaseEntity.java index 76eb0018904..770f689ace5 100644 --- a/src/main/java/teammates/storage/sqlentity/BaseEntity.java +++ b/src/main/java/teammates/storage/sqlentity/BaseEntity.java @@ -8,6 +8,7 @@ import com.google.common.reflect.TypeToken; +import teammates.common.datatransfer.FeedbackParticipantType; import teammates.common.util.JsonUtils; import jakarta.persistence.AttributeConverter; @@ -100,4 +101,22 @@ public T convertToEntityAttribute(String dbData) { return JsonUtils.fromJson(dbData, new TypeToken(){}.getType()); } } + + /** + * Attribute converter between FeedbackParticipantType and JSON. + */ + @Converter + public static class FeedbackParticipantTypeConverter + extends JsonConverter { + + } + + /** + * Attribute converter between a list of FeedbackParticipantTypes and JSON. + */ + @Converter + public static class FeedbackParticipantTypeListConverter + extends JsonConverter> { + + } } diff --git a/src/main/java/teammates/storage/sqlentity/FeedbackQuestion.java b/src/main/java/teammates/storage/sqlentity/FeedbackQuestion.java index d9cfd96d765..1b04baf44d6 100644 --- a/src/main/java/teammates/storage/sqlentity/FeedbackQuestion.java +++ b/src/main/java/teammates/storage/sqlentity/FeedbackQuestion.java @@ -15,7 +15,6 @@ import jakarta.persistence.Column; import jakarta.persistence.Convert; -import jakarta.persistence.Converter; import jakarta.persistence.Entity; import jakarta.persistence.EnumType; import jakarta.persistence.Enumerated; @@ -24,6 +23,7 @@ import jakarta.persistence.InheritanceType; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; import jakarta.persistence.Table; /** @@ -40,6 +40,9 @@ public abstract class FeedbackQuestion extends BaseEntity { @JoinColumn(name = "sessionId") private FeedbackSession feedbackSession; + @OneToMany(mappedBy = "feedbackQuestion") + private List feedbackResponses = new ArrayList<>(); + @Column(nullable = false) private Integer questionNumber; @@ -137,6 +140,14 @@ public void setFeedbackSession(FeedbackSession feedbackSession) { this.feedbackSession = feedbackSession; } + public List getFeedbackResponses() { + return feedbackResponses; + } + + public void setFeedbackResponses(List feedbackResponses) { + this.feedbackResponses = feedbackResponses; + } + public Integer getQuestionNumber() { return questionNumber; } @@ -255,11 +266,5 @@ public boolean equals(Object other) { return false; } } - - @Converter - private static class FeedbackParticipantTypeListConverter - extends JsonConverter> { - - } } diff --git a/src/main/java/teammates/storage/sqlentity/FeedbackResponse.java b/src/main/java/teammates/storage/sqlentity/FeedbackResponse.java new file mode 100644 index 00000000000..c3ea5b97bb3 --- /dev/null +++ b/src/main/java/teammates/storage/sqlentity/FeedbackResponse.java @@ -0,0 +1,179 @@ +package teammates.storage.sqlentity; + +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.UUID; + +import org.hibernate.annotations.UpdateTimestamp; + +import teammates.common.datatransfer.questions.FeedbackQuestionType; + +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Inheritance; +import jakarta.persistence.InheritanceType; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; + +/** + * Represents a Feedback Response. + */ +@Entity +@Table(name = "FeedbackReponses") +@Inheritance(strategy = InheritanceType.SINGLE_TABLE) +public abstract class FeedbackResponse extends BaseEntity { + @Id + private UUID id; + + @ManyToOne + @JoinColumn(name = "questionId") + private FeedbackQuestion feedbackQuestion; + + @Column(nullable = false) + @Convert(converter = FeedbackParticipantTypeConverter.class) + private FeedbackQuestionType type; + + @OneToMany(mappedBy = "feedbackResponse") + private List feedbackResponseComments = new ArrayList<>(); + + @Column(nullable = false) + private String giver; + + @ManyToOne + @JoinColumn(name = "giverSectionId") + private Section giverSection; + + @Column(nullable = false) + private String receiver; + + @ManyToOne + @JoinColumn(name = "receiverSectionId") + private Section receiverSection; + + @UpdateTimestamp + private Instant updatedAt; + + protected FeedbackResponse() { + // required by Hibernate + } + + public FeedbackResponse( + FeedbackQuestion feedbackQuestion, FeedbackQuestionType type, String giver, + Section giverSection, String receiver, Section receiverSection + ) { + this.setFeedbackQuestion(feedbackQuestion); + this.setFeedbackQuestionType(type); + this.setGiver(giver); + this.setGiverSection(giverSection); + this.setReceiver(receiver); + this.setReceiverSection(receiverSection); + } + + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + + public FeedbackQuestion getFeedbackQuestion() { + return feedbackQuestion; + } + + public void setFeedbackQuestion(FeedbackQuestion feedbackQuestion) { + this.feedbackQuestion = feedbackQuestion; + } + + public FeedbackQuestionType getFeedbackQuestionType() { + return type; + } + + public void setFeedbackQuestionType(FeedbackQuestionType type) { + this.type = type; + } + + public List getFeedbackResponseComments() { + return feedbackResponseComments; + } + + public void setFeedbackResponseComments(List feedbackResponseComments) { + this.feedbackResponseComments = feedbackResponseComments; + } + + public String getGiver() { + return giver; + } + + public void setGiver(String giver) { + this.giver = giver; + } + + public Section getGiverSection() { + return giverSection; + } + + public void setGiverSection(Section giverSection) { + this.giverSection = giverSection; + } + + public String getReceiver() { + return receiver; + } + + public void setReceiver(String receiver) { + this.receiver = receiver; + } + + public Section getReceiverSection() { + return receiverSection; + } + + public void setReceiverSection(Section receiverSection) { + this.receiverSection = receiverSection; + } + + public Instant getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(Instant updatedAt) { + this.updatedAt = updatedAt; + } + + @Override + public List getInvalidityInfo() { + return new ArrayList<>(); + } + + @Override + public String toString() { + return "FeedbackResponse [id=" + id + ", giver=" + giver + ", receiver=" + receiver + + ", createdAt=" + getCreatedAt() + ", updatedAt=" + updatedAt + "]"; + } + + @Override + public int hashCode() { + return this.getId().hashCode(); + } + + @Override + public boolean equals(Object other) { + if (other == null) { + return false; + } else if (this == other) { + return true; + } else if (this.getClass() == other.getClass()) { + FeedbackResponse otherResponse = (FeedbackResponse) other; + return Objects.equals(this.id, otherResponse.id); + } else { + return false; + } + } +} diff --git a/src/main/java/teammates/storage/sqlentity/FeedbackResponseComment.java b/src/main/java/teammates/storage/sqlentity/FeedbackResponseComment.java new file mode 100644 index 00000000000..05e00ef9d4c --- /dev/null +++ b/src/main/java/teammates/storage/sqlentity/FeedbackResponseComment.java @@ -0,0 +1,240 @@ +package teammates.storage.sqlentity; + +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.UUID; + +import org.hibernate.annotations.UpdateTimestamp; + +import teammates.common.datatransfer.FeedbackParticipantType; +import teammates.common.util.FieldValidator; + +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; + +/** + * Represents a feedback response comment. + */ +@Entity +@Table(name = "FeedbackReponseComments") +public class FeedbackResponseComment extends BaseEntity { + @Id + private UUID id; + + @ManyToOne + @JoinColumn(name = "responseId") + private FeedbackResponse feedbackResponse; + + @Column(nullable = false) + private String giver; + + @Column(nullable = false) + @Convert(converter = FeedbackParticipantTypeConverter.class) + private FeedbackParticipantType giverType; + + @ManyToOne + @JoinColumn(name = "giverSectionId") + private Section giverSection; + + @ManyToOne + @JoinColumn(name = "receiverSectionId") + private Section receiverSection; + + @Column(nullable = false) + private String commentText; + + @Column(nullable = false) + private boolean isVisibilityFollowingFeedbackQuestion; + + @Column(nullable = false) + private boolean isCommentFromFeedbackParticipant; + + @Column(nullable = false) + @Convert(converter = FeedbackParticipantTypeListConverter.class) + private List showCommentTo; + + @Column(nullable = false) + @Convert(converter = FeedbackParticipantTypeListConverter.class) + private List showGiverNameTo; + + @UpdateTimestamp + private Instant updatedAt; + + @Column(nullable = false) + private String lastEditorEmail; + + protected FeedbackResponseComment() { + // required by Hibernate + } + + public FeedbackResponseComment( + FeedbackResponse feedbackResponse, String giver, FeedbackParticipantType giverType, + Section giverSection, Section receiverSection, String commentText, + boolean isVisibilityFollowingFeedbackQuestion, boolean isCommentFromFeedbackParticipant, + List showCommentTo, List showGiverNameTo, + String lastEditorEmail + ) { + this.setFeedbackResponse(feedbackResponse); + this.setGiver(giver); + this.setGiverType(giverType); + this.setGiverSection(giverSection); + this.setReceiverSection(receiverSection); + this.setCommentText(commentText); + this.setIsVisibilityFollowingFeedbackQuestion(isVisibilityFollowingFeedbackQuestion); + this.setIsCommentFromFeedbackParticipant(isCommentFromFeedbackParticipant); + this.setShowCommentTo(showCommentTo); + this.setShowGiverNameTo(showGiverNameTo); + this.setLastEditorEmail(lastEditorEmail); + } + + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + + public FeedbackResponse getFeedbackResponse() { + return feedbackResponse; + } + + public void setFeedbackResponse(FeedbackResponse feedbackResponse) { + this.feedbackResponse = feedbackResponse; + } + + public String getGiver() { + return giver; + } + + public void setGiver(String giver) { + this.giver = giver; + } + + public FeedbackParticipantType getGiverType() { + return giverType; + } + + public void setGiverType(FeedbackParticipantType giverType) { + this.giverType = giverType; + } + + public Section getGiverSection() { + return giverSection; + } + + public void setGiverSection(Section giverSection) { + this.giverSection = giverSection; + } + + public Section getReceiverSection() { + return receiverSection; + } + + public void setReceiverSection(Section receiverSection) { + this.receiverSection = receiverSection; + } + + public String getCommentText() { + return commentText; + } + + public void setCommentText(String commentText) { + this.commentText = commentText; + } + + public boolean getIsVisibilityFollowingFeedbackQuestion() { + return this.isVisibilityFollowingFeedbackQuestion; + } + + public void setIsVisibilityFollowingFeedbackQuestion(boolean isVisibilityFollowingFeedbackQuestion) { + this.isVisibilityFollowingFeedbackQuestion = isVisibilityFollowingFeedbackQuestion; + } + + public boolean getIsCommentFromFeedbackParticipant() { + return this.isCommentFromFeedbackParticipant; + } + + public void setIsCommentFromFeedbackParticipant(boolean isCommentFromFeedbackParticipant) { + this.isCommentFromFeedbackParticipant = isCommentFromFeedbackParticipant; + } + + public List getShowCommentTo() { + return showCommentTo; + } + + public void setShowCommentTo(List showCommentTo) { + this.showCommentTo = showCommentTo; + } + + public List getShowGiverNameTo() { + return showGiverNameTo; + } + + public void setShowGiverNameTo(List showGiverNameTo) { + this.showGiverNameTo = showGiverNameTo; + } + + public Instant getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(Instant updatedAt) { + this.updatedAt = updatedAt; + } + + public String getLastEditorEmail() { + return lastEditorEmail; + } + + public void setLastEditorEmail(String lastEditorEmail) { + this.lastEditorEmail = lastEditorEmail; + } + + @Override + public List getInvalidityInfo() { + List errors = new ArrayList<>(); + + addNonEmptyError(FieldValidator.getInvalidityInfoForCommentGiverType(giverType), errors); + + addNonEmptyError(FieldValidator.getInvalidityInfoForVisibilityOfFeedbackParticipantComments( + isCommentFromFeedbackParticipant, isVisibilityFollowingFeedbackQuestion), errors); + + return errors; + } + + @Override + public String toString() { + return "FeedbackResponse [id=" + id + ", giver=" + giver + ", commentText=" + commentText + + ", isVisibilityFollowingFeedbackQuestion=" + isVisibilityFollowingFeedbackQuestion + + ", isCommentFromFeedbackParticipant=" + isCommentFromFeedbackParticipant + + ", lastEditorEmail=" + lastEditorEmail + ", createdAt=" + getCreatedAt() + + ", updatedAt=" + updatedAt + "]"; + } + + @Override + public int hashCode() { + return this.getId().hashCode(); + } + + @Override + public boolean equals(Object other) { + if (other == null) { + return false; + } else if (this == other) { + return true; + } else if (this.getClass() == other.getClass()) { + FeedbackResponseComment otherResponse = (FeedbackResponseComment) other; + return Objects.equals(this.id, otherResponse.id); + } else { + return false; + } + } +} diff --git a/src/main/java/teammates/storage/sqlentity/responses/FeedbackNumericalScaleResponse.java b/src/main/java/teammates/storage/sqlentity/responses/FeedbackNumericalScaleResponse.java new file mode 100644 index 00000000000..76912630892 --- /dev/null +++ b/src/main/java/teammates/storage/sqlentity/responses/FeedbackNumericalScaleResponse.java @@ -0,0 +1,46 @@ +package teammates.storage.sqlentity.responses; + +import teammates.common.datatransfer.questions.FeedbackNumericalScaleResponseDetails; +import teammates.storage.sqlentity.FeedbackResponse; + +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Converter; +import jakarta.persistence.Entity; + +/** + * Represents a feedback numerical scale response. + */ +@Entity +public class FeedbackNumericalScaleResponse extends FeedbackResponse { + + @Column(nullable = false) + @Convert(converter = FeedbackNumericalScaleResponseDetailsConverter.class) + private FeedbackNumericalScaleResponseDetails answer; + + protected FeedbackNumericalScaleResponse() { + // required by Hibernate + } + + public FeedbackNumericalScaleResponseDetails getAnswer() { + return answer; + } + + public void setAnswer(FeedbackNumericalScaleResponseDetails answer) { + this.answer = answer; + } + + @Override + public String toString() { + return "FeedbackTextResponse [id=" + super.getId() + + ", createdAt=" + super.getCreatedAt() + ", updatedAt=" + super.getUpdatedAt() + "]"; + } + + /** + * Converter for FeedbackNumericalScaleQuestion specific attributes. + */ + @Converter + public static class FeedbackNumericalScaleResponseDetailsConverter + extends JsonConverter { + } +} diff --git a/src/main/java/teammates/storage/sqlentity/responses/FeedbackTextResponse.java b/src/main/java/teammates/storage/sqlentity/responses/FeedbackTextResponse.java new file mode 100644 index 00000000000..37190515022 --- /dev/null +++ b/src/main/java/teammates/storage/sqlentity/responses/FeedbackTextResponse.java @@ -0,0 +1,34 @@ +package teammates.storage.sqlentity.responses; + +import teammates.storage.sqlentity.FeedbackResponse; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; + +/** + * Represents a text response. + */ +@Entity +public class FeedbackTextResponse extends FeedbackResponse { + + @Column(nullable = false) + private String answer; + + protected FeedbackTextResponse() { + // required by Hibernate + } + + public String getAnswer() { + return answer; + } + + public void setAnswer(String answer) { + this.answer = answer; + } + + @Override + public String toString() { + return "FeedbackTextResponse [id=" + super.getId() + + ", createdAt=" + super.getCreatedAt() + ", updatedAt=" + super.getUpdatedAt() + "]"; + } +} diff --git a/src/main/java/teammates/storage/sqlentity/responses/package-info.java b/src/main/java/teammates/storage/sqlentity/responses/package-info.java new file mode 100644 index 00000000000..73ca379cb57 --- /dev/null +++ b/src/main/java/teammates/storage/sqlentity/responses/package-info.java @@ -0,0 +1,4 @@ +/** + * Contains FeedbackResponse subclass entities. + */ +package teammates.storage.sqlentity.responses;