GitLab wurde erfolgreich aktualisiert. Dank regelmäßiger Updates bleibt das THM GitLab sicher und Sie profitieren von den neuesten Funktionen. Danke für Ihre Geduld.

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;
}