From a12501118e2eddcf899dacae715d046c3ea1b3b1 Mon Sep 17 00:00:00 2001
From: Christoph Thelen <christoph.thelen@mni.thm.de>
Date: Thu, 12 Feb 2015 15:51:10 +0100
Subject: [PATCH] Cache learning progress using new events

Events for all learning progress related actions
are generated, like answering a new question.
The event classes are used as a tag to evict
the cache based on the session.
---
 .../java/de/thm/arsnova/dao/CouchDBDao.java   |  1 +
 .../domain/ILearningProgressFactory.java      | 24 +++++++
 .../domain/LearningProgressFactory.java       | 65 ++++++++++++++++++-
 .../domain/LearningProgressListener.java      | 38 +++++++++++
 .../events/DeleteAllLectureAnswersEvent.java  | 35 ++++++++++
 .../DeleteAllPreparationAnswersEvent.java     | 34 ++++++++++
 .../DeleteAllQuestionsAnswersEvent.java       | 34 ++++++++++
 .../thm/arsnova/events/DeleteAnswerEvent.java | 14 +---
 .../events/DeleteInterposedQuestionEvent.java | 12 ++--
 .../arsnova/events/DeleteQuestionEvent.java   | 35 ++++++++++
 .../de/thm/arsnova/events/NewAnswerEvent.java | 14 +---
 .../events/NewInterposedQuestionEvent.java    | 12 +---
 .../thm/arsnova/events/NewQuestionEvent.java  | 13 +---
 .../thm/arsnova/events/NovaEventVisitor.java  | 10 +++
 .../de/thm/arsnova/events/SessionEvent.java   | 36 ++++++++++
 .../thm/arsnova/services/QuestionService.java | 29 +++++++--
 .../thm/arsnova/services/SessionService.java  |  4 +-
 .../arsnova/socket/ARSnovaSocketIOServer.java | 35 ++++++++++
 18 files changed, 389 insertions(+), 56 deletions(-)
 create mode 100644 src/main/java/de/thm/arsnova/domain/ILearningProgressFactory.java
 create mode 100644 src/main/java/de/thm/arsnova/domain/LearningProgressListener.java
 create mode 100644 src/main/java/de/thm/arsnova/events/DeleteAllLectureAnswersEvent.java
 create mode 100644 src/main/java/de/thm/arsnova/events/DeleteAllPreparationAnswersEvent.java
 create mode 100644 src/main/java/de/thm/arsnova/events/DeleteAllQuestionsAnswersEvent.java
 create mode 100644 src/main/java/de/thm/arsnova/events/DeleteQuestionEvent.java
 create mode 100644 src/main/java/de/thm/arsnova/events/SessionEvent.java

diff --git a/src/main/java/de/thm/arsnova/dao/CouchDBDao.java b/src/main/java/de/thm/arsnova/dao/CouchDBDao.java
index ddf611eda..dc0e26e6a 100644
--- a/src/main/java/de/thm/arsnova/dao/CouchDBDao.java
+++ b/src/main/java/de/thm/arsnova/dao/CouchDBDao.java
@@ -1634,6 +1634,7 @@ public class CouchDBDao implements IDatabaseDao {
 		return true;
 	}
 
