From def8bde488af9aa6fce2a5f546fdae6f39bacafd Mon Sep 17 00:00:00 2001
From: Daniel Gerhardt <code@dgerhardt.net>
Date: Mon, 22 Jan 2018 16:56:11 +0100
Subject: [PATCH] Adjust type handling for answers

---
 .../controller/v2/ContentController.java      | 78 +++++++++++++------
 .../java/de/thm/arsnova/entities/Answer.java  |  6 ++
 .../java/de/thm/arsnova/entities/Content.java |  6 ++
 .../arsnova/persistance/AnswerRepository.java |  4 +-
 .../couchdb/CouchDbAnswerRepository.java      | 12 +--
 .../thm/arsnova/services/ContentService.java  |  9 ++-
 .../arsnova/services/ContentServiceImpl.java  | 18 ++---
 7 files changed, 89 insertions(+), 44 deletions(-)

diff --git a/src/main/java/de/thm/arsnova/controller/v2/ContentController.java b/src/main/java/de/thm/arsnova/controller/v2/ContentController.java
index 46a5110df..074b1a02b 100644
--- a/src/main/java/de/thm/arsnova/controller/v2/ContentController.java
+++ b/src/main/java/de/thm/arsnova/controller/v2/ContentController.java
@@ -18,6 +18,9 @@
 package de.thm.arsnova.controller.v2;
 
 import de.thm.arsnova.controller.PaginationController;
+import de.thm.arsnova.entities.ChoiceAnswer;
+import de.thm.arsnova.entities.ChoiceQuestionContent;
+import de.thm.arsnova.entities.TextAnswer;
 import de.thm.arsnova.entities.migration.FromV2Migrator;
 import de.thm.arsnova.entities.migration.ToV2Migrator;
 import de.thm.arsnova.entities.migration.v2.Answer;
@@ -46,6 +49,7 @@ import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.ResponseStatus;
 import org.springframework.web.bind.annotation.RestController;
 
