From 245f281ffd17980d832aab4e3ef75d3c475e02b6 Mon Sep 17 00:00:00 2001
From: Daniel Gerhardt <code@dgerhardt.net>
Date: Sun, 2 Jul 2017 15:18:31 +0200
Subject: [PATCH] Migrate remaining CouchDB code to Ektorp

Code for the following domains has been migrated:
* VisitedSession
* MotdList
* Statistics
* LearingProgress
---
 .../java/de/thm/arsnova/config/AppConfig.java |  44 ++--
 .../java/de/thm/arsnova/dao/CouchDBDao.java   | 220 ------------------
 .../java/de/thm/arsnova/dao/IDatabaseDao.java |  16 --
 .../domain/LearningProgressFactory.java       |   8 +-
 .../domain/PointBasedLearningProgress.java    |   6 +-
 .../domain/QuestionBasedLearningProgress.java |   6 +-
 .../domain/VariantLearningProgress.java       |  10 +-
 .../de/thm/arsnova/entities/MotdList.java     |  51 ++--
 .../CouchDbTypeFieldConverter.java            |   2 +
 .../persistance/MotdListRepository.java       |   8 +
 .../SessionStatisticsRepository.java          |   8 +
 .../persistance/StatisticsRepository.java     |   7 +
 .../persistance/VisitedSessionRepository.java |   5 +
 .../couchdb/CouchDbMotdListRepository.java    |  46 ++++
 .../CouchDbSessionStatisticsRepository.java   |  54 +++++
 .../couchdb/CouchDbStatisticsRepository.java  |  88 +++++++
 .../CouchDbVisitedSessionRepository.java      |  70 ++++++
 .../de/thm/arsnova/services/MotdService.java  |  17 +-
 .../thm/arsnova/services/SessionService.java  |  10 +-
 .../arsnova/services/StatisticsService.java   |   9 +-
 .../de/thm/arsnova/dao/StubDatabaseDao.java   |  36 ---
 .../PointBasedLearningProgressTest.java       |   4 +-
 .../QuestionBasedLearningProgressTest.java    |   4 +-
 23 files changed, 373 insertions(+), 356 deletions(-)
 create mode 100644 src/main/java/de/thm/arsnova/persistance/MotdListRepository.java
 create mode 100644 src/main/java/de/thm/arsnova/persistance/SessionStatisticsRepository.java
 create mode 100644 src/main/java/de/thm/arsnova/persistance/StatisticsRepository.java
 create mode 100644 src/main/java/de/thm/arsnova/persistance/VisitedSessionRepository.java
 create mode 100644 src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbMotdListRepository.java
 create mode 100644 src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbSessionStatisticsRepository.java
 create mode 100644 src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbStatisticsRepository.java
 create mode 100644 src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbVisitedSessionRepository.java

diff --git a/src/main/java/de/thm/arsnova/config/AppConfig.java b/src/main/java/de/thm/arsnova/config/AppConfig.java
index 49297579d..cd5576087 100644
--- a/src/main/java/de/thm/arsnova/config/AppConfig.java
+++ b/src/main/java/de/thm/arsnova/config/AppConfig.java
@@ -23,30 +23,12 @@ import com.fasterxml.jackson.databind.SerializationFeature;
 import de.thm.arsnova.ImageUtils;
 import de.thm.arsnova.connector.client.ConnectorClient;
 import de.thm.arsnova.connector.client.ConnectorClientImpl;
-import de.thm.arsnova.entities.Answer;
-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.*;
 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.AnswerRepository;
-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.CouchDbAnswerRepository;
-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;
-import de.thm.arsnova.persistance.couchdb.CouchDbUserRepository;
+import de.thm.arsnova.persistance.*;
+import de.thm.arsnova.persistance.couchdb.*;
 import de.thm.arsnova.persistance.couchdb.InitializingCouchDbConnector;
 import de.thm.arsnova.socket.ARSnovaSocket;
 import de.thm.arsnova.socket.ARSnovaSocketIOServer;
@@ -321,6 +303,26 @@ public class AppConfig extends WebMvcConfigurerAdapter {
 		return new CouchDbUserRepository(DbUser.class, couchDbConnector(), false);
 	}
 
