From 4c42a532b548ee0a2b6929ec60af8965a746936c Mon Sep 17 00:00:00 2001
From: Christoph Thelen <christoph.thelen@mni.thm.de>
Date: Mon, 16 Feb 2015 13:00:38 +0100
Subject: [PATCH] Cache all question variants for users

---
 .../java/de/thm/arsnova/dao/CouchDBDao.java   | 102 +++++++++++++++++-
 .../java/de/thm/arsnova/dao/IDatabaseDao.java |  44 ++++++++
 .../thm/arsnova/services/QuestionService.java |  34 +++++-
 3 files changed, 173 insertions(+), 7 deletions(-)

diff --git a/src/main/java/de/thm/arsnova/dao/CouchDBDao.java b/src/main/java/de/thm/arsnova/dao/CouchDBDao.java
index c1b7c41b..e6699bee 100644
--- a/src/main/java/de/thm/arsnova/dao/CouchDBDao.java
+++ b/src/main/java/de/thm/arsnova/dao/CouchDBDao.java
@@ -41,6 +41,7 @@ import org.springframework.beans.factory.annotation.Value;
 import org.springframework.cache.annotation.CacheEvict;
 import org.springframework.cache.annotation.CachePut;
 import org.springframework.cache.annotation.Cacheable;
+import org.springframework.cache.annotation.Caching;
 import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Isolation;
 import org.springframework.transaction.annotation.Transactional;
@@ -346,6 +347,12 @@ public class CouchDBDao implements IDatabaseDao {
 		return sessionInfos;
 	}
 
