From d3948050740152c30595f2b8345628d0c82d27d9 Mon Sep 17 00:00:00 2001
From: Daniel Gerhardt <code@dgerhardt.net>
Date: Mon, 5 Mar 2018 12:45:35 +0100
Subject: [PATCH] Add IDs to content groups of Room when creating Content

Rooms are now updated when Content is created or deleted.

Update handling is NYI.
---
 .../java/de/thm/arsnova/entities/Content.java | 18 +++++++----
 .../java/de/thm/arsnova/entities/Room.java    | 12 +++++--
 .../entities/migration/FromV2Migrator.java    |  1 -
 .../entities/migration/ToV2Migrator.java      |  1 -
 .../de/thm/arsnova/events/LockVoteEvent.java  |  3 +-
 .../events/PiRoundDelayedStartEvent.java      |  3 +-
 .../thm/arsnova/events/PiRoundEndEvent.java   |  3 +-
 .../thm/arsnova/events/PiRoundResetEvent.java |  3 +-
 .../thm/arsnova/events/UnlockVoteEvent.java   |  3 +-
 .../couchdb/CouchDbRoomRepository.java        |  2 +-
 .../arsnova/services/ContentServiceImpl.java  | 32 +++++++++++++------
 .../websocket/ArsnovaSocketioServerImpl.java  |  4 +--
 .../arsnova/websocket/message/Content.java    |  3 +-
 13 files changed, 59 insertions(+), 29 deletions(-)

diff --git a/src/main/java/de/thm/arsnova/entities/Content.java b/src/main/java/de/thm/arsnova/entities/Content.java
index 9988359aa..aef47c63a 100644
--- a/src/main/java/de/thm/arsnova/entities/Content.java
+++ b/src/main/java/de/thm/arsnova/entities/Content.java
@@ -5,8 +5,10 @@ import com.fasterxml.jackson.annotation.JsonView;
 import de.thm.arsnova.entities.serialization.View;
 
 import java.util.Date;