+	@Bean
+	public VisitedSessionRepository visitedSessionRepository() throws Exception {
+		return new CouchDbVisitedSessionRepository(VisitedSession.class, couchDbConnector(), false);
+	}
+
+	@Bean
+	public MotdListRepository motdListRepository() throws Exception {
+		return new CouchDbMotdListRepository(MotdList.class, couchDbConnector(), false);
+	}
+
+	@Bean
+	public StatisticsRepository statisticsRepository() throws Exception {
+		return new CouchDbStatisticsRepository(Object.class, couchDbConnector(), false);
+	}
+
+	@Bean
+	public SessionStatisticsRepository sessionStatisticsRepository() throws Exception {
+		return new CouchDbSessionStatisticsRepository(Object.class, couchDbConnector(), false);
+	}
+
 	@Bean(name = "connectorClient")
 	public ConnectorClient connectorClient() {
 		if (!connectorEnable) {
diff --git a/src/main/java/de/thm/arsnova/dao/CouchDBDao.java b/src/main/java/de/thm/arsnova/dao/CouchDBDao.java
index 247d432cb..38aa4ee83 100644
--- a/src/main/java/de/thm/arsnova/dao/CouchDBDao.java
+++ b/src/main/java/de/thm/arsnova/dao/CouchDBDao.java
@@ -21,16 +21,13 @@ import com.fourspaces.couchdb.Database;
 import com.fourspaces.couchdb.Document;
 import com.fourspaces.couchdb.View;
 import com.fourspaces.couchdb.ViewResults;
-import com.google.common.collect.Lists;
 import de.thm.arsnova.connector.model.Course;
-import de.thm.arsnova.domain.CourseScore;
 import de.thm.arsnova.entities.*;
 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.services.ISessionService;
-import net.sf.json.JSONArray;
 import net.sf.json.JSONObject;
 import org.checkerframework.checker.nullness.qual.NonNull;
 import org.slf4j.Logger;
@@ -38,18 +35,12 @@ import org.slf4j.LoggerFactory;
 import org.springframework.aop.framework.AopContext;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
-import org.springframework.cache.annotation.CachePut;
-import org.springframework.cache.annotation.Cacheable;
-import org.springframework.context.ApplicationEventPublisher;
-import org.springframework.context.ApplicationEventPublisherAware;
 import org.springframework.context.annotation.Profile;
 import org.springframework.stereotype.Service;
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Set;
 
 /**
  * Database implementation based on CouchDB.
@@ -73,8 +64,6 @@ import java.util.Set;
 @Service("databaseDao")
 public class CouchDBDao implements IDatabaseDao {
 
-	private static final int BULK_PARTITION_SIZE = 500;
-
 	@Autowired
 	private ISessionService sessionService;
 
@@ -169,84 +158,6 @@ public class CouchDBDao implements IDatabaseDao {
 		return results == null || results.getResults().isEmpty() || results.getJSONArray("rows").isEmpty();
 	}
 
-	@Cacheable("statistics")
-	@Override
-	public Statistics getStatistics() {
-		final Statistics stats = new Statistics();
-		try {
-			final View statsView = new View("statistics/statistics");
-			final View creatorView = new View("statistics/unique_session_creators");
-			final View studentUserView = new View("statistics/active_student_users");
-			statsView.setGroup(true);
-			creatorView.setGroup(true);
-			studentUserView.setGroup(true);
-
-			final ViewResults statsResults = getDatabase().view(statsView);
-			final ViewResults creatorResults = getDatabase().view(creatorView);
-			final ViewResults studentUserResults = getDatabase().view(studentUserView);
-
-			if (!isEmptyResults(statsResults)) {
-				final JSONArray rows = statsResults.getJSONArray("rows");
-				for (int i = 0; i < rows.size(); i++) {
-					final JSONObject row = rows.getJSONObject(i);
-					final int value = row.getInt("value");
-					switch (row.getString("key")) {
-					case "openSessions":
-						stats.setOpenSessions(stats.getOpenSessions() + value);
-						break;
-					case "closedSessions":
-						stats.setClosedSessions(stats.getClosedSessions() + value);
-						break;
-					case "deletedSessions":
-						/* Deleted sessions are not exposed separately for now. */
-						stats.setClosedSessions(stats.getClosedSessions() + value);
-						break;
-					case "answers":
-						stats.setAnswers(stats.getAnswers() + value);
-						break;
-					case "lectureQuestions":
-						stats.setLectureQuestions(stats.getLectureQuestions() + value);
-						break;
-					case "preparationQuestions":
-						stats.setPreparationQuestions(stats.getPreparationQuestions() + value);
-						break;
-					case "interposedQuestions":
-						stats.setInterposedQuestions(stats.getInterposedQuestions() + value);
-						break;
-					case "conceptQuestions":
-						stats.setConceptQuestions(stats.getConceptQuestions() + value);
-						break;
-					case "flashcards":
-						stats.setFlashcards(stats.getFlashcards() + value);
-						break;
-					}
-				}
-			}
-			if (!isEmptyResults(creatorResults)) {
-				final JSONArray rows = creatorResults.getJSONArray("rows");
-				Set<String> creators = new HashSet<>();
-				for (int i = 0; i < rows.size(); i++) {
-					final JSONObject row = rows.getJSONObject(i);
-					creators.add(row.getString("key"));
-				}
-				stats.setCreators(creators.size());
-			}
-			if (!isEmptyResults(studentUserResults)) {
-				final JSONArray rows = studentUserResults.getJSONArray("rows");
-				Set<String> students = new HashSet<>();
-				for (int i = 0; i < rows.size(); i++) {
-					final JSONObject row = rows.getJSONObject(i);
-					students.add(row.getString("key"));
-				}
-				stats.setActiveStudents(students.size());
-			}
-			return stats;
-		} catch (final Exception e) {
-			logger.error("Could not retrieve session count.", e);
-		}
-		return stats;
-	}
-
 	/**
 	 * Adds convenience methods to CouchDB4J's view class.
 	 */
@@ -272,135 +183,4 @@ public class CouchDBDao implements IDatabaseDao {
 			setKeys(sessionIds);
 		}
 	}
