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,6 +17,8 @@
*/
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;
......@@ -43,28 +45,34 @@ public class PossibleAnswer implements Serializable {
}
@ApiModelProperty(required = true, value = "the text")
@JsonView({View.Persistence.class, View.Public.class})
public String getText() {
return text;
}
@JsonView({View.Persistence.class, View.Public.class})
public void setText(String text) {
this.text = text;
}
@ApiModelProperty(required = true, value = "true for a correct answer")
@JsonView({View.Persistence.class, View.Public.class})
public boolean isCorrect() {
return correct;
}
@JsonView({View.Persistence.class, View.Public.class})
public void setCorrect(boolean correct) {
this.correct = correct;
}
@ApiModelProperty(required = true, value = "the value")
@JsonView({View.Persistence.class, View.Public.class})
public int getValue() {
return value;
}
@JsonView({View.Persistence.class, View.Public.class})
public void setValue(int value) {
this.value = value;
}
......
......@@ -25,6 +25,7 @@ import de.thm.arsnova.entities.DbUser;
import de.thm.arsnova.entities.Entity;
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 java.util.HashMap;
......@@ -39,6 +40,7 @@ public class CouchDbTypeFieldConverter implements Converter<Class<? extends Enti
typeMapping.put(Motd.class, "motd");
typeMapping.put(Session.class, "session");
typeMapping.put(Comment.class, "interposed_question");
typeMapping.put(Content.class, "skill_question");
}
@Override
......
......@@ -19,7 +19,7 @@ package de.thm.arsnova.entities.transport;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonView;
import de.thm.arsnova.entities.Question;
import de.thm.arsnova.entities.Content;
import de.thm.arsnova.entities.User;
import de.thm.arsnova.entities.serialization.View;
import io.swagger.annotations.ApiModel;
......@@ -126,28 +126,28 @@ public class Answer implements Serializable {
this.abstention = abstention;
}
public de.thm.arsnova.entities.Answer generateAnswerEntity(final User user, final Question question) {
public de.thm.arsnova.entities.Answer generateAnswerEntity(final User user, final Content content) {
// rewrite all fields so that no manipulated data gets written
// only answerText, answerSubject, and abstention are allowed
de.thm.arsnova.entities.Answer theAnswer = new de.thm.arsnova.entities.Answer();
theAnswer.setAnswerSubject(this.getAnswerSubject());
theAnswer.setAnswerText(this.getAnswerText());
theAnswer.setAnswerTextRaw(this.getAnswerTextRaw());
theAnswer.setSessionId(question.getSessionId());
theAnswer.setSessionId(content.getSessionId());
theAnswer.setUser(user.getUsername());
theAnswer.setQuestionId(question.get_id());
theAnswer.setQuestionId(content.getId());
theAnswer.setTimestamp(new Date().getTime());
theAnswer.setQuestionVariant(question.getQuestionVariant());
theAnswer.setQuestionVariant(content.getQuestionVariant());
theAnswer.setAbstention(this.isAbstention());
// calculate learning progress value after all properties are set
theAnswer.setQuestionValue(question.calculateValue(theAnswer));
theAnswer.setQuestionValue(content.calculateValue(theAnswer));
theAnswer.setAnswerImage(this.getAnswerImage());
theAnswer.setSuccessfulFreeTextAnswer(this.isSuccessfulFreeTextAnswer());
if ("freetext".equals(question.getQuestionType())) {
if ("freetext".equals(content.getQuestionType())) {
theAnswer.setPiRound(0);
} else {
theAnswer.setPiRound(question.getPiRound());
theAnswer.setPiRound(content.getPiRound());
}
return theAnswer;
......
......@@ -18,7 +18,7 @@
package de.thm.arsnova.entities.transport;
import de.thm.arsnova.entities.Answer;
import de.thm.arsnova.entities.Question;
import de.thm.arsnova.entities.Content;
import de.thm.arsnova.entities.Session;
import de.thm.arsnova.entities.User;
......@@ -30,15 +30,15 @@ public class AnswerQueueElement {
private final Session session;
private final Question question;
private final Content content;
private final Answer answer;
private final User user;
public AnswerQueueElement(Session session, Question question, Answer answer, User user) {
public AnswerQueueElement(Session session, Content content, Answer answer, User user) {
this.session = session;
this.question = question;
this.content = content;
this.answer = answer;
this.user = user;
}
......@@ -47,8 +47,8 @@ public class AnswerQueueElement {
return session;
}
public Question getQuestion() {
return question;
public Content getQuestion() {
return content;
}
public Answer getAnswer() {
......
......@@ -18,8 +18,8 @@
package de.thm.arsnova.entities.transport;
import com.fasterxml.jackson.annotation.JsonView;
import de.thm.arsnova.entities.Content;
import de.thm.arsnova.entities.Motd;
import de.thm.arsnova.entities.Question;
import de.thm.arsnova.entities.Session;
import de.thm.arsnova.entities.SessionFeature;
import de.thm.arsnova.entities.SessionInfo;
......@@ -40,7 +40,7 @@ public class ImportExportSession {
private ImportExportSesssion session;
private List<ImportExportQuestion> questions;
private List<ImportExportContent> questions;
private List<Comment> feedbackQuestions;
......@@ -69,11 +69,11 @@ public class ImportExportSession {
@ApiModelProperty(required = true, value = "used to display questions")
@JsonView(View.Public.class)
public List<ImportExportQuestion> getQuestions() {
public List<ImportExportContent> getQuestions() {
return questions;
}
public void setQuestions(List<ImportExportQuestion> questions) {
public void setQuestions(List<ImportExportContent> questions) {
this.questions = questions;
}
......@@ -126,8 +126,8 @@ public class ImportExportSession {
session = iesession;
}
public void addQuestionWithAnswers(Question q, List<Answer> aL) {
ImportExportQuestion ieq = new ImportExportQuestion(q);
public void addQuestionWithAnswers(Content q, List<Answer> aL) {
ImportExportContent ieq = new ImportExportContent(q);
ieq.setAnswers(aL);
questions.add(ieq);
}
......@@ -158,16 +158,15 @@ public class ImportExportSession {
return s;
}
public static class ImportExportQuestion extends Question {
public static class ImportExportContent extends Content {
private List<Answer> answers;
public ImportExportQuestion() {
public ImportExportContent() {
}
public ImportExportQuestion(Question q) {
setType(q.getType());
public ImportExportContent(Content q) {
setQuestionType(q.getQuestionType());
setQuestionVariant(q.getQuestionVariant());
setSubject(q.getSubject());
......
......@@ -17,7 +17,7 @@
*/
package de.thm.arsnova.events;
import de.thm.arsnova.entities.Question;
import de.thm.arsnova.entities.Content;
import de.thm.arsnova.entities.Session;
/**
......@@ -27,11 +27,11 @@ public class DeleteAnswerEvent extends SessionEvent {
private static final long serialVersionUID = 1L;
private final Question question;
private final Content content;
public DeleteAnswerEvent(Object source, Session session, Question question) {
public DeleteAnswerEvent(Object source, Session session, Content content) {
super(source, session);
this.question = question;
this.content = content;
}
@Override
......@@ -39,7 +39,7 @@ public class DeleteAnswerEvent extends SessionEvent {
visitor.visit(this);
}
public Question getQuestion() {
return question;
public Content getQuestion() {
return content;
}
}
......@@ -17,25 +17,25 @@
*/
package de.thm.arsnova.events;
import de.thm.arsnova.entities.Question;
import de.thm.arsnova.entities.Content;
import de.thm.arsnova.entities.Session;
/**
* Fires whenever a question is deleted.
* Fires whenever a content is deleted.
*/
public class DeleteQuestionEvent extends SessionEvent {
private static final long serialVersionUID = 1L;
private final Question question;
private final Content content;
public DeleteQuestionEvent(Object source, Session session, Question question) {
public DeleteQuestionEvent(Object source, Session session, Content content) {
super(source, session);
this.question = question;
this.content = content;
}
public Question getQuestion() {
return this.question;
public Content getQuestion() {
return this.content;
}
@Override
......
......@@ -17,25 +17,25 @@
*/
package de.thm.arsnova.events;
import de.thm.arsnova.entities.Question;
import de.thm.arsnova.entities.Content;
import de.thm.arsnova.entities.Session;
/**
* Fires whenever a question is disabled, i.e., it is hidden from students.
* Fires whenever a content is disabled, i.e., it is hidden from students.
*/
public class LockQuestionEvent extends SessionEvent {
private static final long serialVersionUID = 1L;
private final Question question;
private final Content content;
public LockQuestionEvent(Object source, Session session, Question question) {
public LockQuestionEvent(Object source, Session session, Content content) {
super(source, session);
this.question = question;
this.content = content;
}
public Question getQuestion() {
return this.question;
public Content getQuestion() {
return this.content;
}
@Override
......
......@@ -17,27 +17,27 @@
*/
package de.thm.arsnova.events;
import de.thm.arsnova.entities.Question;
import de.thm.arsnova.entities.Content;
import de.thm.arsnova.entities.Session;
import java.util.List;
/**
* Fires whenever a set of questions are disabled, i.e., they are hidden from students.
* Fires whenever a set of contents are disabled, i.e., they are hidden from students.
*/
public class LockQuestionsEvent extends SessionEvent {
private static final long serialVersionUID = 1L;
private List<Question> questions;
private List<Content> contents;
public LockQuestionsEvent(Object source, Session session, List<Question> questions) {
public LockQuestionsEvent(Object source, Session session, List<Content> contents) {
super(source, session);
this.questions = questions;
this.contents = contents;
}
public List<Question> getQuestions() {
return this.questions;
public List<Content> getQuestions() {
return this.contents;
}
@Override
......
......@@ -17,36 +17,36 @@
*/
package de.thm.arsnova.events;
import de.thm.arsnova.entities.Question;
import de.thm.arsnova.entities.Content;
import de.thm.arsnova.entities.Session;
import java.util.HashMap;
import java.util.Map;
/**
* Fires whenever voting on a question is disabled.
* Fires whenever voting on a content is disabled.
*/
public class LockVoteEvent extends SessionEvent {
private static final long serialVersionUID = 1L;
private final Question question;
private final Content content;
public LockVoteEvent(Object source, Session session, Question question) {
public LockVoteEvent(Object source, Session session, Content content) {
super(source, session);
this.question = question;
this.content = content;
}
public String getQuestionId() {
return this.question.get_id();
return this.content.getId();
}
public String getQuestionVariant() {
return this.question.getQuestionVariant();
return this.content.getQuestionVariant();
}
public Boolean getVotingDisabled() {
return this.question.isVotingDisabled();
return this.content.isVotingDisabled();
}
public Map<String, Object> getVotingAdmission() {
......
......@@ -17,27 +17,27 @@
*/
package de.thm.arsnova.events;
import de.thm.arsnova.entities.Question;
import de.thm.arsnova.entities.Content;
import de.thm.arsnova.entities.Session;
import java.util.List;
/**
* Fires whenever voting of multiple questions is disabled.
* Fires whenever voting of multiple contents is disabled.
*/
public class LockVotesEvent extends SessionEvent {
private static final long serialVersionUID = 1L;
private List<Question> questions;
private List<Content> contents;
public LockVotesEvent(Object source, Session session, List<Question> questions) {
public LockVotesEvent(Object source, Session session, List<Content> contents) {
super(source, session);
this.questions = questions;
this.contents = contents;