+import java.util.HashSet;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Set;
 
 @JsonTypeInfo(
 		use = JsonTypeInfo.Id.NAME,
@@ -96,7 +98,7 @@ public class Content extends Entity {
 	private String subject;
 	private String body;
 	private Format format;
-	private String group;
+	private Set<String> groups;
 	private boolean abstentionsAllowed;
 	private State state;
 	private Date timestamp;
@@ -144,13 +146,17 @@ public class Content extends Entity {
 	}
 
 	@JsonView(View.Public.class)
-	public String getGroup() {
-		return group;
+	public Set<String> getGroups() {
+		if (groups == null) {
+			groups = new HashSet<>();
+		}
+
+		return groups;
 	}
 
 	@JsonView(View.Public.class)
-	public void setGroup(final String group) {
-		this.group = group;
+	public void setGroups(final Set<String> groups) {
+		this.groups = groups;
 	}
 
 	@JsonView({View.Persistence.class, View.Public.class})
@@ -227,7 +233,7 @@ public class Content extends Entity {
 				Objects.equals(subject, content.subject) &&
 				Objects.equals(body, content.body) &&
 				format == content.format &&
-				Objects.equals(group, content.group) &&
+				Objects.equals(groups, content.groups) &&
 				Objects.equals(timestamp, content.timestamp);
 	}
 }
diff --git a/src/main/java/de/thm/arsnova/entities/Room.java b/src/main/java/de/thm/arsnova/entities/Room.java
index 9fbfed17c..588f2e716 100644
--- a/src/main/java/de/thm/arsnova/entities/Room.java
+++ b/src/main/java/de/thm/arsnova/entities/Room.java
@@ -3,22 +3,28 @@ package de.thm.arsnova.entities;
 import com.fasterxml.jackson.annotation.JsonView;
 import de.thm.arsnova.entities.serialization.View;
 
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Set;
 
 public class Room extends Entity {
 	public static class ContentGroup {
-		private List<String> contentIds;
+		private Set<String> contentIds;
 		private boolean autoSort;
 
 		@JsonView({View.Persistence.class, View.Public.class})
-		public List<String> getContentIds() {
+		public Set<String> getContentIds() {
+			if (contentIds == null) {
+				contentIds = new HashSet<>();
+			}
+
 			return contentIds;
 		}
 
 		@JsonView({View.Persistence.class, View.Public.class})
-		public void setContentIds(final List<String> contentIds) {
+		public void setContentIds(final Set<String> contentIds) {
 			this.contentIds = contentIds;
 		}
 
diff --git a/src/main/java/de/thm/arsnova/entities/migration/FromV2Migrator.java b/src/main/java/de/thm/arsnova/entities/migration/FromV2Migrator.java
index f4774157a..2eaa7a161 100644
--- a/src/main/java/de/thm/arsnova/entities/migration/FromV2Migrator.java
+++ b/src/main/java/de/thm/arsnova/entities/migration/FromV2Migrator.java
@@ -215,7 +215,6 @@ public class FromV2Migrator {
 		to.setRoomId(from.getSessionId());
 		to.setSubject(from.getSubject());
 		to.setBody(from.getText());
-		to.setGroup(from.getQuestionVariant());
 		to.setAbstentionsAllowed(from.isAbstention());
 		to.setAbstentionsAllowed(from.isAbstention());
 		de.thm.arsnova.entities.Content.State state = to.getState();
diff --git a/src/main/java/de/thm/arsnova/entities/migration/ToV2Migrator.java b/src/main/java/de/thm/arsnova/entities/migration/ToV2Migrator.java
index 29c85627b..39f483a95 100644
--- a/src/main/java/de/thm/arsnova/entities/migration/ToV2Migrator.java
+++ b/src/main/java/de/thm/arsnova/entities/migration/ToV2Migrator.java
@@ -177,7 +177,6 @@ public class ToV2Migrator {
 		to.setSessionId(from.getRoomId());
 		to.setSubject(from.getSubject());
 		to.setText(from.getBody());
-		to.setQuestionVariant(from.getGroup());
 		to.setAbstention(from.isAbstentionsAllowed());
 
 		if (from instanceof ChoiceQuestionContent) {
diff --git a/src/main/java/de/thm/arsnova/events/LockVoteEvent.java b/src/main/java/de/thm/arsnova/events/LockVoteEvent.java
index 0d7e263ce..e511a4c9c 100644
--- a/src/main/java/de/thm/arsnova/events/LockVoteEvent.java
+++ b/src/main/java/de/thm/arsnova/events/LockVoteEvent.java
@@ -42,7 +42,8 @@ public class LockVoteEvent extends RoomEvent {
 	}
 
 	public String getGroup() {
-		return this.content.getGroup();
+		/* FIXME: Event does not support content with multiple groups */
+		return content.getGroups().toArray(new String[1])[0];
 	}
 
 	public Boolean getVotingDisabled() {
diff --git a/src/main/java/de/thm/arsnova/events/PiRoundDelayedStartEvent.java b/src/main/java/de/thm/arsnova/events/PiRoundDelayedStartEvent.java
index 510bbf7a9..bd0a79ca2 100644
--- a/src/main/java/de/thm/arsnova/events/PiRoundDelayedStartEvent.java
+++ b/src/main/java/de/thm/arsnova/events/PiRoundDelayedStartEvent.java
@@ -40,7 +40,8 @@ public class PiRoundDelayedStartEvent extends RoomEvent {
 	public PiRoundDelayedStartEvent(Object source, Room room, Content content) {
 		super(source, room);
 		this.questionId = content.getId();
-		this.group = content.getGroup();
+		/* FIXME: Event does not support content with multiple groups */
+		this.group = content.getGroups().toArray(new String[1])[0];
 		this.piRound = content.getState().getRound();
 		this.endTime = content.getState().getRoundEndTimestamp();
 		this.startTime = new Date();
diff --git a/src/main/java/de/thm/arsnova/events/PiRoundEndEvent.java b/src/main/java/de/thm/arsnova/events/PiRoundEndEvent.java
index 188be7b49..0b38d4900 100644
--- a/src/main/java/de/thm/arsnova/events/PiRoundEndEvent.java
+++ b/src/main/java/de/thm/arsnova/events/PiRoundEndEvent.java
@@ -36,7 +36,8 @@ public class PiRoundEndEvent extends RoomEvent {
 	public PiRoundEndEvent(Object source, Room room, Content content) {
 		super(source, room);
 		contentId = content.getId();
-		group = content.getGroup();
+		/* FIXME: Event does not support content with multiple groups */
+		this.group = content.getGroups().toArray(new String[1])[0];
 	}
 
 	@Override
diff --git a/src/main/java/de/thm/arsnova/events/PiRoundResetEvent.java b/src/main/java/de/thm/arsnova/events/PiRoundResetEvent.java
index 52958abd2..9ad99fa92 100644
--- a/src/main/java/de/thm/arsnova/events/PiRoundResetEvent.java
+++ b/src/main/java/de/thm/arsnova/events/PiRoundResetEvent.java
@@ -36,7 +36,8 @@ public class PiRoundResetEvent extends RoomEvent {
 	public PiRoundResetEvent(Object source, Room room, Content content) {
 		super(source, room);
 		contentId = content.getId();
-		group = content.getGroup();
+		/* FIXME: Event does not support content with multiple groups */
+		this.group = content.getGroups().toArray(new String[1])[0];
 	}
 
 	@Override
diff --git a/src/main/java/de/thm/arsnova/events/UnlockVoteEvent.java b/src/main/java/de/thm/arsnova/events/UnlockVoteEvent.java
index 7a974df44..0f0a814b9 100644
--- a/src/main/java/de/thm/arsnova/events/UnlockVoteEvent.java
+++ b/src/main/java/de/thm/arsnova/events/UnlockVoteEvent.java
@@ -42,7 +42,8 @@ public class UnlockVoteEvent extends RoomEvent {
 	}
 
 	public String getGroup() {
-		return this.content.getGroup();
+		/* FIXME: Event does not support content with multiple groups */
+		return content.getGroups().toArray(new String[1])[0];
 	}
 
 	public Boolean getVotingDisabled() {
diff --git a/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbRoomRepository.java b/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbRoomRepository.java
index b03c16b8b..d11af8b7b 100644
--- a/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbRoomRepository.java
+++ b/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbRoomRepository.java
@@ -141,7 +141,7 @@ public class CouchDbRoomRepository extends CouchDbCrudRepository<Room> implement
 //					answerDoc.put("sessionId", a.getRoomId());
 //					answerDoc.put("questionId", a.getContentId());
 //					answerDoc.put("answerSubject", a.getAnswerSubject());
-//					answerDoc.put("questionVariant", a.getGroup());
+//					answerDoc.put("questionVariant", a.getGroups());
 //					answerDoc.put("questionValue", a.getQuestionValue());
 //					answerDoc.put("answerText", a.getAnswerText());
 //					answerDoc.put("answerTextRaw", a.getAnswerTextRaw());
diff --git a/src/main/java/de/thm/arsnova/services/ContentServiceImpl.java b/src/main/java/de/thm/arsnova/services/ContentServiceImpl.java
index 81d19f8e7..d1673162e 100644
--- a/src/main/java/de/thm/arsnova/services/ContentServiceImpl.java
+++ b/src/main/java/de/thm/arsnova/services/ContentServiceImpl.java
@@ -142,9 +142,9 @@ public class ContentServiceImpl extends DefaultEntityServiceImpl<Content> implem
 
 	@Override
 	@Caching(evict = {@CacheEvict(value = "contentlists", key = "#roomId"),
-			@CacheEvict(value = "lecturecontentlists", key = "#roomId", condition = "'lecture'.equals(#content.getGroup())"),
-			@CacheEvict(value = "preparationcontentlists", key = "#roomId", condition = "'preparation'.equals(#content.getGroup())"),
-			@CacheEvict(value = "flashcardcontentlists", key = "#roomId", condition = "'flashcard'.equals(#content.getGroup())") },
+			@CacheEvict(value = "lecturecontentlists", key = "#roomId", condition = "#content.getGroups().contains('lecture')"),
+			@CacheEvict(value = "preparationcontentlists", key = "#roomId", condition = "#content.getGroups().contains('preparation')"),
+			@CacheEvict(value = "flashcardcontentlists", key = "#roomId", condition = "#content.getGroups().contains('flashcard')") },
 			put = {@CachePut(value = "contents", key = "#content.id")})
 	public Content save(final String roomId, final Content content) {
 		content.setRoomId(roomId);
@@ -163,9 +163,9 @@ public class ContentServiceImpl extends DefaultEntityServiceImpl<Content> implem
 	@PreAuthorize("isAuthenticated()")
 	@Caching(evict = {
 			@CacheEvict(value = "contentlists", allEntries = true),
-			@CacheEvict(value = "lecturecontentlists", allEntries = true, condition = "'lecture'.equals(#content.getGroup())"),
-			@CacheEvict(value = "preparationcontentlists", allEntries = true, condition = "'preparation'.equals(#content.getGroup())"),
-			@CacheEvict(value = "flashcardcontentlists", allEntries = true, condition = "'flashcard'.equals(#content.getGroup())") },
+			@CacheEvict(value = "lecturecontentlists", allEntries = true, condition = "#content.getGroups().contains('lecture')"),
+			@CacheEvict(value = "preparationcontentlists", allEntries = true, condition = "#content.getGroups().contains('preparation')"),
+			@CacheEvict(value = "flashcardcontentlists", allEntries = true, condition = "#content.getGroups().contains('flashcard')") },
 			put = {@CachePut(value = "contents", key = "#content.id")})
 	public Content update(final Content content) {
 		final ClientAuthentication user = userService.getCurrentUser();
@@ -189,6 +189,8 @@ public class ContentServiceImpl extends DefaultEntityServiceImpl<Content> implem
 		content.setRevision(oldContent.getRevision());
 		contentRepository.save(content);
 
+		/* TODO: nyi: updating content groups */
+
 		if (!oldContent.getState().isVisible() && content.getState().isVisible()) {
 			final UnlockQuestionEvent event = new UnlockQuestionEvent(this, room, content);
 			this.publisher.publishEvent(event);
@@ -245,6 +247,12 @@ public class ContentServiceImpl extends DefaultEntityServiceImpl<Content> implem
 
 		final Content result = save(room.getId(), content);
 
+		for (final String groupName : result.getGroups()) {
+			Room.ContentGroup group = room.getContentGroups().getOrDefault(groupName, new Room.ContentGroup());
+			group.getContentIds().add(result.getId());
+		}
+		roomRepository.save(room);
+
 		final NewQuestionEvent event = new NewQuestionEvent(this, room, result);
 		this.publisher.publishEvent(event);
 
@@ -258,9 +266,9 @@ public class ContentServiceImpl extends DefaultEntityServiceImpl<Content> implem
 			@CacheEvict("answerlists"),
 			@CacheEvict(value = "contents", key = "#contentId"),
 			@CacheEvict(value = "contentlists", allEntries = true),
-			@CacheEvict(value = "lecturecontentlists", allEntries = true /*, condition = "'lecture'.equals(#content.getGroup())"*/),
-			@CacheEvict(value = "preparationcontentlists", allEntries = true /*, condition = "'preparation'.equals(#content.getGroup())"*/),
-			@CacheEvict(value = "flashcardcontentlists", allEntries = true /*, condition = "'flashcard'.equals(#content.getGroup())"*/) })
+			@CacheEvict(value = "lecturecontentlists", allEntries = true /*, condition = "#content.getGroups().contains('lecture')"*/),
+			@CacheEvict(value = "preparationcontentlists", allEntries = true /*, condition = "#content.getGroups().contains('preparation')"*/),
+			@CacheEvict(value = "flashcardcontentlists", allEntries = true /*, condition = "#content.getGroups().contains('flashcard')"*/) })
 	public void delete(final String contentId) {
 		final Content content = contentRepository.findOne(contentId);
 		if (content == null) {
@@ -272,6 +280,12 @@ public class ContentServiceImpl extends DefaultEntityServiceImpl<Content> implem
 			throw new UnauthorizedException();
 		}
 
+		for (final String groupName : content.getGroups()) {
+			Room.ContentGroup group = room.getContentGroups().getOrDefault(groupName, new Room.ContentGroup());
+			group.getContentIds().remove(content.getId());
+		}
+		roomRepository.save(room);
+
 		try {
 			final int count = answerRepository.deleteByContentId(contentId);
 			contentRepository.delete(contentId);
diff --git a/src/main/java/de/thm/arsnova/websocket/ArsnovaSocketioServerImpl.java b/src/main/java/de/thm/arsnova/websocket/ArsnovaSocketioServerImpl.java
index 5cebdb1cc..456673b33 100644
--- a/src/main/java/de/thm/arsnova/websocket/ArsnovaSocketioServerImpl.java
+++ b/src/main/java/de/thm/arsnova/websocket/ArsnovaSocketioServerImpl.java
@@ -529,9 +529,9 @@ public class ArsnovaSocketioServerImpl implements ArsnovaSocketioServer, Arsnova
 
 		// Update the unanswered count for the content variant that was answered.
 		final de.thm.arsnova.entities.Content content = event.getContent();
-		if ("lecture".equals(content.getGroup())) {
+		if ("lecture".equals(content.getGroups())) {
 			sendToUser(event.getUser(), "unansweredLecturerQuestions", contentService.getUnAnsweredLectureContentIds(roomId, event.getUser()));
-		} else if ("preparation".equals(content.getGroup())) {
+		} else if ("preparation".equals(content.getGroups())) {
 			sendToUser(event.getUser(), "unansweredPreparationQuestions", contentService.getUnAnsweredPreparationContentIds(roomId, event.getUser()));
 		}
 	}
diff --git a/src/main/java/de/thm/arsnova/websocket/message/Content.java b/src/main/java/de/thm/arsnova/websocket/message/Content.java
index ffd294c29..71886b220 100644
--- a/src/main/java/de/thm/arsnova/websocket/message/Content.java
+++ b/src/main/java/de/thm/arsnova/websocket/message/Content.java
@@ -27,7 +27,8 @@ public class Content {
 
 	public Content(de.thm.arsnova.entities.Content content) {
 		this._id = content.getId();
-		this.variant = content.getGroup();
+		/* FIXME: Message does not support content with multiple groups */
+		this.variant = content.getGroups().toArray(new String[1])[0];
 	}
 
 	public String get_id() {
-- 
GitLab