+import javax.naming.OperationNotSupportedException;
 import javax.servlet.http.HttpServletResponse;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -413,13 +417,18 @@ public class ContentController extends PaginationController {
 			@PathVariable final String questionId,
 			final HttpServletResponse response
 			) {
+		final de.thm.arsnova.entities.Content content = contentService.get(questionId);
 		final de.thm.arsnova.entities.Answer answer = contentService.getMyAnswer(questionId);
 		if (answer == null) {
 			response.setStatus(HttpStatus.NO_CONTENT.value());
 			return null;
 		}
 
-		return toV2Migrator.migrate(answer);
+		if (content.getFormat().equals(de.thm.arsnova.entities.Content.Format.TEXT)) {
+			return toV2Migrator.migrate((TextAnswer) answer);
+		} else {
+			return toV2Migrator.migrate((ChoiceAnswer) answer, (ChoiceQuestionContent) content);
+		}
 	}
 
 	/**
@@ -443,25 +452,31 @@ public class ContentController extends PaginationController {
 			@PathVariable final String questionId,
 			@RequestParam(value = "piround", required = false) final Integer piRound,
 			@RequestParam(value = "all", required = false, defaultValue = "false") final Boolean allAnswers,
-			final HttpServletResponse response
-			) {
-		List<de.thm.arsnova.entities.Answer> answers;
-		if (allAnswers) {
-			answers = contentService.getAllAnswers(questionId, -1, -1);
-		} else if (null == piRound) {
-			answers = contentService.getAnswers(questionId, offset, limit);
+			final HttpServletResponse response) throws OperationNotSupportedException {
+		final de.thm.arsnova.entities.Content content = contentService.get(questionId);
+		if (content instanceof ChoiceQuestionContent) {
+			// FIXME migration needed!
+			// contentService.getAllStatistics()
+			throw new OperationNotSupportedException();
 		} else {
-			if (piRound < 1 || piRound > 2) {
-				response.setStatus(HttpStatus.BAD_REQUEST.value());
-
-				return null;
+			List<de.thm.arsnova.entities.TextAnswer> answers;
+			if (allAnswers) {
+				answers = contentService.getAllTextAnswers(questionId, -1, -1);
+			} else if (null == piRound) {
+				answers = contentService.getTextAnswers(questionId, offset, limit);
+			} else {
+				if (piRound < 1 || piRound > 2) {
+					response.setStatus(HttpStatus.BAD_REQUEST.value());
+
+					return null;
+				}
+				answers = contentService.getTextAnswers(questionId, piRound, offset, limit);
 			}
-			answers = contentService.getAnswers(questionId, piRound, offset, limit);
-		}
-		if (answers == null) {
-			return new ArrayList<>();
+			if (answers == null) {
+				return new ArrayList<>();
+			}
+			return answers.stream().map(toV2Migrator::migrate).collect(Collectors.toList());
 		}
-		return answers.stream().map(toV2Migrator::migrate).collect(Collectors.toList());
 	}
 
 	@ApiOperation(value = "Save answer, provided in the Request Body, for a question, identified by provided question ID",
@@ -472,7 +487,15 @@ public class ContentController extends PaginationController {
 			@RequestBody final Answer answer,
 			final HttpServletResponse response
 			) {
-		return toV2Migrator.migrate(contentService.saveAnswer(questionId, fromV2Migrator.migrate(answer)));
+		final de.thm.arsnova.entities.Content content = contentService.get(questionId);
+		final Content contentV2 = toV2Migrator.migrate(content);
+		final de.thm.arsnova.entities.Answer answerV3 = fromV2Migrator.migrate(answer, contentV2);
+
+		if (answerV3 instanceof TextAnswer) {
+			return toV2Migrator.migrate((TextAnswer) contentService.saveAnswer(questionId, answerV3));
+		} else {
+			return  toV2Migrator.migrate((ChoiceAnswer) contentService.saveAnswer(questionId, answerV3), (ChoiceQuestionContent) content);
+		}
 	}
 
 	@ApiOperation(value = "Update answer, provided in Request Body, identified by question ID and answer ID",
@@ -484,7 +507,15 @@ public class ContentController extends PaginationController {
 			@RequestBody final Answer answer,
 			final HttpServletResponse response
 			) {
-		return toV2Migrator.migrate(contentService.updateAnswer(fromV2Migrator.migrate(answer)));
+		final de.thm.arsnova.entities.Content content = contentService.get(questionId);
+		final Content contentV2 = toV2Migrator.migrate(content);
+		final de.thm.arsnova.entities.Answer answerV3 = fromV2Migrator.migrate(answer, contentV2);
+
+		if (answerV3 instanceof TextAnswer) {
+			return toV2Migrator.migrate((TextAnswer) contentService.updateAnswer(answerV3));
+		} else {
+			return  toV2Migrator.migrate((ChoiceAnswer) contentService.updateAnswer(answerV3), (ChoiceQuestionContent) content);
+		}
 	}
 
 	@ApiOperation(value = "Get Image, identified by question ID and answer ID",
@@ -590,7 +621,7 @@ public class ContentController extends PaginationController {
 	@RequestMapping(value = "/{questionId}/freetextanswer/", method = RequestMethod.GET)
 	@Pagination
 	public List<Answer> getFreetextAnswers(@PathVariable final String questionId) {
-		return contentService.getFreetextAnswersByContentId(questionId, offset, limit).stream()
+		return contentService.getTextAnswersByContentId(questionId, offset, limit).stream()
 				.map(toV2Migrator::migrate).collect(Collectors.toList());
 	}
 
@@ -599,9 +630,10 @@ public class ContentController extends PaginationController {
 	@DeprecatedApi
 	@Deprecated
 	@RequestMapping(value = "/myanswers", method = RequestMethod.GET)
-	public List<Answer> getMyAnswers(@RequestParam final String sessionkey) {
-		return contentService.getMyAnswersByRoomShortId(sessionkey).stream()
-				.map(toV2Migrator::migrate).collect(Collectors.toList());
+	public List<Answer> getMyAnswers(@RequestParam final String sessionkey) throws OperationNotSupportedException {
+		throw new OperationNotSupportedException();
+//		return contentService.getMyAnswersByRoomShortId(sessionkey).stream()
+//				.map(toV2Migrator::migrate).collect(Collectors.toList());
 	}
 
 	@ApiOperation(value = "Get the total amount of answers of an session, identified by the sessionkey",
diff --git a/src/main/java/de/thm/arsnova/entities/Answer.java b/src/main/java/de/thm/arsnova/entities/Answer.java
index e96a298d2..6fc558bcf 100644
--- a/src/main/java/de/thm/arsnova/entities/Answer.java
+++ b/src/main/java/de/thm/arsnova/entities/Answer.java
@@ -1,11 +1,17 @@
 package de.thm.arsnova.entities;
 
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
 import com.fasterxml.jackson.annotation.JsonView;
 import de.thm.arsnova.entities.serialization.View;
 
 import java.util.Date;
 import java.util.Map;
 
+@JsonTypeInfo(
+		use = JsonTypeInfo.Id.MINIMAL_CLASS,
+		include = JsonTypeInfo.As.PROPERTY,
+		property = "type"
+)
 public abstract class Answer implements Entity {
 	private String id;
 	private String rev;
diff --git a/src/main/java/de/thm/arsnova/entities/Content.java b/src/main/java/de/thm/arsnova/entities/Content.java
index 1cb3e875b..199ea3097 100644
--- a/src/main/java/de/thm/arsnova/entities/Content.java
+++ b/src/main/java/de/thm/arsnova/entities/Content.java
@@ -1,11 +1,17 @@
 package de.thm.arsnova.entities;
 
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
 import com.fasterxml.jackson.annotation.JsonView;
 import de.thm.arsnova.entities.serialization.View;
 
 import java.util.Date;
 import java.util.Map;
 
+@JsonTypeInfo(
+		use = JsonTypeInfo.Id.MINIMAL_CLASS,
+		include = JsonTypeInfo.As.PROPERTY,
+		property = "type"
+)
 public class Content implements Entity {
 	public enum Format {
 		CHOICE,
diff --git a/src/main/java/de/thm/arsnova/persistance/AnswerRepository.java b/src/main/java/de/thm/arsnova/persistance/AnswerRepository.java
index 610c14537..eea81a7ae 100644
--- a/src/main/java/de/thm/arsnova/persistance/AnswerRepository.java
+++ b/src/main/java/de/thm/arsnova/persistance/AnswerRepository.java
@@ -25,11 +25,11 @@ import org.springframework.data.repository.CrudRepository;
 import java.util.List;
 
 public interface AnswerRepository extends CrudRepository<Answer, String> {
-	Answer findByContentIdUserPiRound(String contentId, UserAuthentication user, int piRound);
+	<T extends Answer> T findByContentIdUserPiRound(String contentId, Class<T> type, UserAuthentication user, int piRound);
 	AnswerStatistics findByContentIdPiRound(String contentId, int piRound);
 	int countByContentIdRound(String contentId, int round);
 	int countByContentId(String contentId);
-	List<Answer> findByContentId(String contentId, int start, int limit);
+	<T extends Answer> List<T> findByContentId(String contentId, Class<T> type, int start, int limit);
 	List<Answer> findByUserRoomId(UserAuthentication user, String roomId);
 	int countByRoomShortId(String roomShortId);
 	int deleteByContentId(String contentId);
diff --git a/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbAnswerRepository.java b/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbAnswerRepository.java
index 52f25bc6e..b3e524942 100644
--- a/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbAnswerRepository.java
+++ b/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbAnswerRepository.java
@@ -70,9 +70,9 @@ public class CouchDbAnswerRepository extends CouchDbCrudRepository<Answer> imple
 	}
 
 	@Override
-	public Answer findByContentIdUserPiRound(final String contentId, final UserAuthentication user, final int piRound) {
-		final List<Answer> answerList = queryView("by_contentid_creatorid_round",
-				ComplexKey.of(contentId, user.getUsername(), piRound));
+	public <T extends Answer> T findByContentIdUserPiRound(final String contentId, final Class<T> type, final UserAuthentication user, final int piRound) {
+		final List<T> answerList = db.queryView(createQuery("by_contentid_creatorid_round")
+				.key(ComplexKey.of(contentId, user.getUsername(), piRound)), type);
 		return answerList.isEmpty() ? null : answerList.get(0);
 	}
 
@@ -128,18 +128,18 @@ public class CouchDbAnswerRepository extends CouchDbCrudRepository<Answer> imple
 	}
 
 	@Override
-	public List<Answer> findByContentId(final String contentId, final int start, final int limit) {
+	public <T extends Answer> List<T> findByContentId(final String contentId, final Class<T> type, final int start, final int limit) {
 		final int qSkip = start > 0 ? start : -1;
 		final int qLimit = limit > 0 ? limit : -1;
 
-		final List<Answer> answers = db.queryView(createQuery("by_contentid_creationtimestamp")
+		final List<T> answers = db.queryView(createQuery("by_contentid_creationtimestamp")
 						.skip(qSkip)
 						.limit(qLimit)
 						//.includeDocs(true)
 						.startKey(ComplexKey.of(contentId))
 						.endKey(ComplexKey.of(contentId, ComplexKey.emptyObject()))
 						.descending(true),
-				Answer.class);
+				type);
 
 		return answers;
 	}
diff --git a/src/main/java/de/thm/arsnova/services/ContentService.java b/src/main/java/de/thm/arsnova/services/ContentService.java
index bdcc5fc14..95f6b4059 100644
--- a/src/main/java/de/thm/arsnova/services/ContentService.java
+++ b/src/main/java/de/thm/arsnova/services/ContentService.java
@@ -20,6 +20,7 @@ package de.thm.arsnova.services;
 import de.thm.arsnova.entities.Answer;
 import de.thm.arsnova.entities.AnswerStatistics;
 import de.thm.arsnova.entities.Content;
+import de.thm.arsnova.entities.TextAnswer;
 import de.thm.arsnova.entities.UserAuthentication;
 
 import java.util.List;
@@ -51,17 +52,17 @@ public interface ContentService extends EntityService<Content> {
 
 	AnswerStatistics getAllStatistics(String contentId);
 
-	List<Answer> getAnswers(String contentId, int piRound, int offset, int limit);
+	List<TextAnswer> getTextAnswers(String contentId, int piRound, int offset, int limit);
 
-	List<Answer> getAnswers(String contentId, int offset, int limit);
+	List<TextAnswer> getTextAnswers(String contentId, int offset, int limit);
 
-	List<Answer> getAllAnswers(String contentId, int offset, int limit);
+	List<TextAnswer> getAllTextAnswers(String contentId, int offset, int limit);
 
 	int countAnswersByContentIdAndRound(String contentId);
 
 	int countAnswersByContentIdAndRound(String contentId, int piRound);
 
-	List<Answer> getFreetextAnswersByContentId(String contentId, int offset, int limit);
+	List<TextAnswer> getTextAnswersByContentId(String contentId, int offset, int limit);
 
 	List<Answer> getMyAnswersByRoomShortId(String roomShortId);
 
diff --git a/src/main/java/de/thm/arsnova/services/ContentServiceImpl.java b/src/main/java/de/thm/arsnova/services/ContentServiceImpl.java
index 331c6c154..b49ddc007 100644
--- a/src/main/java/de/thm/arsnova/services/ContentServiceImpl.java
+++ b/src/main/java/de/thm/arsnova/services/ContentServiceImpl.java
@@ -439,7 +439,7 @@ public class ContentServiceImpl extends DefaultEntityServiceImpl<Content> implem
 		if (content == null) {
 			throw new NotFoundException();
 		}
-		return answerRepository.findByContentIdUserPiRound(contentId, userService.getCurrentUser(), content.getState().getRound());
+		return answerRepository.findByContentIdUserPiRound(contentId, Answer.class, userService.getCurrentUser(), content.getState().getRound());
 	}
 
 	@Override
@@ -497,31 +497,31 @@ public class ContentServiceImpl extends DefaultEntityServiceImpl<Content> implem
 
 	@Override
 	@PreAuthorize("isAuthenticated()")
-	public List<Answer> getAnswers(final String contentId, final int piRound, final int offset, final int limit) {
+	public List<TextAnswer> getTextAnswers(final String contentId, final int piRound, final int offset, final int limit) {
 		/* FIXME: round support not implemented */
 		final Content content = contentRepository.findOne(contentId);
 		if (content == null) {
 			throw new NotFoundException();
 		}
 