-
-	@Override
-	public int deleteInactiveGuestVisitedSessionLists(long lastActivityBefore) {
-		try {
-			View view = new View("logged_in/by_last_activity_for_guests");
-			view.setEndKey(lastActivityBefore);
-			List<Document> results = this.getDatabase().view(view).getResults();
-
-			int count = 0;
-			List<List<Document>> partitions = Lists.partition(results, BULK_PARTITION_SIZE);
-			for (List<Document> partition: partitions) {
-				final List<Document> newDocs = new ArrayList<>();
-				for (final Document oldDoc : partition) {
-					final Document newDoc = new Document();
-					newDoc.setId(oldDoc.getId());
-					newDoc.setRev(oldDoc.getJSONObject("value").getString("_rev"));
-					newDoc.put("_deleted", true);
-					newDocs.add(newDoc);
-					logger.debug("Marked logged_in document {} for deletion.", oldDoc.getId());
-					/* Use log type 'user' since effectively the user is deleted in case of guests */
-					dbLogger.log("delete", "type", "user", "id", oldDoc.getId());
-				}
-
-				if (!newDocs.isEmpty()) {
-					if (getDatabase().bulkSaveDocuments(newDocs.toArray(new Document[newDocs.size()]))) {
-						count += newDocs.size();
-					} else {
-						logger.error("Could not bulk delete visited session lists.");
-					}
-				}
-			}
-
-			if (count > 0) {
-				logger.info("Deleted {} visited session lists of inactive users.", count);
-				dbLogger.log("cleanup", "type", "visitedsessions", "count", count);
-			}
-
-			return count;
-		} catch (IOException e) {
-			logger.error("Could not delete visited session lists of inactive users.", e);
-		}
-
-		return 0;
-	}
-
-	@Cacheable("learningprogress")
-	@Override
-	public CourseScore getLearningProgress(final Session session) {
-		final View maximumValueView = new View("learning_progress/maximum_value_of_question");
-		final View answerSumView = new View("learning_progress/question_value_achieved_for_user");
-		maximumValueView.setStartKeyArray(session.getId());
-		maximumValueView.setEndKeyArray(session.getId(), "{}");
-		answerSumView.setStartKeyArray(session.getId());
-		answerSumView.setEndKeyArray(session.getId(), "{}");
-
-		final List<Document> maximumValueResult = getDatabase().view(maximumValueView).getResults();
-		final List<Document> answerSumResult = getDatabase().view(answerSumView).getResults();
-
-		CourseScore courseScore = new CourseScore();
-
-		// no results found
-		if (maximumValueResult.isEmpty() && answerSumResult.isEmpty()) {
-			return courseScore;
-		}
-
-		// collect mapping (questionId -> max value)
-		for (Document d : maximumValueResult) {
-			String questionId = d.getJSONArray("key").getString(1);
-			JSONObject value = d.getJSONObject("value");
-			int questionScore = value.getInt("value");
-			String questionVariant = value.getString("questionVariant");
-			int piRound = value.getInt("piRound");
-			courseScore.addQuestion(questionId, questionVariant, piRound, questionScore);
-		}
-		// collect mapping (questionId -> (user -> value))
-		for (Document d : answerSumResult) {
-			String username = d.getJSONArray("key").getString(1);
-			JSONObject value = d.getJSONObject("value");
-			String questionId = value.getString("questionId");
-			int userscore = value.getInt("score");
-			int piRound = value.getInt("piRound");
-			courseScore.addAnswer(questionId, piRound, username, userscore);
-		}
-		return courseScore;
-	}
-
-	@Override
-	@Cacheable(cacheNames = "motdlist", key = "#p0")
-	public MotdList getMotdListForUser(final String username) {
-		View view = new View("motdlist/doc_by_username");
-		view.setKey(username);
-
-		ViewResults results = this.getDatabase().view(view);
-
-		MotdList motdlist = new MotdList();
-		for (final Document d : results.getResults()) {
-			motdlist.set_id(d.getId());
-			motdlist.set_rev(d.getJSONObject("value").getString("_rev"));
-			motdlist.setUsername(d.getJSONObject("value").getString("username"));
-			motdlist.setMotdkeys(d.getJSONObject("value").getString("motdkeys"));
-		}
-		return motdlist;
-	}
-
-	@Override
-	@CachePut(cacheNames = "motdlist", key = "#p0.username")
-	public MotdList createOrUpdateMotdList(MotdList motdlist) {
-		try {
-			String id = motdlist.get_id();
-			String rev = motdlist.get_rev();
-			Document d = new Document();
-
-			if (null != id) {
-				d = database.getDocument(id, rev);
-			}
-			d.put("type", "motdlist");
-			d.put("username", motdlist.getUsername());
-			d.put("motdkeys", motdlist.getMotdkeys());
-
-			database.saveDocument(d, id);
-			motdlist.set_id(d.getId());
-			motdlist.set_rev(d.getRev());
-
-			return motdlist;
-		} catch (IOException e) {
-			logger.error("Could not save MotD list {}.", motdlist, e);
-		}
-
-		return null;
-	}
-
 }
diff --git a/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java b/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java
index 8337277a7..48729d116 100644
--- a/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java
+++ b/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java
@@ -17,25 +17,9 @@
  */
 package de.thm.arsnova.dao;
 
-import de.thm.arsnova.domain.CourseScore;
-import de.thm.arsnova.entities.*;
-
-import java.util.List;
-
 /**
  * All methods the database must support.
  */
 public interface IDatabaseDao {
-
-	int deleteInactiveGuestVisitedSessionLists(long lastActivityBefore);
-
-	CourseScore getLearningProgress(Session session);
-
-	Statistics getStatistics();
-
 	<T> T getObjectFromId(String documentId, Class<T> klass);
-
-	MotdList getMotdListForUser(final String username);
-
-	MotdList createOrUpdateMotdList(MotdList motdlist);
 }
diff --git a/src/main/java/de/thm/arsnova/domain/LearningProgressFactory.java b/src/main/java/de/thm/arsnova/domain/LearningProgressFactory.java
index d03d0eb24..a5596c0b7 100644
--- a/src/main/java/de/thm/arsnova/domain/LearningProgressFactory.java
+++ b/src/main/java/de/thm/arsnova/domain/LearningProgressFactory.java
@@ -17,8 +17,8 @@
  */
 package de.thm.arsnova.domain;
 
-import de.thm.arsnova.dao.IDatabaseDao;
 import de.thm.arsnova.events.*;
+import de.thm.arsnova.persistance.SessionStatisticsRepository;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.cache.annotation.CacheEvict;
 import org.springframework.context.ApplicationEventPublisher;
