/*
* This file is part of ARSnova Backend.
* Copyright (C) 2012-2017 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.controller;
import de.thm.arsnova.PaginationListDecorator;
import de.thm.arsnova.entities.Answer;
import de.thm.arsnova.entities.Question;
import de.thm.arsnova.exceptions.BadRequestException;
import de.thm.arsnova.exceptions.ForbiddenException;
import de.thm.arsnova.exceptions.NoContentException;
import de.thm.arsnova.exceptions.NotFoundException;
import de.thm.arsnova.services.IQuestionService;
import de.thm.arsnova.web.DeprecatedApi;
import de.thm.arsnova.web.Pagination;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Handles requests related to questions teachers are asking their students.
*/
@RestController
@RequestMapping("/lecturerquestion")
@Api(value = "/lecturerquestion", description = "Operations for Lecture Questions")
public class LecturerQuestionController extends PaginationController {
@Autowired
private IQuestionService questionService;
@ApiOperation(value = "Get question with provided question Id",
nickname = "getQuestion")
@ApiResponses(value = {
@ApiResponse(code = 404, message = HTML_STATUS_404)
})
@RequestMapping(value = "/{questionId}", method = RequestMethod.GET)
public Question getQuestion(@PathVariable final String questionId) {
final Question question = questionService.getQuestion(questionId);
if (question != null) {
return question;
}
throw new NotFoundException();
}
@ApiOperation(value = "Post provided question",
nickname = "postQuestion")
@ApiResponses(value = {
@ApiResponse(code = 400, message = HTML_STATUS_400)
})
@RequestMapping(value = "/", method = RequestMethod.POST)
@ResponseStatus(HttpStatus.CREATED)
public Question postQuestion(@RequestBody final Question question) {
if (questionService.saveQuestion(question) != null) {
return question;
}
throw new BadRequestException();
}
@ApiOperation(value = "Post provided questions", nickname = "bulkPostQuestions")
@ApiResponses(value = {
@ApiResponse(code = 400, message = HTML_STATUS_400)
})
@RequestMapping(value = "/bulk", method = RequestMethod.POST)
@ResponseStatus(HttpStatus.CREATED)
public List<Question> bulkPostQuestions(@RequestBody final List<Question> questions) {
for (final Question question : questions) {
if (questionService.saveQuestion(question) == null) {
throw new BadRequestException();
}
}
return questions;
}
@ApiOperation(value = "Update the question, identified by provided id, with the provided question in the Request Body",
nickname = "updateQuestion")
@ApiResponses(value = {
@ApiResponse(code = 400, message = HTML_STATUS_400)
})
@RequestMapping(value = "/{questionId}", method = RequestMethod.PUT)
public Question updateQuestion(
@PathVariable final String questionId,
@RequestBody final Question question
) {
try {
return questionService.update(question);
} catch (final Exception e) {
throw new BadRequestException();
}
}
@ApiOperation(value = "Start new Pi Round on question, identified by provided id, with an optional time",
nickname = "startPiRound")
@RequestMapping(value = "/{questionId}/questionimage", method = RequestMethod.GET)
public String getQuestionImage(
@PathVariable final String questionId,
@RequestParam(value = "fcImage", defaultValue = "false", required = false) final boolean fcImage
) {
if (fcImage) {
return questionService.getQuestionFcImage(questionId);
} else {
return questionService.getQuestionImage(questionId);
}
}
@RequestMapping(value = "/{questionId}/startnewpiround", method = RequestMethod.POST)
public void startPiRound(
@PathVariable final String questionId,
@RequestParam(value = "time", defaultValue = "0", required = false) final int time
) {
if (time == 0) {
questionService.startNewPiRound(questionId, null);
} else {
questionService.startNewPiRoundDelayed(questionId, time);
}
}
@RequestMapping(value = "/{questionId}/canceldelayedpiround", method = RequestMethod.POST)
@ApiOperation(value = "Cancel Pi Round on question, identified by provided id",
nickname = "cancelPiRound")
public void cancelPiRound(
@PathVariable final String questionId
) {
questionService.cancelPiRoundChange(questionId);
}
@RequestMapping(value = "/{questionId}/resetpiroundstate", method = RequestMethod.POST)
@ApiOperation(value = "Reset Pi Round on question, identified by provided id",
nickname = "resetPiQuestion")
public void resetPiQuestion(
@PathVariable final String questionId
) {
questionService.resetPiRoundState(questionId);
}
@ApiOperation(value = "Set voting admission on question, identified by provided id",
nickname = "setVotingAdmission")
@RequestMapping(value = "/{questionId}/disablevote", method = RequestMethod.POST)
public void setVotingAdmission(
@PathVariable final String questionId,
@RequestParam(value = "disable", defaultValue = "false", required = false) final Boolean disableVote
) {
boolean disable = false;
if (disableVote != null) {
disable = disableVote;
}
questionService.setVotingAdmission(questionId, disable);
}
@ApiOperation(value = "Set voting admission for all questions",
nickname = "setVotingAdmissionForAllQuestions")
@RequestMapping(value = "/disablevote", method = RequestMethod.POST)
public void setVotingAdmissionForAllQuestions(
@RequestParam final String sessionkey,
@RequestParam(value = "disable", defaultValue = "false", required = false) final Boolean disableVote,
@RequestParam(value = "lecturequestionsonly", defaultValue = "false", required = false) final boolean lectureQuestionsOnly,
@RequestParam(value = "preparationquestionsonly", defaultValue = "false", required = false) final boolean preparationQuestionsOnly
) {
boolean disable = false;
List<Question> questions;
if (disableVote != null) {
disable = disableVote;
}
if (lectureQuestionsOnly) {
questions = questionService.getLectureQuestions(sessionkey);
questionService.setVotingAdmissions(sessionkey, disable, questions);
} else if (preparationQuestionsOnly) {
questions = questionService.getPreparationQuestions(sessionkey);
questionService.setVotingAdmissions(sessionkey, disable, questions);
} else {
questionService.setVotingAdmissionForAllQuestions(sessionkey, disable);
}
}
@ApiOperation(value = "Publish a question, identified by provided id and question in Request Body.",
nickname = "publishQuestion")
@RequestMapping(value = "/{questionId}/publish", method = RequestMethod.POST)
public void publishQuestion(
@PathVariable final String questionId,
@RequestParam(required = false) final Boolean publish,
@RequestBody final Question question
) {
if (publish != null) {
question.setActive(publish);
}
questionService.update(question);
}
@ApiOperation(value = "Publish all questions",
nickname = "publishAllQuestions")
@RequestMapping(value = "/publish", method = RequestMethod.POST)
public void publishAllQuestions(
@RequestParam final String sessionkey,
@RequestParam(required = false) final Boolean publish,
@RequestParam(value = "lecturequestionsonly", defaultValue = "false", required = false) final boolean lectureQuestionsOnly,
@RequestParam(value = "preparationquestionsonly", defaultValue = "false", required = false) final boolean preparationQuestionsOnly
) {
boolean p = publish == null || publish;
List<Question> questions;
if (lectureQuestionsOnly) {
questions = questionService.getLectureQuestions(sessionkey);
questionService.publishQuestions(sessionkey, p, questions);
} else if (preparationQuestionsOnly) {
questions = questionService.getPreparationQuestions(sessionkey);
questionService.publishQuestions(sessionkey, p, questions);
} else {
questionService.publishAll(sessionkey, p);
}
}
@ApiOperation(value = "Publish statistics from question with provided id",
nickname = "publishStatistics")
@RequestMapping(value = "/{questionId}/publishstatistics", method = RequestMethod.POST)
public void publishStatistics(
@PathVariable final String questionId,
@RequestParam(required = false) final Boolean showStatistics,
@RequestBody final Question question
) {
if (showStatistics != null) {
question.setShowStatistic(showStatistics);
}
questionService.update(question);
}
@ApiOperation(value = "Publish correct answer from question with provided id",
nickname = "publishCorrectAnswer")
@RequestMapping(value = "/{questionId}/publishcorrectanswer", method = RequestMethod.POST)
public void publishCorrectAnswer(
@PathVariable final String questionId,
@RequestParam(required = false) final Boolean showCorrectAnswer,
@RequestBody final Question question
) {
if (showCorrectAnswer != null) {
question.setShowAnswer(showCorrectAnswer);
}
questionService.update(question);
}
@ApiOperation(value = "Get skill questions",
nickname = "getSkillQuestions")
@RequestMapping(value = "/", method = RequestMethod.GET)
@Pagination
public List<Question> getSkillQuestions(
@RequestParam final String sessionkey,
@RequestParam(value = "lecturequestionsonly", defaultValue = "false") final boolean lectureQuestionsOnly,
@RequestParam(value = "flashcardsonly", defaultValue = "false") final boolean flashcardsOnly,
@RequestParam(value = "preparationquestionsonly", defaultValue = "false") final boolean preparationQuestionsOnly,
@RequestParam(value = "requestImageData", defaultValue = "false") final boolean requestImageData,
final HttpServletResponse response
) {
List<Question> questions;
if (lectureQuestionsOnly) {
questions = questionService.getLectureQuestions(sessionkey);
} else if (flashcardsOnly) {
questions = questionService.getFlashcards(sessionkey);
} else if (preparationQuestionsOnly) {
questions = questionService.getPreparationQuestions(sessionkey);
} else {
questions = questionService.getSkillQuestions(sessionkey);
}
if (questions == null || questions.isEmpty()) {
response.setStatus(HttpStatus.NO_CONTENT.value());
return null;
} else if (!requestImageData) {
questions = questionService.replaceImageData(questions);
}
return new PaginationListDecorator<>(questions, offset, limit);
}
@ApiOperation(value = "Delete skill questions",
nickname = "deleteSkillQuestions")
@RequestMapping(value = { "/" }, method = RequestMethod.DELETE)
public void deleteSkillQuestions(
@RequestParam final String sessionkey,
@RequestParam(value = "lecturequestionsonly", defaultValue = "false") final boolean lectureQuestionsOnly,
@RequestParam(value = "flashcardsonly", defaultValue = "false") final boolean flashcardsOnly,
@RequestParam(value = "preparationquestionsonly", defaultValue = "false") final boolean preparationQuestionsOnly,
final HttpServletResponse response
) {
if (lectureQuestionsOnly) {
questionService.deleteLectureQuestions(sessionkey);
} else if (flashcardsOnly) {
questionService.deleteFlashcards(sessionkey);
} else if (preparationQuestionsOnly) {
questionService.deletePreparationQuestions(sessionkey);
} else {
questionService.deleteAllQuestions(sessionkey);
}
}
@ApiOperation(value = "Get the amount of skill questions by the sessionkey",
nickname = "getSkillQuestionCount")
@DeprecatedApi
@Deprecated
@RequestMapping(value = "/count", method = RequestMethod.GET)
public int getSkillQuestionCount(
@RequestParam final String sessionkey,
@RequestParam(value = "lecturequestionsonly", defaultValue = "false") final boolean lectureQuestionsOnly,
@RequestParam(value = "flashcardsonly", defaultValue = "false") final boolean flashcardsOnly,
@RequestParam(value = "preparationquestionsonly", defaultValue = "false") final boolean preparationQuestionsOnly
) {
if (lectureQuestionsOnly) {
return questionService.getLectureQuestionCount(sessionkey);
} else if (flashcardsOnly) {
return questionService.getFlashcardCount(sessionkey);
} else if (preparationQuestionsOnly) {
return questionService.getPreparationQuestionCount(sessionkey);
} else {
return questionService.getSkillQuestionCount(sessionkey);
}
}
@ApiOperation(value = "Delete answers and questions",
nickname = "deleteAnswersAndQuestion")
@RequestMapping(value = "/{questionId}", method = RequestMethod.DELETE)
public void deleteAnswersAndQuestion(
@PathVariable final String questionId
) {
questionService.deleteQuestion(questionId);
}
@ApiOperation(value = "Get unanswered skill question ID by provided session ID",
nickname = "getUnAnsweredSkillQuestionIds")
@DeprecatedApi
@Deprecated
@RequestMapping(value = "/unanswered", method = RequestMethod.GET)
public List<String> getUnAnsweredSkillQuestionIds(
@RequestParam final String sessionkey,
@RequestParam(value = "lecturequestionsonly", defaultValue = "false") final boolean lectureQuestionsOnly,
@RequestParam(value = "preparationquestionsonly", defaultValue = "false") final boolean preparationQuestionsOnly
) {
List<String> answers;
if (lectureQuestionsOnly) {
answers = questionService.getUnAnsweredLectureQuestionIds(sessionkey);
} else if (preparationQuestionsOnly) {
answers = questionService.getUnAnsweredPreparationQuestionIds(sessionkey);
} else {
answers = questionService.getUnAnsweredQuestionIds(sessionkey);
}
if (answers == null || answers.isEmpty()) {
throw new NoContentException();
}
return answers;
}
/**
* returns a JSON document which represents the given answer of a question.
*
* @param questionId
* CouchDB Question ID for which the given answer should be
* retrieved
* @return JSON Document of {@link Answer} or {@link NotFoundException}
* @throws NotFoundException
* if wrong session, wrong question or no answer was given by
* the current user
* @throws ForbiddenException
* if not logged in
*/
@ApiOperation(value = "Get my answer for a question, identified by provided question ID",
nickname = "getMyAnswer")
@DeprecatedApi
@Deprecated
@RequestMapping(value = "/{questionId}/myanswer", method = RequestMethod.GET)
public Answer getMyAnswer(
@PathVariable final String questionId,
final HttpServletResponse response
) {
final Answer answer = questionService.getMyAnswer(questionId);
if (answer == null) {
response.setStatus(HttpStatus.NO_CONTENT.value());
return null;
}
return answer;
}
/**
* returns a list of {@link Answer}s encoded as a JSON document for a given
* question id. In this case only {@link Answer} <tt>questionId</tt>,
* <tt>answerText</tt>, <tt>answerSubject</tt> and <tt>answerCount</tt>
* properties are set
*
* @param questionId
* CouchDB Question ID for which the given answers should be
* retrieved
* @throws NotFoundException
* if wrong session, wrong question or no answers was given
* @throws ForbiddenException
* if not logged in
*/
@ApiOperation(value = "Get answers for a question, identified by provided question ID",
nickname = "getAnswers")
@RequestMapping(value = "/{questionId}/answer/", method = RequestMethod.GET)
public List<Answer> getAnswers(
@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<Answer> answers;
if (allAnswers) {
answers = questionService.getAllAnswers(questionId, -1, -1);
} else if (null == piRound) {
answers = questionService.getAnswers(questionId, offset, limit);
} else {
if (piRound < 1 || piRound > 2) {
response.setStatus(HttpStatus.BAD_REQUEST.value());
return null;
}
answers = questionService.getAnswers(questionId, piRound, offset, limit);
}
if (answers == null) {
return new ArrayList<>();
}
return answers;
}
@ApiOperation(value = "Save answer, provided in the Request Body, for a question, identified by provided question ID",
nickname = "saveAnswer")
@RequestMapping(value = "/{questionId}/answer/", method = RequestMethod.POST)
public Answer saveAnswer(
@PathVariable final String questionId,
@RequestBody final de.thm.arsnova.entities.transport.Answer answer,
final HttpServletResponse response
) {
return questionService.saveAnswer(questionId, answer);
}
@ApiOperation(value = "Update answer, provided in Request Body, identified by question ID and answer ID",
nickname = "updateAnswer")
@RequestMapping(value = "/{questionId}/answer/{answerId}", method = RequestMethod.PUT)
public Answer updateAnswer(
@PathVariable final String questionId,
@PathVariable final String answerId,
@RequestBody final Answer answer,
final HttpServletResponse response
) {
return questionService.updateAnswer(answer);
}
@ApiOperation(value = "Get Image, identified by question ID and answer ID",
nickname = "getImage")
@RequestMapping(value = "/{questionId}/answer/{answerId}/image", method = RequestMethod.GET)
public String getImage(
@PathVariable final String questionId,
@PathVariable final String answerId,
final HttpServletResponse response
) {
return questionService.getImage(questionId, answerId);
}
@ApiOperation(value = "Delete answer, identified by question ID and answer ID",
nickname = "deleteAnswer")
@RequestMapping(value = "/{questionId}/answer/{answerId}", method = RequestMethod.DELETE)
public void deleteAnswer(
@PathVariable final String questionId,
@PathVariable final String answerId,
final HttpServletResponse response
) {
questionService.deleteAnswer(questionId, answerId);
}
@ApiOperation(value = "Delete answers from a question, identified by question ID",
nickname = "deleteAnswers")
@RequestMapping(value = "/{questionId}/answer/", method = RequestMethod.DELETE)
public void deleteAnswers(
@PathVariable final String questionId,
final HttpServletResponse response
) {
questionService.deleteAnswers(questionId);
}
@ApiOperation(value = "Delete all answers and questions from a session, identified by sessionkey",
nickname = "deleteAllQuestionsAnswers")
@RequestMapping(value = "/answers", method = RequestMethod.DELETE)
public void deleteAllQuestionsAnswers(
@RequestParam final String sessionkey,
@RequestParam(value = "lecturequestionsonly", defaultValue = "false") final boolean lectureQuestionsOnly,
@RequestParam(value = "preparationquestionsonly", defaultValue = "false") final boolean preparationQuestionsOnly,
final HttpServletResponse response
) {
if (lectureQuestionsOnly) {
questionService.deleteAllLectureAnswers(sessionkey);
} else if (preparationQuestionsOnly) {
questionService.deleteAllPreparationAnswers(sessionkey);
} else {
questionService.deleteAllQuestionsAnswers(sessionkey);
}
}
/**
*
* @param questionId
* CouchDB Question ID for which the given answers should be
* retrieved
* @return count of answers for given question id
* @throws NotFoundException
* if wrong session or wrong question
* @throws ForbiddenException
* if not logged in
*/
@ApiOperation(value = "Get the amount of answers for a question, identified by question ID",
nickname = "getAnswerCount")
@DeprecatedApi
@Deprecated
@RequestMapping(value = "/{questionId}/answercount", method = RequestMethod.GET)
public int getAnswerCount(@PathVariable final String questionId) {
return questionService.getAnswerCount(questionId);
}
@ApiOperation(value = "Get the amount of answers for a question, identified by the question ID",
nickname = "getAllAnswerCount")
@RequestMapping(value = "/{questionId}/allroundanswercount", method = RequestMethod.GET)
public List<Integer> getAllAnswerCount(@PathVariable final String questionId) {
return Arrays.asList(
questionService.getAnswerCount(questionId, 1),
questionService.getAnswerCount(questionId, 2)
);
}
@ApiOperation(value = "Get the total amount of answers by a question, identified by the question ID",
nickname = "getTotalAnswerCountByQuestion")
@RequestMapping(value = "/{questionId}/totalanswercount", method = RequestMethod.GET)
public int getTotalAnswerCountByQuestion(@PathVariable final String questionId) {
return questionService.getTotalAnswerCountByQuestion(questionId);
}
@ApiOperation(value = "Get the amount of answers and abstention answers by a question, identified by the question ID",
nickname = "getAnswerAndAbstentionCount")
@RequestMapping(value = "/{questionId}/answerandabstentioncount", method = RequestMethod.GET)
public List<Integer> getAnswerAndAbstentionCount(@PathVariable final String questionId) {
return Arrays.asList(
questionService.getAnswerCount(questionId),
questionService.getAbstentionAnswerCount(questionId)
);
}
@ApiOperation(value = "Get all Freetext answers by a question, identified by the question ID",
nickname = "getFreetextAnswers")
@RequestMapping(value = "/{questionId}/freetextanswer/", method = RequestMethod.GET)
@Pagination
public List<Answer> getFreetextAnswers(@PathVariable final String questionId) {
return questionService.getFreetextAnswers(questionId, offset, limit);
}
@ApiOperation(value = "Get my answers of an session, identified by the sessionkey",
nickname = "getMyAnswers")
@DeprecatedApi
@Deprecated
@RequestMapping(value = "/myanswers", method = RequestMethod.GET)
public List<Answer> getMyAnswers(@RequestParam final String sessionkey) {
return questionService.getMyAnswers(sessionkey);
}
@ApiOperation(value = "Get the total amount of answers of an session, identified by the sessionkey",
nickname = "getTotalAnswerCount")
@DeprecatedApi
@Deprecated
@RequestMapping(value = "/answercount", method = RequestMethod.GET)
public int getTotalAnswerCount(
@RequestParam final String sessionkey,
@RequestParam(value = "lecturequestionsonly", defaultValue = "false") final boolean lectureQuestionsOnly,
@RequestParam(value = "preparationquestionsonly", defaultValue = "false") final boolean preparationQuestionsOnly
) {
if (lectureQuestionsOnly) {
return questionService.countLectureQuestionAnswers(sessionkey);
} else if (preparationQuestionsOnly) {
return questionService.countPreparationQuestionAnswers(sessionkey);
} else {
return questionService.getTotalAnswerCount(sessionkey);
}
}
}