-		return getFreetextAnswersByContentId(contentId, offset, limit);
+		return getTextAnswersByContentId(contentId, offset, limit);
 	}
 
 	@Override
 	@PreAuthorize("isAuthenticated()")
-	public List<Answer> getAnswers(final String contentId, final int offset, final int limit) {
-		return getAnswers(contentId, 0, offset, limit);
+	public List<TextAnswer> getTextAnswers(final String contentId, final int offset, final int limit) {
+		return getTextAnswers(contentId, 0, offset, limit);
 	}
 
 	@Override
 	@PreAuthorize("isAuthenticated()")
-	public List<Answer> getAllAnswers(final String contentId, final int offset, final int limit) {
+	public List<TextAnswer> getAllTextAnswers(final String contentId, final int offset, final int limit) {
 		final Content content = get(contentId);
 		if (content == null) {
 			throw new NotFoundException();
 		}
 
-		return getFreetextAnswersByContentId(contentId, offset, limit);
+		return getTextAnswersByContentId(contentId, offset, limit);
 	}
 
 	@Override
@@ -574,8 +574,8 @@ public class ContentServiceImpl extends DefaultEntityServiceImpl<Content> implem
 
 	@Override
 	@PreAuthorize("isAuthenticated()")
-	public List<Answer> getFreetextAnswersByContentId(final String contentId, final int offset, final int limit) {
-		final List<Answer> answers = answerRepository.findByContentId(contentId, offset, limit);
+	public List<TextAnswer> getTextAnswersByContentId(final String contentId, final int offset, final int limit) {
+		final List<TextAnswer> answers = answerRepository.findByContentId(contentId, TextAnswer.class, offset, limit);
 		if (answers == null) {
 			throw new NotFoundException();
 		}
-- 
GitLab