+	/**
+	 * @deprecated The decision to load data depending on the user should be made by a service class, not this
+	 * database class. Please use getSkillQuestionsForUsers or getSkillQuestionsForTeachers as this will enable
+	 * caching.
+	 */
+	@Deprecated
 	@Override
 	public final List<Question> getSkillQuestions(final User user, final Session session) {
 		String viewName;
@@ -357,6 +364,20 @@ public class CouchDBDao implements IDatabaseDao {
 		return getQuestions(new NovaView(viewName), session);
 	}
 
+	@Cacheable("skillquestions")
+	@Override
+	public final List<Question> getSkillQuestionsForUsers(final Session session) {
+		String viewName = "skill_question/by_session_for_all_full";
+		return getQuestions(new NovaView(viewName), session);
+	}
+
+	@Cacheable("skillquestions")
+	@Override
+	public final List<Question> getSkillQuestionsForTeachers(final Session session) {
+		String viewName = "skill_question/by_session_sorted_by_subject_and_text";
+		return getQuestions(new NovaView(viewName), session);
+	}
+
 	@Override
 	public final int getSkillQuestionCount(final Session session) {
 		return getQuestionCount(new NovaView("skill_question/count_by_session"), session);
@@ -709,7 +730,11 @@ public class CouchDBDao implements IDatabaseDao {
 		return collectQuestionIds(view);
 	}
 
-	@CacheEvict(value = "questions")
+	@Caching(evict = { @CacheEvict("questions"),
+			@CacheEvict(value = "skillquestions", allEntries = true),
+			@CacheEvict(value = "lecturequestions", allEntries = true),
+			@CacheEvict(value = "preparationquestions", allEntries = true),
+			@CacheEvict(value = "flashcardquestions", allEntries = true) })
 	@Override
 	public final void deleteQuestionWithAnswers(final Question question) {
 		try {
@@ -720,6 +745,11 @@ public class CouchDBDao implements IDatabaseDao {
 		}
 	}
 
+	@Caching(evict = { @CacheEvict("questions"),
+			@CacheEvict(value = "skillquestions", allEntries = true),
+			@CacheEvict(value = "lecturequestions", allEntries = true),
+			@CacheEvict(value = "preparationquestions", allEntries = true),
+			@CacheEvict(value = "flashcardquestions", allEntries = true) })
 	@Override
 	public final void deleteAllQuestionsWithAnswers(final Session session) {
 		final NovaView view = new NovaView("skill_question/by_session");
@@ -1313,6 +1343,12 @@ public class CouchDBDao implements IDatabaseDao {
 		}
 	}
 
+	/**
+	 * @deprecated The decision to load data depending on the user should be made by a service class, not this
+	 * database class. Please use getLectureQuestionsForUsers or getLectureQuestionsForTeachers as this will enable
+	 * caching.
+	 */
+	@Deprecated
 	@Override
 	public List<Question> getLectureQuestions(final User user, final Session session) {
 		String viewName;
@@ -1324,6 +1360,24 @@ public class CouchDBDao implements IDatabaseDao {
 		return getQuestions(new NovaView(viewName), session);
 	}
 
+	@Cacheable("lecturequestions")
+	@Override
+	public List<Question> getLectureQuestionsForUsers(final Session session) {
+		String viewName = "skill_question/lecture_question_by_session_for_all";
+		return getQuestions(new NovaView(viewName), session);
+	}
+
+	@Override
+	public List<Question> getLectureQuestionsForTeachers(final Session session) {
+		String viewName = "skill_question/lecture_question_by_session";
+		return getQuestions(new NovaView(viewName), session);
+	}
+
+	/**
+	 * @deprecated The decision to load data depending on the user should be made by a service class, not this
+	 * database class. Please use getFlashcardsForUsers or getFlashcardsForTeachers as this will enable caching.
+	 */
+	@Deprecated
 	@Override
 	public List<Question> getFlashcards(final User user, final Session session) {
 		String viewName;
@@ -1335,6 +1389,25 @@ public class CouchDBDao implements IDatabaseDao {
 		return getQuestions(new NovaView(viewName), session);
 	}
 
+	@Cacheable("flashcardquestions")
+	@Override
+	public List<Question> getFlashcardsForUsers(final Session session) {
+		String viewName = "skill_question/flashcard_by_session_for_all";
+		return getQuestions(new NovaView(viewName), session);
+	}
+
+	@Override
+	public List<Question> getFlashcardsForTeachers(final Session session) {
+		String viewName = "skill_question/flashcard_by_session";
+		return getQuestions(new NovaView(viewName), session);
+	}
+
+	/**
+	 * @deprecated The decision to load data depending on the user should be made by a service class, not this
+	 * database class. Please use getPreparationQuestionsForUsers or getPreparationQuestionsForTeachers as this will enable
+	 * caching.
+	 */
+	@Deprecated
 	@Override
 	public List<Question> getPreparationQuestions(final User user, final Session session) {
 		String viewName;
@@ -1344,7 +1417,19 @@ public class CouchDBDao implements IDatabaseDao {
 			viewName = "skill_question/preparation_question_by_session_for_all";
 		}
 		return getQuestions(new NovaView(viewName), session);
+	}
+
+	@Cacheable("preparationquestions")
+	@Override
+	public List<Question> getPreparationQuestionsForUsers(final Session session) {
+		String viewName = "skill_question/preparation_question_by_session_for_all";
+		return getQuestions(new NovaView(viewName), session);
+	}
 
+	@Override
+	public List<Question> getPreparationQuestionsForTeachers(final Session session) {
+		String viewName = "skill_question/preparation_question_by_session";
+		return getQuestions(new NovaView(viewName), session);
 	}
 
 	private List<Question> getQuestions(final NovaView view, final Session session) {
@@ -1425,18 +1510,27 @@ public class CouchDBDao implements IDatabaseDao {
 		return results.getJSONArray("rows").optJSONObject(0).optInt("value");
 	}
 
+	@Caching(evict = { @CacheEvict(value = "questions", allEntries = true),
+			@CacheEvict(value = "skillquestions", allEntries = true),
+			@CacheEvict("lecturequestions") })
 	@Override
 	public void deleteAllLectureQuestionsWithAnswers(final Session session) {
 		final NovaView view = new NovaView("skill_question/lecture_question_by_session");
 		deleteAllQuestionDocumentsWithAnswers(session, view);
 	}
 
+	@Caching(evict = { @CacheEvict(value = "questions", allEntries = true),
+			@CacheEvict(value = "skillquestions", allEntries = true),
+			@CacheEvict("flashcardquestions") })
 	@Override
 	public void deleteAllFlashcardsWithAnswers(final Session session) {
 		final NovaView view = new NovaView("skill_question/flashcard_by_session");
 		deleteAllQuestionDocumentsWithAnswers(session, view);
 	}
 
+	@Caching(evict = { @CacheEvict(value = "questions", allEntries = true),
+			@CacheEvict(value = "skillquestions", allEntries = true),
+			@CacheEvict("preparationquestions") })
 	@Override
 	public void deleteAllPreparationQuestionsWithAnswers(final Session session) {
 		final NovaView view = new NovaView("skill_question/preparation_question_by_session");
@@ -1538,7 +1632,11 @@ public class CouchDBDao implements IDatabaseDao {
 		publishQuestions(session, publish, questions);
 	}
 
-	@CacheEvict(value = "questions", allEntries = true)
+	@Caching(evict = { @CacheEvict(value = "questions", allEntries = true),
+			@CacheEvict(value = "skillquestions", allEntries = true),
+			@CacheEvict(value = "lecturequestions", allEntries = true),
+			@CacheEvict(value = "preparationquestions", allEntries = true),
+			@CacheEvict(value = "flashcardquestions", allEntries = true) })
 	@Override
 	public void publishQuestions(final Session session, final boolean publish, List<Question> questions) {
 		for (final Question q : questions) {
diff --git a/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java b/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java
index 9944d347..8695dee2 100644
--- a/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java
+++ b/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java
@@ -59,8 +59,19 @@ public interface IDatabaseDao {
 
 	Question getQuestion(String id);
 
+	/**
+	 * @deprecated Use getSkillQuestionsForUsers or getSkillQuestionsForTeachers
+	 * @param user
+	 * @param session
+	 * @return
+	 */
+	@Deprecated
 	List<Question> getSkillQuestions(User user, Session session);
 
+	List<Question> getSkillQuestionsForUsers(Session session);
+
+	List<Question> getSkillQuestionsForTeachers(Session session);
+
 	int getSkillQuestionCount(Session session);
 
 	LoggedIn registerAsOnlineUser(User u, Session s);
@@ -135,12 +146,45 @@ public interface IDatabaseDao {
 
 	void deleteSession(Session session);
 
+	/**
+	 * @deprecated Use getLectureQuestionsForUsers or getLectureQuestionsForTeachers
+	 * @param user
+	 * @param session
+	 * @return
+	 */
+	@Deprecated
 	List<Question> getLectureQuestions(User user, Session session);
 
+	List<Question> getLectureQuestionsForUsers(Session session);
+
+	List<Question> getLectureQuestionsForTeachers(Session session);
+
+	/**
+	 * @deprecated Use getFlashcardsForUsers or getFlashcardsForTeachers
+	 * @param user
+	 * @param session
+	 * @return
+	 */
+	@Deprecated
 	List<Question> getFlashcards(User user, Session session);
 
+	List<Question> getFlashcardsForUsers(Session session);
+
+	List<Question> getFlashcardsForTeachers(Session session);
+
+	/**
+	 * @deprecated Use getPreparationQuestionsForUsers or getPreparationQuestionsForTeachers
+	 * @param user
+	 * @param session
+	 * @return
+	 */
+	@Deprecated
 	List<Question> getPreparationQuestions(User user, Session session);
 
+	List<Question> getPreparationQuestionsForUsers(Session session);
+
+	List<Question> getPreparationQuestionsForTeachers(Session session);
+
 	int getLectureQuestionCount(Session session);
 
 	int getFlashcardCount(Session session);
diff --git a/src/main/java/de/thm/arsnova/services/QuestionService.java b/src/main/java/de/thm/arsnova/services/QuestionService.java
index 7fc4aedb..4bff1ebf 100644
--- a/src/main/java/de/thm/arsnova/services/QuestionService.java
+++ b/src/main/java/de/thm/arsnova/services/QuestionService.java
@@ -84,7 +84,13 @@ public class QuestionService implements IQuestionService, ApplicationEventPublis
 	@Override
 	@PreAuthorize("isAuthenticated()")
 	public List<Question> getSkillQuestions(final String sessionkey) {
-		return databaseDao.getSkillQuestions(userService.getCurrentUser(), getSession(sessionkey));
+		final Session session = getSession(sessionkey);
+		final User user = userService.getCurrentUser();
+		if (session.isCreator(user)) {
+			return databaseDao.getSkillQuestionsForTeachers(session);
+		} else {
+			return databaseDao.getSkillQuestionsForUsers(session);
+		}
 	}
 
 	@Override
@@ -317,7 +323,7 @@ public class QuestionService implements IQuestionService, ApplicationEventPublis
 	public List<Answer> getMyAnswers(final String sessionKey) {
 		final Session session = getSession(sessionKey);
 		// Load questions first because we are only interested in answers of the latest piRound.
-		final List<Question> questions = getSkillQuestions(sessionKey);
+		final List<Question> questions = databaseDao.getSkillQuestionsForUsers(session);
 		final Map<String, Question> questionIdToQuestion = new HashMap<String, Question>();
 		for (final Question question : questions) {
 			questionIdToQuestion.put(question.get_id(), question);
@@ -495,19 +501,37 @@ public class QuestionService implements IQuestionService, ApplicationEventPublis
 	@Override
 	@PreAuthorize("isAuthenticated()")
 	public List<Question> getLectureQuestions(final String sessionkey) {
-		return databaseDao.getLectureQuestions(userService.getCurrentUser(), getSession(sessionkey));
+		final Session session = getSession(sessionkey);
+		final User user = userService.getCurrentUser();
+		if (session.isCreator(user)) {
+			return databaseDao.getLectureQuestionsForTeachers(session);
+		} else {
+			return databaseDao.getLectureQuestionsForUsers(session);
+		}
 	}
 
 	@Override
 	@PreAuthorize("isAuthenticated()")
 	public List<Question> getFlashcards(final String sessionkey) {
-		return databaseDao.getFlashcards(userService.getCurrentUser(), getSession(sessionkey));
+		final Session session = getSession(sessionkey);
+		final User user = userService.getCurrentUser();
+		if (session.isCreator(user)) {
+			return databaseDao.getFlashcardsForTeachers(session);
+		} else {
+			return databaseDao.getFlashcardsForUsers(session);
+		}
 	}
 
 	@Override
 	@PreAuthorize("isAuthenticated()")
 	public List<Question> getPreparationQuestions(final String sessionkey) {
-		return databaseDao.getPreparationQuestions(userService.getCurrentUser(), getSession(sessionkey));
+		final Session session = getSession(sessionkey);
+		final User user = userService.getCurrentUser();
+		if (session.isCreator(user)) {
+			return databaseDao.getPreparationQuestionsForTeachers(session);
+		} else {
+			return databaseDao.getPreparationQuestionsForUsers(session);
+		}
 	}
 
 	private Session getSession(final String sessionkey) {
-- 
GitLab