diff --git a/src/main/java/de/thm/arsnova/entities/Content.java b/src/main/java/de/thm/arsnova/entities/Content.java index 9988359aa0e0feb25081be0e13335175185acedb..aef47c63a0ddb76619465bf793e8ef66026b3ea6 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 9fbfed17cd7f4a8d2b2e42122452f024db53e633..588f2e7165135181b2859aca98bb1dfd2705ae1b 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 f4774157af96768c1435197f0a007ac135da9df5..2eaa7a1616d69a6c64ed2f3d713ef49cb4f23b34 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 29c85627b6cd0f67197bd3d9f9864751cb6ed868..39f483a954f3be128a747ff02d80d425e014c383 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 0d7e263cef46d5cdbf2716d07e7ce28150f88d22..e511a4c9caeb86ac8e4078a708b3de861a45a96d 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 510bbf7a9abf932c00a8ef67d3a8ec9eea0062c7..bd0a79ca203a8ea91641bda3f53f1efa79b021c5 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 188be7b494e280abd76e5bfb0c3fbdbba96e0414..0b38d4900f12e20223f5852fc3faa984a35de0ea 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 52958abd277dbafe53baec95993c173eae5618af..9ad99fa923ef454e1962881e3a5e52a406b0029c 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 7a974df44027dbf6cc734d1fbce1b4a1e0cda98e..0f0a814b9143b1fd5da2600271563e822aa22a30 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 b03c16b8baf220b2327aa744153fe363ffb1a16b..d11af8b7bf6e9b1ee4e74d56f4d4531535c82d54 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 81d19f8e7deedf84af30a57383a905be9f410f7b..d1673162e85633a964dfa7c0820447bde76bc94a 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 5cebdb1cc2217bdeff5580c568032123169b4d50..456673b334e8c6ab705f8b970aa0460cbf073dfb 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 ffd294c2977624376664fae840ad6e7c49e1edce..71886b22068758d2c07d7479abdaf030c990804a 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() {