+	@Cacheable("learningprogress")
 	@Override
 	public CourseScore getLearningProgress(final Session session) {
 		final NovaView maximumValueView = new NovaView("learning_progress/maximum_value_of_question");
diff --git a/src/main/java/de/thm/arsnova/domain/ILearningProgressFactory.java b/src/main/java/de/thm/arsnova/domain/ILearningProgressFactory.java
new file mode 100644
index 000000000..48b63c66e
--- /dev/null
+++ b/src/main/java/de/thm/arsnova/domain/ILearningProgressFactory.java
@@ -0,0 +1,24 @@
+/*
+ * This file is part of ARSnova Backend.
+ * Copyright (C) 2012-2015 The ARSnova Team
+ *
+ * ARSnova Backend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * ARSnova Backend is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package de.thm.arsnova.domain;
+
+public interface ILearningProgressFactory {
+
+	public abstract LearningProgress createFromType(String progressType);
+
+}
\ No newline at end of file
diff --git a/src/main/java/de/thm/arsnova/domain/LearningProgressFactory.java b/src/main/java/de/thm/arsnova/domain/LearningProgressFactory.java
index 0f819d410..ef69aadcb 100644
--- a/src/main/java/de/thm/arsnova/domain/LearningProgressFactory.java
+++ b/src/main/java/de/thm/arsnova/domain/LearningProgressFactory.java
@@ -1,16 +1,45 @@
+/*
+ * This file is part of ARSnova Backend.
+ * Copyright (C) 2012-2015 The ARSnova Team
+ *
+ * ARSnova Backend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * ARSnova Backend is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
 package de.thm.arsnova.domain;
 
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.annotation.CacheEvict;
 import org.springframework.stereotype.Component;
 
 import de.thm.arsnova.dao.IDatabaseDao;
+import de.thm.arsnova.events.DeleteAllLectureAnswersEvent;
+import de.thm.arsnova.events.DeleteAllPreparationAnswersEvent;
+import de.thm.arsnova.events.DeleteAllQuestionsAnswersEvent;
+import de.thm.arsnova.events.DeleteAnswerEvent;
+import de.thm.arsnova.events.DeleteInterposedQuestionEvent;
+import de.thm.arsnova.events.DeleteQuestionEvent;
+import de.thm.arsnova.events.NewAnswerEvent;
+import de.thm.arsnova.events.NewInterposedQuestionEvent;
+import de.thm.arsnova.events.NewQuestionEvent;
+import de.thm.arsnova.events.NovaEventVisitor;
 
 @Component
-public class LearningProgressFactory {
+public class LearningProgressFactory implements NovaEventVisitor, ILearningProgressFactory {
 
 	@Autowired
 	private IDatabaseDao databaseDao;
 
+	@Override
 	public LearningProgress createFromType(String progressType) {
 		if (progressType.equals("questions")) {
 			return new QuestionBasedLearningProgress(databaseDao);
@@ -19,4 +48,38 @@ public class LearningProgressFactory {
 		}
 	}
 
+	@Override
+	public void visit(NewInterposedQuestionEvent event) {}
+
+	@Override
+	public void visit(DeleteInterposedQuestionEvent deleteInterposedQuestionEvent) {}
+
+	@CacheEvict(value = "learningprogress", key = "#event.Session")
+	@Override
+	public void visit(NewQuestionEvent event) {}
+
+	@CacheEvict(value = "learningprogress", key = "#event.Session")
+	@Override
+	public void visit(NewAnswerEvent event) {}
+
+	@CacheEvict(value = "learningprogress", key = "#event.Session")
+	@Override
+	public void visit(DeleteAnswerEvent event) {}
+
+	@CacheEvict(value = "learningprogress", key = "#event.Session")
+	@Override
+	public void visit(DeleteQuestionEvent event) {}
+
+	@CacheEvict(value = "learningprogress", key = "#event.Session")
+	@Override
+	public void visit(DeleteAllQuestionsAnswersEvent event) {}
+
+	@CacheEvict(value = "learningprogress", key = "#event.Session")
+	@Override
+	public void visit(DeleteAllPreparationAnswersEvent event) {}
+
+	@CacheEvict(value = "learningprogress", key = "#event.Session")
+	@Override
+	public void visit(DeleteAllLectureAnswersEvent event) {}
+
 }
diff --git a/src/main/java/de/thm/arsnova/domain/LearningProgressListener.java b/src/main/java/de/thm/arsnova/domain/LearningProgressListener.java
new file mode 100644
index 000000000..28bc8e0ee
--- /dev/null
+++ b/src/main/java/de/thm/arsnova/domain/LearningProgressListener.java
@@ -0,0 +1,38 @@
+/*
+ * This file is part of ARSnova Backend.
+ * Copyright (C) 2012-2015 The ARSnova Team
+ *
+ * ARSnova Backend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * ARSnova Backend is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package de.thm.arsnova.domain;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationListener;
+import org.springframework.stereotype.Component;
+
+import de.thm.arsnova.events.NovaEvent;
+import de.thm.arsnova.events.NovaEventVisitor;
+
+@Component
+public class LearningProgressListener implements ApplicationListener<NovaEvent> {
+
+	@Autowired
+	private ILearningProgressFactory learningProgressFactory;
+
+	@Override
+	public void onApplicationEvent(NovaEvent event) {
+		event.accept((NovaEventVisitor) learningProgressFactory);
+	}
+
+}
diff --git a/src/main/java/de/thm/arsnova/events/DeleteAllLectureAnswersEvent.java b/src/main/java/de/thm/arsnova/events/DeleteAllLectureAnswersEvent.java
new file mode 100644
index 000000000..132f2f450
--- /dev/null
+++ b/src/main/java/de/thm/arsnova/events/DeleteAllLectureAnswersEvent.java
@@ -0,0 +1,35 @@
+/*
+ * This file is part of ARSnova Backend.
+ * Copyright (C) 2012-2015 The ARSnova Team
+ *
+ * ARSnova Backend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * ARSnova Backend is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package de.thm.arsnova.events;
+
+import de.thm.arsnova.entities.Session;
+
+public class DeleteAllLectureAnswersEvent extends SessionEvent {
+
+	private static final long serialVersionUID = 1L;
+
+	public DeleteAllLectureAnswersEvent(Object source, Session session) {
+		super(source, session);
+	}
+
+	@Override
+	public void accept(NovaEventVisitor visitor) {
+		visitor.visit(this);
+	}
+
+}
diff --git a/src/main/java/de/thm/arsnova/events/DeleteAllPreparationAnswersEvent.java b/src/main/java/de/thm/arsnova/events/DeleteAllPreparationAnswersEvent.java
new file mode 100644
index 000000000..4c823f768
--- /dev/null
+++ b/src/main/java/de/thm/arsnova/events/DeleteAllPreparationAnswersEvent.java
@@ -0,0 +1,34 @@
+/*
+ * This file is part of ARSnova Backend.
+ * Copyright (C) 2012-2015 The ARSnova Team
+ *
+ * ARSnova Backend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * ARSnova Backend is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package de.thm.arsnova.events;
+
+import de.thm.arsnova.entities.Session;
+
+public class DeleteAllPreparationAnswersEvent extends SessionEvent {
+
+	private static final long serialVersionUID = 1L;
+
+	public DeleteAllPreparationAnswersEvent(Object source, Session session) {
+		super(source, session);
+	}
+
+	@Override
+	public void accept(NovaEventVisitor visitor) {
+		visitor.visit(this);
+	}
+}
diff --git a/src/main/java/de/thm/arsnova/events/DeleteAllQuestionsAnswersEvent.java b/src/main/java/de/thm/arsnova/events/DeleteAllQuestionsAnswersEvent.java
new file mode 100644
index 000000000..6ac6683c4
--- /dev/null
+++ b/src/main/java/de/thm/arsnova/events/DeleteAllQuestionsAnswersEvent.java
@@ -0,0 +1,34 @@
+/*
+ * This file is part of ARSnova Backend.
+ * Copyright (C) 2012-2015 The ARSnova Team
+ *
+ * ARSnova Backend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * ARSnova Backend is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package de.thm.arsnova.events;
+
+import de.thm.arsnova.entities.Session;
+
+public class DeleteAllQuestionsAnswersEvent extends SessionEvent {
+
+	private static final long serialVersionUID = 1L;
+
+	public DeleteAllQuestionsAnswersEvent(Object source, Session session) {
+		super(source, session);
+	}
+
+	@Override
+	public void accept(NovaEventVisitor visitor) {
+		visitor.visit(this);
+	}
+}
diff --git a/src/main/java/de/thm/arsnova/events/DeleteAnswerEvent.java b/src/main/java/de/thm/arsnova/events/DeleteAnswerEvent.java
index e7a7be35a..02ed5a9c0 100644
--- a/src/main/java/de/thm/arsnova/events/DeleteAnswerEvent.java
+++ b/src/main/java/de/thm/arsnova/events/DeleteAnswerEvent.java
@@ -20,18 +20,15 @@ package de.thm.arsnova.events;
 import de.thm.arsnova.entities.Question;
 import de.thm.arsnova.entities.Session;
 
-public class DeleteAnswerEvent extends NovaEvent {
+public class DeleteAnswerEvent extends SessionEvent {
 
 	private static final long serialVersionUID = 1L;
 
 	private final Question question;
 
-	private final Session session;
-
-	public DeleteAnswerEvent(Object source, Question question, Session session) {
-		super(source);
+	public DeleteAnswerEvent(Object source, Session session, Question question) {
+		super(source, session);
 		this.question = question;
-		this.session = session;
 	}
 
 	@Override
@@ -42,9 +39,4 @@ public class DeleteAnswerEvent extends NovaEvent {
 	public Question getQuestion() {
 		return question;
 	}
-
-	public Session getSession() {
-		return session;
-	}
-
 }
diff --git a/src/main/java/de/thm/arsnova/events/DeleteInterposedQuestionEvent.java b/src/main/java/de/thm/arsnova/events/DeleteInterposedQuestionEvent.java
index 185ebb3f9..a0dbfdef4 100644
--- a/src/main/java/de/thm/arsnova/events/DeleteInterposedQuestionEvent.java
+++ b/src/main/java/de/thm/arsnova/events/DeleteInterposedQuestionEvent.java
@@ -20,24 +20,24 @@ package de.thm.arsnova.events;
 import de.thm.arsnova.entities.InterposedQuestion;
 import de.thm.arsnova.entities.Session;
 
-public class DeleteInterposedQuestionEvent extends NovaEvent {
+public class DeleteInterposedQuestionEvent extends SessionEvent {
 
 	private static final long serialVersionUID = 1L;
 
-	private final Session session;
-
 	private final InterposedQuestion question;
 
 	public DeleteInterposedQuestionEvent(Object source, Session session, InterposedQuestion question) {
-		super(source);
-		this.session = session;
+		super(source, session);
 		this.question = question;
 	}
 
 	@Override
 	public void accept(NovaEventVisitor visitor) {
-		// TODO Auto-generated method stub
+		visitor.visit(this);
+	}
 
+	public InterposedQuestion getQuestion() {
+		return question;
 	}
 
 }
diff --git a/src/main/java/de/thm/arsnova/events/DeleteQuestionEvent.java b/src/main/java/de/thm/arsnova/events/DeleteQuestionEvent.java
new file mode 100644
index 000000000..4c063a96c
--- /dev/null
+++ b/src/main/java/de/thm/arsnova/events/DeleteQuestionEvent.java
@@ -0,0 +1,35 @@
+/*
+ * This file is part of ARSnova Backend.
+ * Copyright (C) 2012-2015 The ARSnova Team
+ *
+ * ARSnova Backend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * ARSnova Backend is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package de.thm.arsnova.events;
+
+import de.thm.arsnova.entities.Session;
+
+public class DeleteQuestionEvent extends SessionEvent {
+
+	private static final long serialVersionUID = 1L;
+
+	public DeleteQuestionEvent(Object source, Session session) {
+		super(source, session);
+	}
+
+	@Override
+	public void accept(NovaEventVisitor visitor) {
+		visitor.visit(this);
+	}
+
+}
diff --git a/src/main/java/de/thm/arsnova/events/NewAnswerEvent.java b/src/main/java/de/thm/arsnova/events/NewAnswerEvent.java
index d8f6149a3..624258732 100644
--- a/src/main/java/de/thm/arsnova/events/NewAnswerEvent.java
+++ b/src/main/java/de/thm/arsnova/events/NewAnswerEvent.java
@@ -22,7 +22,7 @@ import de.thm.arsnova.entities.Question;
 import de.thm.arsnova.entities.Session;
 import de.thm.arsnova.entities.User;
 
-public class NewAnswerEvent extends NovaEvent {
+public class NewAnswerEvent extends SessionEvent {
 
 	private static final long serialVersionUID = 1L;
 
@@ -32,14 +32,11 @@ public class NewAnswerEvent extends NovaEvent {
 
 	private final Question question;
 
-	private final Session session;
-
-	public NewAnswerEvent(Object source, Answer answer, User user, Question question, Session session) {
-		super(source);
+	public NewAnswerEvent(Object source, Session session, Answer answer, User user, Question question) {
+		super(source, session);
 		this.answer = answer;
 		this.user = user;
 		this.question = question;
-		this.session = session;
 	}
 
 	@Override
@@ -58,9 +55,4 @@ public class NewAnswerEvent extends NovaEvent {
 	public Question getQuestion() {
 		return question;
 	}
-
-	public Session getSession() {
-		return session;
-	}
-
 }
diff --git a/src/main/java/de/thm/arsnova/events/NewInterposedQuestionEvent.java b/src/main/java/de/thm/arsnova/events/NewInterposedQuestionEvent.java
index 52c545f03..2d0fbfcee 100644
--- a/src/main/java/de/thm/arsnova/events/NewInterposedQuestionEvent.java
+++ b/src/main/java/de/thm/arsnova/events/NewInterposedQuestionEvent.java
@@ -20,21 +20,15 @@ package de.thm.arsnova.events;
 import de.thm.arsnova.entities.InterposedQuestion;
 import de.thm.arsnova.entities.Session;
 
-public class NewInterposedQuestionEvent extends NovaEvent {
+public class NewInterposedQuestionEvent extends SessionEvent {
 
 	private static final long serialVersionUID = 1L;
 
-	private final Session session;
 	private final InterposedQuestion question;
 
-	public NewInterposedQuestionEvent(Object source, InterposedQuestion question, Session session) {
-		super(source);
+	public NewInterposedQuestionEvent(Object source, Session session, InterposedQuestion question) {
+		super(source, session);
 		this.question = question;
-		this.session = session;
-	}
-
-	public Session getSession() {
-		return session;
 	}
 
 	public InterposedQuestion getQuestion() {
diff --git a/src/main/java/de/thm/arsnova/events/NewQuestionEvent.java b/src/main/java/de/thm/arsnova/events/NewQuestionEvent.java
index 84bcf4ccc..898104edc 100644
--- a/src/main/java/de/thm/arsnova/events/NewQuestionEvent.java
+++ b/src/main/java/de/thm/arsnova/events/NewQuestionEvent.java
@@ -20,28 +20,21 @@ package de.thm.arsnova.events;
 import de.thm.arsnova.entities.Question;
 import de.thm.arsnova.entities.Session;
 
-public class NewQuestionEvent extends NovaEvent {
+public class NewQuestionEvent extends SessionEvent {
 
 	private static final long serialVersionUID = 1L;
 
 	private final Question question;
 
-	private final Session session;
-
-	public NewQuestionEvent(Object source, Question question, Session session) {
-		super(source);
+	public NewQuestionEvent(Object source, Session session, Question question) {
+		super(source, session);
 		this.question = question;
-		this.session = session;
 	}
 
 	public Question getQuestion() {
 		return question;
 	}
 
-	public Session getSession() {
-		return session;
-	}
-
 	@Override
 	public void accept(NovaEventVisitor visitor) {
 		visitor.visit(this);
diff --git a/src/main/java/de/thm/arsnova/events/NovaEventVisitor.java b/src/main/java/de/thm/arsnova/events/NovaEventVisitor.java
index 6764f2d17..75968075a 100644
--- a/src/main/java/de/thm/arsnova/events/NovaEventVisitor.java
+++ b/src/main/java/de/thm/arsnova/events/NovaEventVisitor.java
@@ -21,10 +21,20 @@ public interface NovaEventVisitor {
 
 	void visit(NewInterposedQuestionEvent newInterposedQuestionEvent);
 
+	void visit(DeleteInterposedQuestionEvent deleteInterposedQuestionEvent);
+
 	void visit(NewQuestionEvent newQuestionEvent);
 
 	void visit(NewAnswerEvent newAnswerEvent);
 
 	void visit(DeleteAnswerEvent deleteAnswerEvent);
 
+	void visit(DeleteQuestionEvent deleteQuestionEvent);
+
+	void visit(DeleteAllQuestionsAnswersEvent deleteAllAnswersEvent);
+
+	void visit(DeleteAllPreparationAnswersEvent deleteAllPreparationAnswersEvent);
+
+	void visit(DeleteAllLectureAnswersEvent deleteAllLectureAnswersEvent);
+
 }
diff --git a/src/main/java/de/thm/arsnova/events/SessionEvent.java b/src/main/java/de/thm/arsnova/events/SessionEvent.java
new file mode 100644
index 000000000..2c34956c0
--- /dev/null
+++ b/src/main/java/de/thm/arsnova/events/SessionEvent.java
@@ -0,0 +1,36 @@
+/*
+ * This file is part of ARSnova Backend.
+ * Copyright (C) 2012-2015 The ARSnova Team
+ *
+ * ARSnova Backend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * ARSnova Backend is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package de.thm.arsnova.events;
+
+import de.thm.arsnova.entities.Session;
+
+public abstract class SessionEvent extends NovaEvent {
+
+	private static final long serialVersionUID = 1L;
+
+	private final Session session;
+
+	public SessionEvent(Object source, Session session) {
+		super(source);
+		this.session = session;
+	}
+
+	public Session getSession() {
+		return session;
+	}
+}
diff --git a/src/main/java/de/thm/arsnova/services/QuestionService.java b/src/main/java/de/thm/arsnova/services/QuestionService.java
index 93f310dde..b1e27a79f 100644
--- a/src/main/java/de/thm/arsnova/services/QuestionService.java
+++ b/src/main/java/de/thm/arsnova/services/QuestionService.java
@@ -26,6 +26,7 @@ import java.util.List;
 import java.util.Map;
 
 import de.thm.arsnova.exceptions.ForbiddenException;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -43,8 +44,12 @@ import de.thm.arsnova.entities.InterposedReadingCount;
 import de.thm.arsnova.entities.Question;
 import de.thm.arsnova.entities.Session;
 import de.thm.arsnova.entities.User;
+import de.thm.arsnova.events.DeleteAllLectureAnswersEvent;
+import de.thm.arsnova.events.DeleteAllPreparationAnswersEvent;
+import de.thm.arsnova.events.DeleteAllQuestionsAnswersEvent;
 import de.thm.arsnova.events.DeleteAnswerEvent;
 import de.thm.arsnova.events.DeleteInterposedQuestionEvent;
+import de.thm.arsnova.events.DeleteQuestionEvent;
 import de.thm.arsnova.events.NewAnswerEvent;
 import de.thm.arsnova.events.NewInterposedQuestionEvent;
 import de.thm.arsnova.events.NewQuestionEvent;
@@ -120,7 +125,7 @@ public class QuestionService implements IQuestionService, ApplicationEventPublis
 		}
 
 		final Question result = databaseDao.saveQuestion(session, question);
-		final NewQuestionEvent event = new NewQuestionEvent(this, result, session);
+		final NewQuestionEvent event = new NewQuestionEvent(this, session, result);
 		this.publisher.publishEvent(event);
 
 		return result;
@@ -133,7 +138,7 @@ public class QuestionService implements IQuestionService, ApplicationEventPublis
 		final InterposedQuestion result = databaseDao.saveQuestion(session, question, userService.getCurrentUser());
 
 		if (null != result) {
-			final NewInterposedQuestionEvent event = new NewInterposedQuestionEvent(this, result, session);
+			final NewInterposedQuestionEvent event = new NewInterposedQuestionEvent(this, session, result);
 			this.publisher.publishEvent(event);
 			return true;
 		}
@@ -168,6 +173,9 @@ public class QuestionService implements IQuestionService, ApplicationEventPublis
 			throw new UnauthorizedException();
 		}
 		databaseDao.deleteQuestionWithAnswers(question);
+
+		final DeleteQuestionEvent event = new DeleteQuestionEvent(this, session);
+		this.publisher.publishEvent(event);
 	}
 
 	@Override
@@ -175,6 +183,9 @@ public class QuestionService implements IQuestionService, ApplicationEventPublis
 	public void deleteAllQuestions(final String sessionKeyword) {
 		final Session session = getSessionWithAuthCheck(sessionKeyword);
 		databaseDao.deleteAllQuestionsWithAnswers(session);
+
+		final DeleteQuestionEvent event = new DeleteQuestionEvent(this, session);
+		this.publisher.publishEvent(event);
 	}
 
 	private Session getSessionWithAuthCheck(final String sessionKeyword) {
@@ -419,7 +430,7 @@ public class QuestionService implements IQuestionService, ApplicationEventPublis
 		final Question result = databaseDao.updateQuestion(question);
 
 		if (!oldQuestion.isActive() && question.isActive()) {
-			final NewQuestionEvent event = new NewQuestionEvent(this, result, session);
+			final NewQuestionEvent event = new NewQuestionEvent(this, session, result);
 			this.publisher.publishEvent(event);
 		}
 
@@ -439,7 +450,7 @@ public class QuestionService implements IQuestionService, ApplicationEventPublis
 
 		final Answer result = databaseDao.saveAnswer(theAnswer, user);
 		final Session session = databaseDao.getSessionFromKeyword(question.getSessionKeyword());
-		this.publisher.publishEvent(new NewAnswerEvent(this, result, user, question, session));
+		this.publisher.publishEvent(new NewAnswerEvent(this, session, result, user, question));
 
 		return result;
 	}
@@ -456,7 +467,7 @@ public class QuestionService implements IQuestionService, ApplicationEventPublis
 		final Question question = getQuestion(answer.getQuestionId());
 		final Answer result = databaseDao.updateAnswer(realAnswer);
 		final Session session = databaseDao.getSessionFromKeyword(question.getSessionKeyword());
-		this.publisher.publishEvent(new NewAnswerEvent(this, result, user, question, session));
+		this.publisher.publishEvent(new NewAnswerEvent(this, session, result, user, question));
 
 		return result;
 	}
@@ -475,7 +486,7 @@ public class QuestionService implements IQuestionService, ApplicationEventPublis
 		}
 		databaseDao.deleteAnswer(answerId);
 
-		this.publisher.publishEvent(new DeleteAnswerEvent(this, question, session));
+		this.publisher.publishEvent(new DeleteAnswerEvent(this, session, question));
 	}
 
 	@Override
@@ -641,6 +652,8 @@ public class QuestionService implements IQuestionService, ApplicationEventPublis
 			throw new UnauthorizedException();
 		}
 		databaseDao.deleteAllQuestionsAnswers(session);
+
+		this.publisher.publishEvent(new DeleteAllQuestionsAnswersEvent(this, session));
 	}
 
 	@Override
@@ -648,6 +661,8 @@ public class QuestionService implements IQuestionService, ApplicationEventPublis
 	public void deleteAllPreparationAnswers(String sessionkey) {
 		final Session session = getSession(sessionkey);
 		databaseDao.deleteAllPreparationAnswers(session);
+
+		this.publisher.publishEvent(new DeleteAllPreparationAnswersEvent(this, session));
 	}
 
 	@Override
@@ -655,6 +670,8 @@ public class QuestionService implements IQuestionService, ApplicationEventPublis
 	public void deleteAllLectureAnswers(String sessionkey) {
 		final Session session = getSession(sessionkey);
 		databaseDao.deleteAllLectureAnswers(session);
+
+		this.publisher.publishEvent(new DeleteAllLectureAnswersEvent(this, session));
 	}
 
 	@Override
diff --git a/src/main/java/de/thm/arsnova/services/SessionService.java b/src/main/java/de/thm/arsnova/services/SessionService.java
index 9d490dad1..ff05e7d95 100644
--- a/src/main/java/de/thm/arsnova/services/SessionService.java
+++ b/src/main/java/de/thm/arsnova/services/SessionService.java
@@ -34,8 +34,8 @@ 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.domain.LearningProgressFactory;
 import de.thm.arsnova.entities.Question;
 import de.thm.arsnova.entities.Session;
 import de.thm.arsnova.entities.SessionInfo;
@@ -96,7 +96,7 @@ public class SessionService implements ISessionService {
 	private ARSnovaSocketIOServer socketIoServer;
 
 	@Autowired
-	private LearningProgressFactory learningProgressFactory;
+	private ILearningProgressFactory learningProgressFactory;
 
 	@Autowired(required = false)
 	private ConnectorClient connectorClient;
diff --git a/src/main/java/de/thm/arsnova/socket/ARSnovaSocketIOServer.java b/src/main/java/de/thm/arsnova/socket/ARSnovaSocketIOServer.java
index 8cf4e7451..62a0d1902 100644
--- a/src/main/java/de/thm/arsnova/socket/ARSnovaSocketIOServer.java
+++ b/src/main/java/de/thm/arsnova/socket/ARSnovaSocketIOServer.java
@@ -49,7 +49,12 @@ import com.corundumstudio.socketio.protocol.PacketType;
 import de.thm.arsnova.entities.InterposedQuestion;
 import de.thm.arsnova.entities.User;
 import de.thm.arsnova.entities.transport.LearningProgressType;
+import de.thm.arsnova.events.DeleteAllLectureAnswersEvent;
+import de.thm.arsnova.events.DeleteAllPreparationAnswersEvent;
+import de.thm.arsnova.events.DeleteAllQuestionsAnswersEvent;
 import de.thm.arsnova.events.DeleteAnswerEvent;
+import de.thm.arsnova.events.DeleteInterposedQuestionEvent;
+import de.thm.arsnova.events.DeleteQuestionEvent;
 import de.thm.arsnova.events.NewAnswerEvent;
 import de.thm.arsnova.events.NewInterposedQuestionEvent;
 import de.thm.arsnova.events.NewQuestionEvent;
@@ -455,6 +460,36 @@ public class ARSnovaSocketIOServer implements ApplicationListener<NovaEvent>, No
 		broadcastInSession(sessionKey, "countPreparationQuestionAnswers", questionService.countPreparationQuestionAnswersInternal(sessionKey));
 	}
 
+	@Override
+	public void visit(DeleteQuestionEvent deleteQuestionEvent) {
+		// TODO Auto-generated method stub
+
+	}
+
+	@Override
+	public void visit(DeleteAllQuestionsAnswersEvent deleteAllAnswersEvent) {
+		// TODO Auto-generated method stub
+
+	}
+
+	@Override
+	public void visit(DeleteAllPreparationAnswersEvent deleteAllPreparationAnswersEvent) {
+		// TODO Auto-generated method stub
+
+	}
+
+	@Override
+	public void visit(DeleteAllLectureAnswersEvent deleteAllLectureAnswersEvent) {
+		// TODO Auto-generated method stub
+
+	}
+
+	@Override
+	public void visit(DeleteInterposedQuestionEvent deleteInterposedQuestionEvent) {
+		// TODO Auto-generated method stub
+
+	}
+
 	@Override
 	public void onApplicationEvent(NovaEvent event) {
 		event.accept(this);
-- 
GitLab