Commit 1a7b2dcd authored by Daniel Gerhardt's avatar Daniel Gerhardt

Separate content persistance code and migrate it to Ektorp

(Lecturer/Skill)Question has been renamed to Content. Method names have
not been touched yet to ease reviewing the changes.
parent 98401962
......@@ -51,7 +51,7 @@ public class CacheBuster implements ICacheBuster, NovaEventVisitor {
@Override
public void visit(LockQuestionsEvent lockQuestionsEvent) { }
@CacheEvict(value = "answers", key = "#event.Question")
@CacheEvict(value = "answers", key = "#event.content")
@Override
public void visit(NewAnswerEvent event) { }
......
......@@ -27,16 +27,19 @@ import de.thm.arsnova.entities.Comment;
import de.thm.arsnova.entities.DbUser;
import de.thm.arsnova.entities.LogEntry;
import de.thm.arsnova.entities.Motd;
import de.thm.arsnova.entities.Content;
import de.thm.arsnova.entities.Session;
import de.thm.arsnova.entities.serialization.CouchDbDocumentModule;
import de.thm.arsnova.entities.serialization.CouchDbObjectMapperFactory;
import de.thm.arsnova.entities.serialization.View;
import de.thm.arsnova.persistance.CommentRepository;
import de.thm.arsnova.persistance.ContentRepository;
import de.thm.arsnova.persistance.LogEntryRepository;
import de.thm.arsnova.persistance.MotdRepository;
import de.thm.arsnova.persistance.SessionRepository;
import de.thm.arsnova.persistance.UserRepository;
import de.thm.arsnova.persistance.couchdb.CouchDbCommentRepository;
import de.thm.arsnova.persistance.couchdb.CouchDbContentRepository;
import de.thm.arsnova.persistance.couchdb.CouchDbLogEntryRepository;
import de.thm.arsnova.persistance.couchdb.CouchDbMotdRepository;
import de.thm.arsnova.persistance.couchdb.CouchDbSessionRepository;
......@@ -300,6 +303,11 @@ public class AppConfig extends WebMvcConfigurerAdapter {
return new CouchDbCommentRepository(Comment.class, couchDbConnector(), false);
}
@Bean
public ContentRepository contentRepository() throws Exception {
return new CouchDbContentRepository(Content.class, couchDbConnector(), false);
}
@Bean
public UserRepository userRepository() throws Exception {
return new CouchDbUserRepository(DbUser.class, couchDbConnector(), false);
......
......@@ -20,7 +20,7 @@ package de.thm.arsnova.controller;
import de.thm.arsnova.entities.CommentReadingCount;
import de.thm.arsnova.entities.transport.Comment;
import de.thm.arsnova.exceptions.BadRequestException;
import de.thm.arsnova.services.IQuestionService;
import de.thm.arsnova.services.IContentService;
import de.thm.arsnova.web.DeprecatedApi;
import de.thm.arsnova.web.Pagination;
import io.swagger.annotations.Api;
......@@ -45,11 +45,11 @@ import java.util.List;
*/
@RestController
@RequestMapping("/audiencequestion")
@Api(value = "/audiencequestion", description = "the Audience Question API")
@Api(value = "/audiencequestion", description = "the Audience Content API")
public class CommentController extends PaginationController {
@Autowired
private IQuestionService questionService;
private IContentService contentService;
@ApiOperation(value = "Count all the comments in current session",
nickname = "getAudienceQuestionCount")
......@@ -57,7 +57,7 @@ public class CommentController extends PaginationController {
@DeprecatedApi
@Deprecated
public int getInterposedCount(@ApiParam(value = "Session-Key from current session", required = true) @RequestParam final String sessionkey) {
return questionService.getInterposedCount(sessionkey);
return contentService.getInterposedCount(sessionkey);
}
@ApiOperation(value = "count all unread comments",
......@@ -66,7 +66,7 @@ public class CommentController extends PaginationController {
@DeprecatedApi
@Deprecated
public CommentReadingCount getUnreadInterposedCount(@ApiParam(value = "Session-Key from current session", required = true) @RequestParam("sessionkey") final String sessionkey, String user) {
return questionService.getInterposedReadingCount(sessionkey, user);
return contentService.getInterposedReadingCount(sessionkey, user);
}
@ApiOperation(value = "Retrieves all Comments for a Session",
......@@ -74,14 +74,14 @@ public class CommentController extends PaginationController {
@RequestMapping(value = "/", method = RequestMethod.GET)
@Pagination
public List<Comment> getInterposedQuestions(@ApiParam(value = "Session-Key from current session", required = true) @RequestParam final String sessionkey) {
return Comment.fromList(questionService.getInterposedQuestions(sessionkey, offset, limit));
return Comment.fromList(contentService.getInterposedQuestions(sessionkey, offset, limit));
}
@ApiOperation(value = "Retrieves an Comment",
nickname = "getInterposedQuestion")
@RequestMapping(value = "/{questionId}", method = RequestMethod.GET)
public Comment getInterposedQuestion(@ApiParam(value = "ID of the Comment that needs to be deleted", required = true) @PathVariable final String questionId) {
return new Comment(questionService.readInterposedQuestion(questionId));
return new Comment(contentService.readInterposedQuestion(questionId));
}
@ApiOperation(value = "Creates a new Comment for a Session and returns the Comment's data",
......@@ -95,7 +95,7 @@ public class CommentController extends PaginationController {
@ApiParam(value = "Session-Key from current session", required = true) @RequestParam final String sessionkey,
@ApiParam(value = "the body from the new comment", required = true) @RequestBody final de.thm.arsnova.entities.Comment comment
) {
if (questionService.saveQuestion(comment)) {
if (contentService.saveQuestion(comment)) {
return;
}
......@@ -106,6 +106,6 @@ public class CommentController extends PaginationController {
nickname = "deleteInterposedQuestion")
@RequestMapping(value = "/{questionId}", method = RequestMethod.DELETE)
public void deleteInterposedQuestion(@ApiParam(value = "ID of the comment that needs to be deleted", required = true) @PathVariable final String questionId) {
questionService.deleteInterposedQuestion(questionId);
contentService.deleteInterposedQuestion(questionId);
}
}
......@@ -17,7 +17,7 @@
*/
package de.thm.arsnova.controller;
import de.thm.arsnova.services.IQuestionService;
import de.thm.arsnova.services.IContentService;
import de.thm.arsnova.web.DeprecatedApi;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
......@@ -33,7 +33,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
public class LegacyController extends AbstractController {
@Autowired
private IQuestionService questionService;
private IContentService contentService;
/* specific routes */
......@@ -95,7 +95,7 @@ public class LegacyController extends AbstractController {
@RequestMapping(value = "/session/{sessionKey}/interposed", method = RequestMethod.DELETE)
@ResponseBody
public void deleteAllInterposedQuestions(@PathVariable final String sessionKey) {
questionService.deleteAllInterposedQuestions(sessionKey);
contentService.deleteAllInterposedQuestions(sessionKey);
}
@DeprecatedApi
......
......@@ -26,35 +26,17 @@ import java.util.List;
* All methods the database must support.
*/
public interface IDatabaseDao {
Question saveQuestion(Session session, Question question);
Question getQuestion(String id);
List<Question> getSkillQuestionsForUsers(Session session);
List<Question> getSkillQuestionsForTeachers(Session session);
int getSkillQuestionCount(Session session);
List<String> getQuestionIds(Session session, User user);
int deleteQuestionWithAnswers(Question question);
int[] deleteAllQuestionsWithAnswers(Session session);
List<String> getUnAnsweredQuestionIds(Session session, User user);
Answer getMyAnswer(User me, String questionId, int piRound);
List<Answer> getAnswers(Question question, int piRound);
List<Answer> getAnswers(Content content, int piRound);
List<Answer> getAnswers(Question question);
List<Answer> getAnswers(Content content);
List<Answer> getAllAnswers(Question question);
List<Answer> getAllAnswers(Content content);
int getAnswerCount(Question question, int piRound);
int getAnswerCount(Content content, int piRound);
int getTotalAnswerCountByQuestion(Question question);
int getTotalAnswerCountByQuestion(Content content);
int getAbstentionAnswerCount(String questionId);
......@@ -64,11 +46,9 @@ public interface IDatabaseDao {
int getTotalAnswerCount(String sessionKey);
Question updateQuestion(Question question);
int deleteAnswers(Content content);
int deleteAnswers(Question question);
Answer saveAnswer(Answer answer, User user, Question question, Session session);
Answer saveAnswer(Answer answer, User user, Content content, Session session);
Answer updateAnswer(Answer answer);
......@@ -76,44 +56,10 @@ public interface IDatabaseDao {
int deleteInactiveGuestVisitedSessionLists(long lastActivityBefore);
List<Question> getLectureQuestionsForUsers(Session session);
List<Question> getLectureQuestionsForTeachers(Session session);
List<Question> getFlashcardsForUsers(Session session);
List<Question> getFlashcardsForTeachers(Session session);
List<Question> getPreparationQuestionsForUsers(Session session);
List<Question> getPreparationQuestionsForTeachers(Session session);
List<Question> getAllSkillQuestions(Session session);
int getLectureQuestionCount(Session session);
int getFlashcardCount(Session session);
int getPreparationQuestionCount(Session session);
int countLectureQuestionAnswers(Session session);
int countPreparationQuestionAnswers(Session session);
int[] deleteAllLectureQuestionsWithAnswers(Session session);
int[] deleteAllFlashcardsWithAnswers(Session session);
int[] deleteAllPreparationQuestionsWithAnswers(Session session);
List<String> getUnAnsweredLectureQuestionIds(Session session, User user);
List<String> getUnAnsweredPreparationQuestionIds(Session session, User user);
void publishQuestions(Session session, boolean publish, List<Question> questions);
List<Question> publishAllQuestions(Session session, boolean publish);
int deleteAllQuestionsAnswers(Session session);
CourseScore getLearningProgress(Session session);
......@@ -124,21 +70,11 @@ public interface IDatabaseDao {
Statistics getStatistics();
List<String> getSubjects(Session session, String questionVariant);
List<String> getQuestionIdsBySubject(Session session, String questionVariant, String subject);
List<Question> getQuestionsByIds(List<String> ids, Session session);
void resetQuestionsRoundState(Session session, List<Question> questions);
void setVotingAdmissions(Session session, boolean disableVoting, List<Question> questions);
List<Question> setVotingAdmissionForAllQuestions(Session session, boolean disableVoting);
<T> T getObjectFromId(String documentId, Class<T> klass);
MotdList getMotdListForUser(final String username);
MotdList createOrUpdateMotdList(MotdList motdlist);
int[] deleteAllAnswersWithQuestions(List<Content> contents);
}
......@@ -17,20 +17,21 @@
*/
package de.thm.arsnova.entities;
import com.fasterxml.jackson.annotation.JsonView;
import de.thm.arsnova.entities.serialization.View;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* A question the teacher is asking.
*/
@ApiModel(value = "lecturerquestion", description = "the question entity")
public class Question implements Serializable {
private String type;
@ApiModel(value = "content", description = "the content entity")
public class Content implements Entity {
private String id;
private String rev;
private String questionType;
private String questionVariant;
private String subject;
......@@ -62,8 +63,6 @@ public class Question implements Serializable {
private boolean strictMode;
private int rating;
private String correctAnswer;
private String _id;
private String _rev;
private String image;
private String fcImage;
......@@ -92,56 +91,78 @@ public class Question implements Serializable {
private String hint;
private String solution;
@ApiModelProperty(required = true, value = "the type")
public final String getType() {
return type;
@ApiModelProperty(required = true, value = "the couchDB ID")
@JsonView({View.Persistence.class, View.Public.class})
public String getId() {
return id;
}
@JsonView({View.Persistence.class, View.Public.class})
public void setId(final String id) {
this.id = id;
}
@JsonView({View.Persistence.class, View.Public.class})
public void setRevision(final String rev) {
this.rev = rev;
}
public final void setType(final String type) {
this.type = type;
@JsonView({View.Persistence.class, View.Public.class})
public String getRevision() {
return rev;
}
@ApiModelProperty(required = true, value = "the question type")
@JsonView({View.Persistence.class, View.Public.class})
public final String getQuestionType() {
return questionType;
}
@JsonView({View.Persistence.class, View.Public.class})
public final void setQuestionType(final String questionType) {
this.questionType = questionType;
}
@ApiModelProperty(required = true, value = "either lecture or preparation")
@JsonView({View.Persistence.class, View.Public.class})
public final String getQuestionVariant() {
return questionVariant;
}
@JsonView({View.Persistence.class, View.Public.class})
public final void setQuestionVariant(final String questionVariant) {
this.questionVariant = questionVariant;
}
@ApiModelProperty(required = true, value = "used to display subject")
@JsonView({View.Persistence.class, View.Public.class})
public final String getSubject() {
return subject;
}
@JsonView({View.Persistence.class, View.Public.class})
public final void setSubject(final String subject) {
this.subject = subject;
}
@ApiModelProperty(required = true, value = "the text")
@JsonView({View.Persistence.class, View.Public.class})
public final String getText() {
return text;
}
@JsonView({View.Persistence.class, View.Public.class})
public final void setText(final String text) {
this.text = text;
}
@ApiModelProperty(required = true, value = "true for active question")
@JsonView({View.Persistence.class, View.Public.class})
public final boolean isActive() {
return active;
}
@JsonView({View.Persistence.class, View.Public.class})
public final void setActive(final boolean active) {
this.active = active;
}
......@@ -156,10 +177,12 @@ public class Question implements Serializable {
}
@ApiModelProperty(required = true, value = "list of possible answers")
@JsonView({View.Persistence.class, View.Public.class})
public final List<PossibleAnswer> getPossibleAnswers() {
return possibleAnswers;
}
@JsonView({View.Persistence.class, View.Public.class})
public final void setPossibleAnswers(final List<PossibleAnswer> possibleAnswers) {
this.possibleAnswers = possibleAnswers;
}
......@@ -174,10 +197,12 @@ public class Question implements Serializable {
}
@ApiModelProperty(required = true, value = "couchDB ID of the session, the question is assigned to")
@JsonView({View.Persistence.class, View.Public.class})
public final String getSessionId() {
return sessionId;
}
@JsonView({View.Persistence.class, View.Public.class})
public final void setSessionId(final String sessionId) {
this.sessionId = sessionId;
}
......@@ -201,10 +226,12 @@ public class Question implements Serializable {
}
@ApiModelProperty(required = true, value = "creation date timestamp")
@JsonView(View.Persistence.class)
public final long getTimestamp() {
return timestamp;
}
@JsonView(View.Persistence.class)
public final void setTimestamp(final long timestamp) {
this.timestamp = timestamp;
}
......@@ -219,46 +246,56 @@ public class Question implements Serializable {
}
@ApiModelProperty(required = true, value = "used to display duration")
@JsonView({View.Persistence.class, View.Public.class})
public final int getDuration() {
return duration;
}
@JsonView({View.Persistence.class, View.Public.class})
public final void setDuration(final int duration) {
this.duration = duration;
}
@ApiModelProperty(required = true, value = "true for image question")
@JsonView({View.Persistence.class, View.Public.class})
public final boolean isImageQuestion() {
return imageQuestion;
}
@JsonView({View.Persistence.class, View.Public.class})
public void setImageQuestion(boolean imageQuestion) {
this.imageQuestion = imageQuestion;
}
public final void setDuration(final int duration) {
this.duration = duration;
}
@ApiModelProperty(required = true, value = "the peer instruction round no.")
@JsonView({View.Persistence.class, View.Public.class})
public int getPiRound() {
return piRound;
}
@JsonView({View.Persistence.class, View.Public.class})
public void setPiRound(final int piRound) {
this.piRound = piRound;
}
@ApiModelProperty(required = true, value = "the peer instruction round end timestamp")
@JsonView({View.Persistence.class, View.Public.class})
public long getPiRoundEndTime() {
return piRoundEndTime;
}
@JsonView({View.Persistence.class, View.Public.class})
public void setPiRoundEndTime(long piRoundEndTime) {
this.piRoundEndTime = piRoundEndTime;
}
@ApiModelProperty(required = true, value = "the peer instruction round start timestamp")
@JsonView({View.Persistence.class, View.Public.class})
public long getPiRoundStartTime() {
return piRoundStartTime;
}
@JsonView({View.Persistence.class, View.Public.class})
public void setPiRoundStartTime(long piRoundStartTime) {
this.piRoundStartTime = piRoundStartTime;
}
......@@ -282,340 +319,395 @@ public class Question implements Serializable {
}
@ApiModelProperty(required = true, value = "used to display showStatistic")
@JsonView({View.Persistence.class, View.Public.class})
public boolean isShowStatistic() {
return showStatistic;
}
@JsonView({View.Persistence.class, View.Public.class})
public void setShowStatistic(final boolean showStatistic) {
this.showStatistic = showStatistic;
}
@ApiModelProperty(required = true, value = "used to display cvIsColored")
@JsonView({View.Persistence.class, View.Public.class})
public boolean getCvIsColored() {
return cvIsColored;
}
@JsonView({View.Persistence.class, View.Public.class})
public void setCvIsColored(boolean cvIsColored) {
this.cvIsColored = cvIsColored;
}
@ApiModelProperty(required = true, value = "used to display showAnswer")
@JsonView({View.Persistence.class, View.Public.class})
public boolean isShowAnswer() {
return showAnswer;
}
@JsonView({View.Persistence.class, View.Public.class})
public void setShowAnswer(final boolean showAnswer) {
this.showAnswer = showAnswer;
}
@ApiModelProperty(required = true, value = "used to display abstention")
@JsonView({View.Persistence.class, View.Public.class})
public boolean isAbstention() {
return abstention;
}
@JsonView({View.Persistence.class, View.Public.class})
public void setAbstention(final boolean abstention) {
this.abstention = abstention;
}
@JsonView({View.Persistence.class, View.Public.class})
public boolean isIgnoreCaseSensitive() {
return ignoreCaseSensitive;
}
@JsonView({View.Persistence.class, View.Public.class})
public void setIgnoreCaseSensitive(final boolean ignoreCaseSensitive) {
this.ignoreCaseSensitive = ignoreCaseSensitive;
}
@JsonView({View.Persistence.class, View.Public.class})
public boolean isIgnoreWhitespaces() {
return ignoreWhitespaces;
}
@JsonView({View.Persistence.class, View.Public.class})
public void setIgnoreWhitespaces(final boolean ignoreWhitespaces) {
this.ignoreWhitespaces = ignoreWhitespaces;
}
@JsonView({View.Persistence.class, View.Public.class})
public boolean isIgnorePunctuation() {
return ignorePunctuation;
}
@JsonView({View.Persistence.class, View.Public.class})
public void setIgnorePunctuation(final boolean ignorePunctuation) {
this.ignorePunctuation = ignorePunctuation;
}
@JsonView({View.Persistence.class, View.Public.class})
public boolean isFixedAnswer() {
return this.fixedAnswer;
}
@JsonView({View.Persistence.class, View.Public.class})
public void setFixedAnswer(final boolean fixedAnswer) {
this.fixedAnswer = fixedAnswer;
}
@JsonView({View.Persistence.class, View.Public.class})
public boolean isStrictMode() {
return this.strictMode;
}
@JsonView({View.Persistence.class, View.Public.class})
public void setStrictMode(final boolean strictMode) {
this.strictMode = strictMode;
}
@JsonView({View.Persistence.class, View.Public.class})
public final int getRating() {
return this.rating;
}
@JsonView({View.Persistence.class, View.Public.class})
public final void setRating(final int rating) {
this.rating = rating;
}
@JsonView({View.Persistence.class, View.Public.class})
public final String getCorrectAnswer() {
return correctAnswer;
}
@JsonView({View.Persistence.class, View.Public.class})
public final void setCorrectAnswer(final String correctAnswer) {
this.correctAnswer = correctAnswer;
}
@ApiModelProperty(required = true, value = "the couchDB ID")
public final String get_id() {