@@ -34,7 +34,7 @@ import org.springframework.stereotype.Component;
 public class LearningProgressFactory implements NovaEventVisitor, ILearningProgressFactory, ApplicationEventPublisherAware {
 
 	@Autowired
-	private IDatabaseDao databaseDao;
+	private SessionStatisticsRepository sessionStatisticsRepository;
 
 	private ApplicationEventPublisher publisher;
 
@@ -42,9 +42,9 @@ public class LearningProgressFactory implements NovaEventVisitor, ILearningProgr
 	public LearningProgress create(String progressType, String questionVariant) {
 		VariantLearningProgress learningProgress;
 		if ("questions".equals(progressType)) {
-			learningProgress = new QuestionBasedLearningProgress(databaseDao);
+			learningProgress = new QuestionBasedLearningProgress(sessionStatisticsRepository);
 		} else {
-			learningProgress = new PointBasedLearningProgress(databaseDao);
+			learningProgress = new PointBasedLearningProgress(sessionStatisticsRepository);
 		}
 		learningProgress.setQuestionVariant(questionVariant);
 		return learningProgress;
diff --git a/src/main/java/de/thm/arsnova/domain/PointBasedLearningProgress.java b/src/main/java/de/thm/arsnova/domain/PointBasedLearningProgress.java
index a904caf6b..21f2fbd3d 100644
--- a/src/main/java/de/thm/arsnova/domain/PointBasedLearningProgress.java
+++ b/src/main/java/de/thm/arsnova/domain/PointBasedLearningProgress.java
@@ -17,17 +17,17 @@
  */
 package de.thm.arsnova.domain;
 
-import de.thm.arsnova.dao.IDatabaseDao;
 import de.thm.arsnova.entities.User;
 import de.thm.arsnova.entities.transport.LearningProgressValues;
+import de.thm.arsnova.persistance.SessionStatisticsRepository;
 
 /**
  * Calculates learning progress based on a question's value.
  */
 public class PointBasedLearningProgress extends VariantLearningProgress {
 
-	public PointBasedLearningProgress(IDatabaseDao dao) {
-		super(dao);
+	public PointBasedLearningProgress(SessionStatisticsRepository sessionStatisticsRepository) {
+		super(sessionStatisticsRepository);
 	}
 
 	@Override
diff --git a/src/main/java/de/thm/arsnova/domain/QuestionBasedLearningProgress.java b/src/main/java/de/thm/arsnova/domain/QuestionBasedLearningProgress.java
index dba9b4180..37b6c6397 100644
--- a/src/main/java/de/thm/arsnova/domain/QuestionBasedLearningProgress.java
+++ b/src/main/java/de/thm/arsnova/domain/QuestionBasedLearningProgress.java
@@ -17,9 +17,9 @@
  */
 package de.thm.arsnova.domain;
 
-import de.thm.arsnova.dao.IDatabaseDao;
 import de.thm.arsnova.entities.User;
 import de.thm.arsnova.entities.transport.LearningProgressValues;
+import de.thm.arsnova.persistance.SessionStatisticsRepository;
 
 /**
  * Calculates learning progress based on overall correctness of an answer. A question is answered correctly if and
@@ -27,8 +27,8 @@ import de.thm.arsnova.entities.transport.LearningProgressValues;
  */
 public class QuestionBasedLearningProgress extends VariantLearningProgress {
 
-	public QuestionBasedLearningProgress(IDatabaseDao dao) {
-		super(dao);
+	public QuestionBasedLearningProgress(SessionStatisticsRepository sessionStatisticsRepository) {
+		super(sessionStatisticsRepository);
 	}
 
 	@Override
diff --git a/src/main/java/de/thm/arsnova/domain/VariantLearningProgress.java b/src/main/java/de/thm/arsnova/domain/VariantLearningProgress.java
index 708acb4b7..7e1c06970 100644
--- a/src/main/java/de/thm/arsnova/domain/VariantLearningProgress.java
+++ b/src/main/java/de/thm/arsnova/domain/VariantLearningProgress.java
@@ -17,10 +17,10 @@
  */
 package de.thm.arsnova.domain;
 
-import de.thm.arsnova.dao.IDatabaseDao;
 import de.thm.arsnova.entities.Session;
 import de.thm.arsnova.entities.User;
 import de.thm.arsnova.entities.transport.LearningProgressValues;
+import de.thm.arsnova.persistance.SessionStatisticsRepository;
 
 /**
  * Base class for the learning progress feature that allows filtering on the question variant.
@@ -31,14 +31,14 @@ abstract class VariantLearningProgress implements LearningProgress {
 
 	private String questionVariant;
 
-	private final IDatabaseDao databaseDao;
+	private final SessionStatisticsRepository sessionStatisticsRepository;
 
-	public VariantLearningProgress(final IDatabaseDao dao) {
-		this.databaseDao = dao;
+	public VariantLearningProgress(final SessionStatisticsRepository sessionStatisticsRepository) {
+		this.sessionStatisticsRepository = sessionStatisticsRepository;
 	}
 
 	private void loadProgress(final Session session) {
-		this.courseScore = databaseDao.getLearningProgress(session);
+		this.courseScore = sessionStatisticsRepository.getLearningProgress(session);
 	}
 
 	public void setQuestionVariant(final String variant) {
diff --git a/src/main/java/de/thm/arsnova/entities/MotdList.java b/src/main/java/de/thm/arsnova/entities/MotdList.java
index 307fb6696..35b611fee 100644
--- a/src/main/java/de/thm/arsnova/entities/MotdList.java
+++ b/src/main/java/de/thm/arsnova/entities/MotdList.java
@@ -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;
 
@@ -24,45 +26,52 @@ import io.swagger.annotations.ApiModelProperty;
  * This class represents a list of motdkeys for a user.
  */
 @ApiModel(value = "motdlist", description = "the motdlist to save the messages a user has confirmed to be read")
-public class MotdList {
-
+public class MotdList implements Entity {
+	private String id;
+	private String rev;
 	private String motdkeys;
 	private String username;
-	private String _id;
-	private String _rev;
+
+	@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;
+	}
+
+	@JsonView({View.Persistence.class, View.Public.class})
+	public String getRevision() {
+		return rev;
+	}
 
 	@ApiModelProperty(required = true, value = "the motdkeylist")
+	@JsonView({View.Persistence.class, View.Public.class})
 	public String getMotdkeys() {
 		return motdkeys;
 	}
 
+	@JsonView({View.Persistence.class, View.Public.class})
 	public void setMotdkeys(String motds) {
 		motdkeys = motds;
 	}
 
 	@ApiModelProperty(required = true, value = "the username")
+	@JsonView({View.Persistence.class, View.Public.class})
 	public String getUsername() {
 		return username;
 	}
 
+	@JsonView({View.Persistence.class, View.Public.class})
 	public void setUsername(final String u) {
 		username = u;
 	}
-
-	@ApiModelProperty(required = true, value = "the couchDB ID")
-	public String get_id() {
-		return _id;
-	}
-
-	public void set_id(final String id) {
-		_id = id;
-	}
-
-	public void set_rev(final String rev) {
-		_rev = rev;
-	}
-
-	public String get_rev() {
-		return _rev;
-	}
 }
diff --git a/src/main/java/de/thm/arsnova/entities/serialization/CouchDbTypeFieldConverter.java b/src/main/java/de/thm/arsnova/entities/serialization/CouchDbTypeFieldConverter.java
index 3a3c6c1eb..5b2199fef 100644
--- a/src/main/java/de/thm/arsnova/entities/serialization/CouchDbTypeFieldConverter.java
+++ b/src/main/java/de/thm/arsnova/entities/serialization/CouchDbTypeFieldConverter.java
@@ -27,6 +27,7 @@ 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.MotdList;
 import de.thm.arsnova.entities.Session;
 
 import java.util.HashMap;
@@ -39,6 +40,7 @@ public class CouchDbTypeFieldConverter implements Converter<Class<? extends Enti
 		typeMapping.put(LogEntry.class, "log");
 		typeMapping.put(DbUser.class, "userdetails");
 		typeMapping.put(Motd.class, "motd");
+		typeMapping.put(MotdList.class, "motdlist");
 		typeMapping.put(Session.class, "session");
 		typeMapping.put(Comment.class, "interposed_question");
 		typeMapping.put(Content.class, "skill_question");
diff --git a/src/main/java/de/thm/arsnova/persistance/MotdListRepository.java b/src/main/java/de/thm/arsnova/persistance/MotdListRepository.java
new file mode 100644
index 000000000..a044fe7ed
--- /dev/null
+++ b/src/main/java/de/thm/arsnova/persistance/MotdListRepository.java
@@ -0,0 +1,8 @@
+package de.thm.arsnova.persistance;
+
+import de.thm.arsnova.entities.MotdList;
+
+public interface MotdListRepository {
+	MotdList getMotdListForUser(final String username);
+	MotdList createOrUpdateMotdList(MotdList motdlist);
+}
diff --git a/src/main/java/de/thm/arsnova/persistance/SessionStatisticsRepository.java b/src/main/java/de/thm/arsnova/persistance/SessionStatisticsRepository.java
new file mode 100644
index 000000000..193da0333
--- /dev/null
+++ b/src/main/java/de/thm/arsnova/persistance/SessionStatisticsRepository.java
@@ -0,0 +1,8 @@
+package de.thm.arsnova.persistance;
+
+import de.thm.arsnova.domain.CourseScore;
+import de.thm.arsnova.entities.Session;
+
+public interface SessionStatisticsRepository {
+	CourseScore getLearningProgress(Session session);
+}
diff --git a/src/main/java/de/thm/arsnova/persistance/StatisticsRepository.java b/src/main/java/de/thm/arsnova/persistance/StatisticsRepository.java
new file mode 100644
index 000000000..ea334f0d6
--- /dev/null
+++ b/src/main/java/de/thm/arsnova/persistance/StatisticsRepository.java
@@ -0,0 +1,7 @@
+package de.thm.arsnova.persistance;
+
+import de.thm.arsnova.entities.Statistics;
+
+public interface StatisticsRepository {
+	Statistics getStatistics();
+}
diff --git a/src/main/java/de/thm/arsnova/persistance/VisitedSessionRepository.java b/src/main/java/de/thm/arsnova/persistance/VisitedSessionRepository.java
new file mode 100644
index 000000000..ce0b23581
--- /dev/null
+++ b/src/main/java/de/thm/arsnova/persistance/VisitedSessionRepository.java
@@ -0,0 +1,5 @@
+package de.thm.arsnova.persistance;
+
+public interface VisitedSessionRepository {
+	int deleteInactiveGuestVisitedSessionLists(long lastActivityBefore);
+}
diff --git a/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbMotdListRepository.java b/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbMotdListRepository.java
new file mode 100644
index 000000000..05bef30ab
--- /dev/null
+++ b/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbMotdListRepository.java
@@ -0,0 +1,46 @@
+package de.thm.arsnova.persistance.couchdb;
+
+import de.thm.arsnova.entities.MotdList;
+import de.thm.arsnova.persistance.MotdListRepository;
+import org.ektorp.CouchDbConnector;
+import org.ektorp.DbAccessException;
+import org.ektorp.support.CouchDbRepositorySupport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.cache.annotation.CachePut;
+import org.springframework.cache.annotation.Cacheable;
+
+import java.util.List;
+
+public class CouchDbMotdListRepository extends CouchDbRepositorySupport<MotdList> implements MotdListRepository {
+	private static final Logger logger = LoggerFactory.getLogger(CouchDbMotdListRepository.class);
+
+	public CouchDbMotdListRepository(Class<MotdList> type, CouchDbConnector db, boolean createIfNotExists) {
+		super(type, db, createIfNotExists);
+	}
+
+	@Override
+	@Cacheable(cacheNames = "motdlist", key = "#p0")
+	public MotdList getMotdListForUser(final String username) {
+		List<MotdList> motdListList = queryView("by_username", username);
+		return motdListList.isEmpty() ? new MotdList() : motdListList.get(0);
+	}
+
+	@Override
+	@CachePut(cacheNames = "motdlist", key = "#p0.username")
+	public MotdList createOrUpdateMotdList(MotdList motdlist) {
+		try {
+			if (motdlist.getId() != null) {
+				update(motdlist);
+			} else {
+				db.create(motdlist);
+			}
+
+			return motdlist;
+		} catch (DbAccessException e) {
+			logger.error("Could not save MotD list {}.", motdlist, e);
+		}
+
+		return null;
+	}
+}
diff --git a/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbSessionStatisticsRepository.java b/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbSessionStatisticsRepository.java
new file mode 100644
index 000000000..be48429e2
--- /dev/null
+++ b/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbSessionStatisticsRepository.java
@@ -0,0 +1,54 @@
+package de.thm.arsnova.persistance.couchdb;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import de.thm.arsnova.domain.CourseScore;
+import de.thm.arsnova.entities.Session;
+import de.thm.arsnova.persistance.SessionStatisticsRepository;
+import org.ektorp.ComplexKey;
+import org.ektorp.CouchDbConnector;
+import org.ektorp.ViewResult;
+import org.ektorp.support.CouchDbRepositorySupport;
+import org.springframework.cache.annotation.Cacheable;
+
+public class CouchDbSessionStatisticsRepository extends CouchDbRepositorySupport implements SessionStatisticsRepository {
+	public CouchDbSessionStatisticsRepository(Class type, CouchDbConnector db, boolean createIfNotExists) {
+		super(type, db, "learning_progress", createIfNotExists);
+	}
+
+	@Cacheable("learningprogress")
+	@Override
+	public CourseScore getLearningProgress(final Session session) {
+		final ViewResult maximumValueResult = db.queryView(createQuery("maximum_value_of_question")
+				.startKey(ComplexKey.of(session.getId()))
+				.endKey(ComplexKey.of(session.getId(), ComplexKey.emptyObject())));
+		final ViewResult answerSumResult = db.queryView(createQuery("question_value_achieved_for_user")
+				.startKey(ComplexKey.of(session.getId()))
+				.endKey(ComplexKey.of(session.getId(), ComplexKey.emptyObject())));
+		final CourseScore courseScore = new CourseScore();
+
+		// no results found
+		if (maximumValueResult.isEmpty() && answerSumResult.isEmpty()) {
+			return courseScore;
+		}
+
+		// collect mapping (questionId -> max value)
+		for (ViewResult.Row row : maximumValueResult) {
+			final String questionId = row.getKeyAsNode().get(1).asText();
+			final JsonNode value = row.getValueAsNode();
+			final int questionScore = value.get("value").asInt();
+			final String questionVariant = value.get("questionVariant").asText();
+			final int piRound = value.get("piRound").asInt();
+			courseScore.addQuestion(questionId, questionVariant, piRound, questionScore);
+		}
+		// collect mapping (questionId -> (user -> value))
+		for (ViewResult.Row row : answerSumResult) {
+			final String username = row.getKeyAsNode().get(1).asText();
+			final JsonNode value = row.getValueAsNode();
+			final String questionId = value.get("questionId").asText();
+			final int userscore = value.get("score").asInt();
+			final int piRound = value.get("piRound").asInt();
+			courseScore.addAnswer(questionId, piRound, username, userscore);
+		}
+		return courseScore;
+	}
+}
diff --git a/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbStatisticsRepository.java b/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbStatisticsRepository.java
new file mode 100644
index 000000000..20ed90676
--- /dev/null
+++ b/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbStatisticsRepository.java
@@ -0,0 +1,88 @@
+package de.thm.arsnova.persistance.couchdb;
+
+import de.thm.arsnova.entities.Statistics;
+import de.thm.arsnova.persistance.StatisticsRepository;
+import org.ektorp.CouchDbConnector;
+import org.ektorp.DbAccessException;
+import org.ektorp.ViewResult;
+import org.ektorp.support.CouchDbRepositorySupport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.cache.annotation.Cacheable;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class CouchDbStatisticsRepository extends CouchDbRepositorySupport implements StatisticsRepository {
+	private static final Logger logger = LoggerFactory.getLogger(CouchDbStatisticsRepository.class);
+
+	public CouchDbStatisticsRepository(Class type, CouchDbConnector db, boolean createIfNotExists) {
+		super(type, db, "statistics", createIfNotExists);
+	}
+
+	@Cacheable("statistics")
+	@Override
+	public Statistics getStatistics() {
+		final Statistics stats = new Statistics();
+		try {
+			final ViewResult statsResult = db.queryView(createQuery("statistics").group(true));
+			final ViewResult creatorResult = db.queryView(createQuery("unique_session_creators").group(true));
+			final ViewResult studentUserResult = db.queryView(createQuery("active_student_users").group(true));
+
+			if (!statsResult.isEmpty()) {
+				for (ViewResult.Row row: statsResult.getRows()) {
+					final int value = row.getValueAsInt();
+					switch (row.getKey()) {
+						case "openSessions":
+							stats.setOpenSessions(stats.getOpenSessions() + value);
+							break;
+						case "closedSessions":
+							stats.setClosedSessions(stats.getClosedSessions() + value);
+							break;
+						case "deletedSessions":
+						/* Deleted sessions are not exposed separately for now. */
+							stats.setClosedSessions(stats.getClosedSessions() + value);
+							break;
+						case "answers":
+							stats.setAnswers(stats.getAnswers() + value);
+							break;
+						case "lectureQuestions":
+							stats.setLectureQuestions(stats.getLectureQuestions() + value);
+							break;
+						case "preparationQuestions":
+							stats.setPreparationQuestions(stats.getPreparationQuestions() + value);
+							break;
+						case "interposedQuestions":
+							stats.setInterposedQuestions(stats.getInterposedQuestions() + value);
+							break;
+						case "conceptQuestions":
+							stats.setConceptQuestions(stats.getConceptQuestions() + value);
+							break;
+						case "flashcards":
+							stats.setFlashcards(stats.getFlashcards() + value);
+							break;
+					}
+				}
+			}
+			if (!creatorResult.isEmpty()) {
+				Set<String> creators = new HashSet<>();
+				for (ViewResult.Row row: statsResult.getRows()) {
+					creators.add(row.getKey());
+				}
+				stats.setCreators(creators.size());
+			}
+			if (!studentUserResult.isEmpty()) {
+				Set<String> students = new HashSet<>();
+				for (ViewResult.Row row: statsResult.getRows()) {
+					students.add(row.getKey());
+				}
+				stats.setActiveStudents(students.size());
+			}
+			return stats;
+		} catch (final DbAccessException e) {
+			logger.error("Could not retrieve statistics.", e);
+		}
+
+		return stats;
+	}
+}
diff --git a/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbVisitedSessionRepository.java b/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbVisitedSessionRepository.java
new file mode 100644
index 000000000..e682387a7
--- /dev/null
+++ b/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbVisitedSessionRepository.java
@@ -0,0 +1,70 @@
+package de.thm.arsnova.persistance.couchdb;
+
+import com.google.common.collect.Lists;
+import de.thm.arsnova.entities.VisitedSession;
+import de.thm.arsnova.persistance.LogEntryRepository;
+import de.thm.arsnova.persistance.VisitedSessionRepository;
+import org.ektorp.BulkDeleteDocument;
+import org.ektorp.CouchDbConnector;
+import org.ektorp.DbAccessException;
+import org.ektorp.DocumentOperationResult;
+import org.ektorp.ViewResult;
+import org.ektorp.support.CouchDbRepositorySupport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CouchDbVisitedSessionRepository extends CouchDbRepositorySupport<VisitedSession> implements VisitedSessionRepository {
+	private static final int BULK_PARTITION_SIZE = 500;
+
+	private static final Logger logger = LoggerFactory.getLogger(CouchDbVisitedSessionRepository.class);
+
+	@Autowired
+	private LogEntryRepository dbLogger;
+
+	public CouchDbVisitedSessionRepository(Class<VisitedSession> type, CouchDbConnector db, boolean createIfNotExists) {
+		super(type, db, createIfNotExists);
+	}
+
+	@Override
+	public int deleteInactiveGuestVisitedSessionLists(long lastActivityBefore) {
+		try {
+			ViewResult result = db.queryView(createQuery("by_last_activity_for_guests").endKey(lastActivityBefore));
+
+			int count = 0;
+			List<List<ViewResult.Row>> partitions = Lists.partition(result.getRows(), BULK_PARTITION_SIZE);
+			for (List<ViewResult.Row> partition: partitions) {
+				final List<BulkDeleteDocument> newDocs = new ArrayList<>();
+				for (final ViewResult.Row oldDoc : partition) {
+					final BulkDeleteDocument newDoc = new BulkDeleteDocument(oldDoc.getId(), oldDoc.getValueAsNode().get("_rev").asText());
+					newDocs.add(newDoc);
+					logger.debug("Marked logged_in document {} for deletion.", oldDoc.getId());
+					/* Use log type 'user' since effectively the user is deleted in case of guests */
+					dbLogger.log("delete", "type", "user", "id", oldDoc.getId());
+				}
+
+				if (!newDocs.isEmpty()) {
+					List<DocumentOperationResult> results = db.executeBulk(newDocs);
+					count += newDocs.size() - results.size();
+					if (!results.isEmpty()) {
+						logger.error("Could not bulk delete some visited session lists.");
+					}
+				}
+			}
+
+			if (count > 0) {
+				logger.info("Deleted {} visited session lists of inactive users.", count);
+				dbLogger.log("cleanup", "type", "visitedsessions", "count", count);
+			}
+
+			return count;
+		} catch (DbAccessException e) {
+			logger.error("Could not delete visited session lists of inactive users.", e);
+		}
+
+		return 0;
+	}
+}
diff --git a/src/main/java/de/thm/arsnova/services/MotdService.java b/src/main/java/de/thm/arsnova/services/MotdService.java
index 4df366c73..674525ec2 100644
--- a/src/main/java/de/thm/arsnova/services/MotdService.java
+++ b/src/main/java/de/thm/arsnova/services/MotdService.java
@@ -17,12 +17,12 @@
  */
 package de.thm.arsnova.services;
 
-import de.thm.arsnova.dao.IDatabaseDao;
 import de.thm.arsnova.entities.Motd;
 import de.thm.arsnova.entities.MotdList;
 import de.thm.arsnova.entities.Session;
 import de.thm.arsnova.entities.User;
 import de.thm.arsnova.exceptions.BadRequestException;
+import de.thm.arsnova.persistance.MotdListRepository;
 import de.thm.arsnova.persistance.MotdRepository;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -38,10 +38,6 @@ import java.util.StringTokenizer;
  */
 @Service
 public class MotdService implements IMotdService {
-
-	@Autowired
-	private IDatabaseDao databaseDao;
-
 	@Autowired
 	private IUserService userService;
 
@@ -51,9 +47,8 @@ public class MotdService implements IMotdService {
 	@Autowired
 	private MotdRepository motdRepository;
 
-	public void setDatabaseDao(final IDatabaseDao databaseDao) {
-		this.databaseDao = databaseDao;
-	}
+	@Autowired
+	private MotdListRepository motdListRepository;
 
   @Override
   @PreAuthorize("isAuthenticated()")
@@ -175,7 +170,7 @@ public class MotdService implements IMotdService {
 	public MotdList getMotdListForUser(final String username) {
 		final User user = userService.getCurrentUser();
 		if (username.equals(user.getUsername()) && !"guest".equals(user.getType())) {
-			return databaseDao.getMotdListForUser(username);
+			return motdListRepository.getMotdListForUser(username);
 		}
 		return null;
 	}
@@ -185,7 +180,7 @@ public class MotdService implements IMotdService {
 	public MotdList saveUserMotdList(MotdList motdList) {
 		final User user = userService.getCurrentUser();
 		if (user.getUsername().equals(motdList.getUsername())) {
-			return databaseDao.createOrUpdateMotdList(motdList);
+			return motdListRepository.createOrUpdateMotdList(motdList);
 		}
 		return null;
 	}
@@ -195,7 +190,7 @@ public class MotdService implements IMotdService {
 	public MotdList updateUserMotdList(MotdList motdList) {
 		final User user = userService.getCurrentUser();
 		if (user.getUsername().equals(motdList.getUsername())) {
-			return databaseDao.createOrUpdateMotdList(motdList);
+			return motdListRepository.createOrUpdateMotdList(motdList);
 		}
 		return null;
 	}
diff --git a/src/main/java/de/thm/arsnova/services/SessionService.java b/src/main/java/de/thm/arsnova/services/SessionService.java
index 97b522b42..0257be71d 100644
--- a/src/main/java/de/thm/arsnova/services/SessionService.java
+++ b/src/main/java/de/thm/arsnova/services/SessionService.java
@@ -20,7 +20,6 @@ package de.thm.arsnova.services;
 import de.thm.arsnova.ImageUtils;
 import de.thm.arsnova.connector.client.ConnectorClient;
 import de.thm.arsnova.connector.model.Course;
-import de.thm.arsnova.dao.IDatabaseDao;
 import de.thm.arsnova.domain.ILearningProgressFactory;
 import de.thm.arsnova.domain.LearningProgress;
 import de.thm.arsnova.entities.LearningProgressOptions;
@@ -42,6 +41,7 @@ import de.thm.arsnova.exceptions.NotFoundException;
 import de.thm.arsnova.exceptions.PayloadTooLargeException;
 import de.thm.arsnova.exceptions.UnauthorizedException;
 import de.thm.arsnova.persistance.SessionRepository;
+import de.thm.arsnova.persistance.VisitedSessionRepository;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -105,7 +105,7 @@ public class SessionService implements ISessionService, ApplicationEventPublishe
 	private static final long SESSION_INACTIVITY_CHECK_INTERVAL_MS = 30 * 60 * 1000L;
 
 	@Autowired
-	private IDatabaseDao databaseDao;
+	private VisitedSessionRepository visitedSessionRepository;
 
 	@Autowired
 	private IUserService userService;
@@ -148,14 +148,10 @@ public class SessionService implements ISessionService, ApplicationEventPublishe
 			logger.info("Delete lists of visited session for inactive users.");
 			long unixTime = System.currentTimeMillis();
 			long lastActivityBefore = unixTime - guestSessionInactivityThresholdDays * 24 * 60 * 60 * 1000L;
-			databaseDao.deleteInactiveGuestVisitedSessionLists(lastActivityBefore);
+			visitedSessionRepository.deleteInactiveGuestVisitedSessionLists(lastActivityBefore);
 		}
 	}
 
-	public void setDatabaseDao(final IDatabaseDao newDatabaseDao) {
-		databaseDao = newDatabaseDao;
-	}
-
 	@Override
 	public Session joinSession(final String keyword, final UUID socketId) {
 		/* Socket.IO solution */
diff --git a/src/main/java/de/thm/arsnova/services/StatisticsService.java b/src/main/java/de/thm/arsnova/services/StatisticsService.java
index e8e7fff3e..ddf091b72 100644
--- a/src/main/java/de/thm/arsnova/services/StatisticsService.java
+++ b/src/main/java/de/thm/arsnova/services/StatisticsService.java
@@ -17,8 +17,8 @@
  */
 package de.thm.arsnova.services;
 
-import de.thm.arsnova.dao.IDatabaseDao;
 import de.thm.arsnova.entities.Statistics;
+import de.thm.arsnova.persistance.StatisticsRepository;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Service;
@@ -29,18 +29,17 @@ import org.springframework.stereotype.Service;
  */
 @Service
 public class StatisticsService implements IStatisticsService {
-
 	@Autowired
-	private IDatabaseDao databaseDao;
+	private StatisticsRepository statisticsRepository;
 
 	@Autowired
 	private IUserService userService;
 
 	private Statistics statistics = new Statistics();
 
-	@Scheduled(initialDelay = 0, fixedRate = 300000)
+	@Scheduled(initialDelay = 0, fixedRate = 10000)
 	private void refreshStatistics() {
-		statistics = databaseDao.getStatistics();
+		statistics = statisticsRepository.getStatistics();
 	}
 
 	@Override
diff --git a/src/test/java/de/thm/arsnova/dao/StubDatabaseDao.java b/src/test/java/de/thm/arsnova/dao/StubDatabaseDao.java
index 099e1dfd1..1901a6cc3 100644
--- a/src/test/java/de/thm/arsnova/dao/StubDatabaseDao.java
+++ b/src/test/java/de/thm/arsnova/dao/StubDatabaseDao.java
@@ -17,7 +17,6 @@
  */
 package de.thm.arsnova.dao;
 
-import de.thm.arsnova.domain.CourseScore;
 import de.thm.arsnova.entities.*;
 import org.springframework.context.annotation.Profile;
 import org.springframework.stereotype.Service;
@@ -96,44 +95,9 @@ public class StubDatabaseDao implements IDatabaseDao {
 		stubQuestions.put("12345678", contents);
 	}
 
-	@Override
-	public int deleteInactiveGuestVisitedSessionLists(long lastActivityBefore) {
-		// TODO Auto-generated method stub
-		return 0;
-	}
-
-	@Override
-	public CourseScore getLearningProgress(Session session) {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	@Override
-	public Statistics getStatistics() {
-		final Statistics stats = new Statistics();
-		stats.setOpenSessions(3);
-		stats.setClosedSessions(0);
-		stats.setLectureQuestions(0);
-		stats.setAnswers(0);
-		stats.setInterposedQuestions(0);
-		return stats;
-	}
-
 	@Override
 	public <T> T getObjectFromId(String documentId, Class<T> klass) {
 		// TODO Auto-generated method stub
 		return null;
 	}
-
-	@Override
-	public MotdList getMotdListForUser(final String username) {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	@Override
-	public MotdList createOrUpdateMotdList(MotdList motdlist) {
-		// TODO Auto-generated method stub
-		return null;
-	}
 }
diff --git a/src/test/java/de/thm/arsnova/domain/PointBasedLearningProgressTest.java b/src/test/java/de/thm/arsnova/domain/PointBasedLearningProgressTest.java
index bfad95b36..6f42527dc 100644
--- a/src/test/java/de/thm/arsnova/domain/PointBasedLearningProgressTest.java
+++ b/src/test/java/de/thm/arsnova/domain/PointBasedLearningProgressTest.java
@@ -17,10 +17,10 @@
  */
 package de.thm.arsnova.domain;
 
-import de.thm.arsnova.dao.IDatabaseDao;
 import de.thm.arsnova.entities.TestUser;
 import de.thm.arsnova.entities.User;
 import de.thm.arsnova.entities.transport.LearningProgressValues;
+import de.thm.arsnova.persistance.SessionStatisticsRepository;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -50,7 +50,7 @@ public class PointBasedLearningProgressTest {
 	@Before
 	public void setUp() {
 		this.courseScore = new CourseScore();
-		IDatabaseDao db = mock(IDatabaseDao.class);
+		SessionStatisticsRepository db = mock(SessionStatisticsRepository.class);
 		when(db.getLearningProgress(null)).thenReturn(courseScore);
 		this.lp = new PointBasedLearningProgress(db);
 	}
diff --git a/src/test/java/de/thm/arsnova/domain/QuestionBasedLearningProgressTest.java b/src/test/java/de/thm/arsnova/domain/QuestionBasedLearningProgressTest.java
index 7e029a6cb..8adf79257 100644
--- a/src/test/java/de/thm/arsnova/domain/QuestionBasedLearningProgressTest.java
+++ b/src/test/java/de/thm/arsnova/domain/QuestionBasedLearningProgressTest.java
@@ -17,10 +17,10 @@
  */
 package de.thm.arsnova.domain;
 
-import de.thm.arsnova.dao.IDatabaseDao;
 import de.thm.arsnova.entities.TestUser;
 import de.thm.arsnova.entities.User;
 import de.thm.arsnova.entities.transport.LearningProgressValues;
+import de.thm.arsnova.persistance.SessionStatisticsRepository;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -50,7 +50,7 @@ public class QuestionBasedLearningProgressTest {
 	@Before
 	public void setUp() {
 		this.courseScore = new CourseScore();
-		IDatabaseDao db = mock(IDatabaseDao.class);
+		SessionStatisticsRepository db = mock(SessionStatisticsRepository.class);
 		when(db.getLearningProgress(null)).thenReturn(courseScore);
 		this.lp = new QuestionBasedLearningProgress(db);
 	}
-- 
GitLab