/*
* 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.services;
import de.thm.arsnova.ImageUtils;
import de.thm.arsnova.dao.IDatabaseDao;
import de.thm.arsnova.entities.Answer;
import de.thm.arsnova.entities.InterposedQuestion;
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.*;
import de.thm.arsnova.exceptions.BadRequestException;
import de.thm.arsnova.exceptions.ForbiddenException;
import de.thm.arsnova.exceptions.NotFoundException;
import de.thm.arsnova.exceptions.UnauthorizedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
/**
* Performs all question, interposed question, and answer related operations.
*/
@Service
public class QuestionService implements IQuestionService, ApplicationEventPublisherAware {
@Autowired
private IDatabaseDao databaseDao;
@Autowired
private IUserService userService;
@Autowired
private ImageUtils imageUtils;
@Value("${upload.filesize_b}")
private int uploadFileSizeByte;
private ApplicationEventPublisher publisher;
private static final Logger logger = LoggerFactory.getLogger(QuestionService.class);
private HashMap<String, Timer> timerList = new HashMap<>();
public void setDatabaseDao(final IDatabaseDao databaseDao) {
this.databaseDao = databaseDao;
}
@Override
@PreAuthorize("isAuthenticated()")
public List<Question> getSkillQuestions(final String sessionkey) {
final Session session = getSession(sessionkey);
final User user = userService.getCurrentUser();
if (session.isCreator(user)) {
return databaseDao.getSkillQuestionsForTeachers(session);
} else {
return databaseDao.getSkillQuestionsForUsers(session);
}
}
@Override
@PreAuthorize("isAuthenticated()")
public int getSkillQuestionCount(final String sessionkey) {
final Session session = databaseDao.getSessionFromKeyword(sessionkey);
return databaseDao.getSkillQuestionCount(session);
}
@Override
@PreAuthorize("isAuthenticated() and hasPermission(#question.getSessionKeyword(), 'session', 'owner')")
public Question saveQuestion(final Question question) {
final Session session = databaseDao.getSessionFromKeyword(question.getSessionKeyword());
question.setSessionId(session.get_id());
question.setTimestamp(System.currentTimeMillis() / 1000L);
if ("freetext".equals(question.getQuestionType())) {
question.setPiRound(0);
} else if (question.getPiRound() < 1 || question.getPiRound() > 2) {
question.setPiRound(1);
}
// convert imageurl to base64 if neccessary
if ("grid".equals(question.getQuestionType()) && !question.getImage().startsWith("http")) {
// base64 adds offset to filesize, formula taken from: http://en.wikipedia.org/wiki/Base64#MIME
final int fileSize = (int) ((question.getImage().length() - 814) / 1.37);
if (fileSize > uploadFileSizeByte) {
logger.error("Could not save file. File is too large with {} Byte.", fileSize);
throw new BadRequestException();
}
}
final Question result = databaseDao.saveQuestion(session, question);
final NewQuestionEvent event = new NewQuestionEvent(this, session, result);
this.publisher.publishEvent(event);
return result;
}
@Override
@PreAuthorize("isAuthenticated()")
public boolean saveQuestion(final InterposedQuestion question) {
final Session session = databaseDao.getSessionFromKeyword(question.getSessionId());
final InterposedQuestion result = databaseDao.saveQuestion(session, question, userService.getCurrentUser());
if (null != result) {
final NewInterposedQuestionEvent event = new NewInterposedQuestionEvent(this, session, result);
this.publisher.publishEvent(event);
return true;
}
return false;
}
@Override
@PreAuthorize("isAuthenticated()")
public Question getQuestion(final String id) {
final Question result = databaseDao.getQuestion(id);
if (result == null) {
return null;
}
if (!"freetext".equals(result.getQuestionType()) && 0 == result.getPiRound()) {
/* needed for legacy questions whose piRound property has not been set */
result.setPiRound(1);
}
return result;
}
@Override
@PreAuthorize("isAuthenticated() and hasPermission(#questionId, 'question', 'owner')")
public void deleteQuestion(final String questionId) {
final Question question = databaseDao.getQuestion(questionId);
if (question == null) {
throw new NotFoundException();
}
final Session session = databaseDao.getSessionFromKeyword(question.getSessionKeyword());
if (session == null) {
throw new UnauthorizedException();
}
databaseDao.deleteQuestionWithAnswers(question);
final DeleteQuestionEvent event = new DeleteQuestionEvent(this, session, question);
this.publisher.publishEvent(event);
}
@Override
@PreAuthorize("isAuthenticated() and hasPermission(#sessionKeyword, 'session', 'owner')")
public void deleteAllQuestions(final String sessionKeyword) {
final Session session = getSessionWithAuthCheck(sessionKeyword);
databaseDao.deleteAllQuestionsWithAnswers(session);
final DeleteAllQuestionsEvent event = new DeleteAllQuestionsEvent(this, session);
this.publisher.publishEvent(event);
}
@Override
@PreAuthorize("isAuthenticated() and hasPermission(#questionId, 'question', 'owner')")
public void startNewPiRound(final String questionId, User user) {
final Question question = databaseDao.getQuestion(questionId);
final Session session = databaseDao.getSessionFromKeyword(question.getSessionKeyword());
if (null == user) {
user = userService.getCurrentUser();
}
cancelDelayedPiRoundChange(questionId);
question.setPiRoundEndTime(0);
question.setVotingDisabled(true);
question.updateRoundManagementState();
update(question, user);
this.publisher.publishEvent(new PiRoundEndEvent(this, session, question));
}
@Override
@PreAuthorize("isAuthenticated() and hasPermission(#questionId, 'question', 'owner')")
public void startNewPiRoundDelayed(final String questionId, final int time) {
final IQuestionService questionService = this;
final User user = userService.getCurrentUser();
final Question question = databaseDao.getQuestion(questionId);
final Session session = databaseDao.getSessionFromKeyword(question.getSessionKeyword());
final Date date = new Date();
final Timer timer = new Timer();
final Date endDate = new Date(date.getTime() + (time * 1000));
question.updateRoundStartVariables(date, endDate);
update(question);
this.publisher.publishEvent(new PiRoundDelayedStartEvent(this, session, question));
timerList.put(questionId, timer);
timer.schedule(new TimerTask() {
@Override
public void run() {
questionService.startNewPiRound(questionId, user);
}
}, endDate);
}
@Override
@PreAuthorize("isAuthenticated() and hasPermission(#questionId, 'question', 'owner')")
public void cancelPiRoundChange(final String questionId) {
final Question question = databaseDao.getQuestion(questionId);
final Session session = databaseDao.getSessionFromKeyword(question.getSessionKeyword());
cancelDelayedPiRoundChange(questionId);
question.resetRoundManagementState();
if (0 == question.getPiRound() || 1 == question.getPiRound()) {
question.setPiRoundFinished(false);
} else {
question.setPiRound(1);
question.setPiRoundFinished(true);
}
update(question);
this.publisher.publishEvent(new PiRoundCancelEvent(this, session, question));
}
@Override
public void cancelDelayedPiRoundChange(final String questionId) {
Timer timer = timerList.get(questionId);
if (null != timer) {
timer.cancel();
timerList.remove(questionId);
timer.purge();
}
}
@Override
@PreAuthorize("isAuthenticated() and hasPermission(#questionId, 'question', 'owner')")
public void resetPiRoundState(final String questionId) {
final Question question = databaseDao.getQuestion(questionId);
final Session session = databaseDao.getSessionFromKeyword(question.getSessionKeyword());
cancelDelayedPiRoundChange(questionId);
if ("freetext".equals(question.getQuestionType())) {
question.setPiRound(0);
} else {
question.setPiRound(1);
}
question.resetRoundManagementState();
databaseDao.deleteAnswers(question);
update(question);
this.publisher.publishEvent(new PiRoundResetEvent(this, session, question));
}
@Override
@PreAuthorize("isAuthenticated() and hasPermission(#questionId, 'question', 'owner')")
public void setVotingAdmission(final String questionId, final boolean disableVoting) {
final Question question = databaseDao.getQuestion(questionId);
final Session session = databaseDao.getSessionFromKeyword(question.getSessionKeyword());
question.setVotingDisabled(disableVoting);
if (!disableVoting && !question.isActive()) {
question.setActive(true);
update(question);
} else {
databaseDao.updateQuestion(question);
}
NovaEvent event;
if (disableVoting) {
event = new LockVoteEvent(this, session, question);
} else {
event = new UnlockVoteEvent(this, session, question);
}
this.publisher.publishEvent(event);
}
@Override
@PreAuthorize("isAuthenticated()")
public void setVotingAdmissions(final String sessionkey, final boolean disableVoting, List<Question> questions) {
final User user = getCurrentUser();
final Session session = getSession(sessionkey);
if (!session.isCreator(user)) {
throw new UnauthorizedException();
}
databaseDao.setVotingAdmissions(session, disableVoting, questions);
NovaEvent event;
if (disableVoting) {
event = new LockVotesEvent(this, session, questions);
} else {
event = new UnlockVotesEvent(this, session, questions);
}
this.publisher.publishEvent(event);
}
@Override
@PreAuthorize("isAuthenticated()")
public void setVotingAdmissionForAllQuestions(final String sessionkey, final boolean disableVoting) {
final User user = getCurrentUser();
final Session session = getSession(sessionkey);
if (!session.isCreator(user)) {
throw new UnauthorizedException();
}
final List<Question> questions = databaseDao.setVotingAdmissionForAllQuestions(session, disableVoting);
NovaEvent event;
if (disableVoting) {
event = new LockVotesEvent(this, session, questions);
} else {
event = new UnlockVotesEvent(this, session, questions);
}
this.publisher.publishEvent(event);
}
private Session getSessionWithAuthCheck(final String sessionKeyword) {
final User user = userService.getCurrentUser();
final Session session = databaseDao.getSessionFromKeyword(sessionKeyword);
if (user == null || session == null || !session.isCreator(user)) {
throw new UnauthorizedException();
}
return session;
}
@Override
@PreAuthorize("isAuthenticated() and hasPermission(#questionId, 'interposedquestion', 'owner')")
public void deleteInterposedQuestion(final String questionId) {
final InterposedQuestion question = databaseDao.getInterposedQuestion(questionId);
if (question == null) {
throw new NotFoundException();
}
databaseDao.deleteInterposedQuestion(question);
final Session session = databaseDao.getSessionFromKeyword(question.getSessionId());
final DeleteInterposedQuestionEvent event = new DeleteInterposedQuestionEvent(this, session, question);
this.publisher.publishEvent(event);
}
@Override
@PreAuthorize("isAuthenticated()")
public void deleteAllInterposedQuestions(final String sessionKeyword) {
final Session session = databaseDao.getSessionFromKeyword(sessionKeyword);
if (session == null) {
throw new UnauthorizedException();
}
final User user = getCurrentUser();
if (session.isCreator(user)) {
databaseDao.deleteAllInterposedQuestions(session);
} else {
databaseDao.deleteAllInterposedQuestions(session, user);
}
}
@Override
@PreAuthorize("isAuthenticated() and hasPermission(#questionId, 'question', 'owner')")
public void deleteAnswers(final String questionId) {
final Question question = databaseDao.getQuestion(questionId);
question.resetQuestionState();
databaseDao.updateQuestion(question);
databaseDao.deleteAnswers(question);
}
@Override
@PreAuthorize("isAuthenticated()")
public List<String> getUnAnsweredQuestionIds(final String sessionKey) {
final User user = getCurrentUser();
final Session session = getSession(sessionKey);
return databaseDao.getUnAnsweredQuestionIds(session, user);
}
private User getCurrentUser() {
final User user = userService.getCurrentUser();
if (user == null) {
throw new UnauthorizedException();
}
return user;
}
@Override
@PreAuthorize("isAuthenticated()")
public Answer getMyAnswer(final String questionId) {
final Question question = getQuestion(questionId);
if (question == null) {
throw new NotFoundException();
}
return databaseDao.getMyAnswer(userService.getCurrentUser(), questionId, question.getPiRound());
}
@Override
public void readFreetextAnswer(final String answerId, final User user) {
final Answer answer = databaseDao.getObjectFromId(answerId, Answer.class);
if (answer == null) {
throw new NotFoundException();
}
if (answer.isRead()) {
return;
}
final Session session = databaseDao.getSessionFromId(answer.getSessionId());
if (session.isCreator(user)) {
answer.setRead(true);
databaseDao.updateAnswer(answer);
}
}
@Override
@PreAuthorize("isAuthenticated()")
public List<Answer> getAnswers(final String questionId, final int piRound, final int offset, final int limit) {
final Question question = databaseDao.getQuestion(questionId);
if (question == null) {
throw new NotFoundException();
}
return "freetext".equals(question.getQuestionType())
? getFreetextAnswers(questionId, offset, limit)
: databaseDao.getAnswers(question, piRound);
}
@Override
@PreAuthorize("isAuthenticated()")
public List<Answer> getAnswers(final String questionId, final int offset, final int limit) {
final Question question = getQuestion(questionId);
if (question == null) {
throw new NotFoundException();
}
if ("freetext".equals(question.getQuestionType())) {
return getFreetextAnswers(questionId, offset, limit);
} else {
return databaseDao.getAnswers(question);
}
}
@Override
@PreAuthorize("isAuthenticated()")
public List<Answer> getAllAnswers(final String questionId, final int offset, final int limit) {
final Question question = getQuestion(questionId);
if (question == null) {
throw new NotFoundException();
}
if ("freetext".equals(question.getQuestionType())) {
return getFreetextAnswers(questionId, offset, limit);
} else {
return databaseDao.getAllAnswers(question);
}
}
@Override
@PreAuthorize("isAuthenticated()")
public int getAnswerCount(final String questionId) {
final Question question = getQuestion(questionId);
if (question == null) {
return 0;
}
if ("freetext".equals(question.getQuestionType())) {
return databaseDao.getTotalAnswerCountByQuestion(question);
} else {
return databaseDao.getAnswerCount(question, question.getPiRound());
}
}
@Override
@PreAuthorize("isAuthenticated()")
public int getAnswerCount(final String questionId, final int piRound) {
final Question question = getQuestion(questionId);
if (question == null) {
return 0;
}
return databaseDao.getAnswerCount(question, piRound);
}
@Override
@PreAuthorize("isAuthenticated()")
public int getAbstentionAnswerCount(final String questionId) {
final Question question = getQuestion(questionId);
if (question == null) {
return 0;
}
return databaseDao.getAbstentionAnswerCount(questionId);
}
@Override
@PreAuthorize("isAuthenticated()")
public int getTotalAnswerCountByQuestion(final String questionId) {
final Question question = getQuestion(questionId);
if (question == null) {
return 0;
}
return databaseDao.getTotalAnswerCountByQuestion(question);
}
@Override
@PreAuthorize("isAuthenticated()")
public List<Answer> getFreetextAnswers(final String questionId, final int offset, final int limit) {
final List<Answer> answers = databaseDao.getFreetextAnswers(questionId, offset, limit);
if (answers == null) {
throw new NotFoundException();
}
/* Remove user for privacy concerns */
for (Answer answer : answers) {
answer.setUser(null);
}
return answers;
}
@Override
@PreAuthorize("isAuthenticated()")
public List<Answer> getMyAnswers(final String sessionKey) {
final Session session = getSession(sessionKey);
// Load questions first because we are only interested in answers of the latest piRound.
final List<Question> questions = databaseDao.getSkillQuestionsForUsers(session);
final Map<String, Question> questionIdToQuestion = new HashMap<>();
for (final Question question : questions) {
questionIdToQuestion.put(question.get_id(), question);
}
/* filter answers by active piRound per question */
final List<Answer> answers = databaseDao.getMyAnswers(userService.getCurrentUser(), session);
final List<Answer> filteredAnswers = new ArrayList<>();
for (final Answer answer : answers) {
final Question question = questionIdToQuestion.get(answer.getQuestionId());
if (question == null) {
// Question is not present. Most likely it has been locked by the
// Session's creator. Locked Questions do not appear in this list.
continue;
}
if (0 == answer.getPiRound() && !"freetext".equals(question.getQuestionType())) {
answer.setPiRound(1);
}
// discard all answers that aren't in the same piRound as the question
if (answer.getPiRound() == question.getPiRound()) {
filteredAnswers.add(answer);
}
}
return filteredAnswers;
}
@Override
@PreAuthorize("isAuthenticated()")
public int getTotalAnswerCount(final String sessionKey) {
return databaseDao.getTotalAnswerCount(sessionKey);
}
@Override
@PreAuthorize("isAuthenticated()")
public int getInterposedCount(final String sessionKey) {
return databaseDao.getInterposedCount(sessionKey);
}
@Override
@PreAuthorize("isAuthenticated()")
public InterposedReadingCount getInterposedReadingCount(final String sessionKey, String username) {
final Session session = databaseDao.getSessionFromKeyword(sessionKey);
if (session == null) {
throw new NotFoundException();
}
if (username == null) {
return databaseDao.getInterposedReadingCount(session);
} else {
User currentUser = userService.getCurrentUser();
if (!currentUser.getUsername().equals(username)) {
throw new ForbiddenException();
}
return databaseDao.getInterposedReadingCount(session, currentUser);
}
}
@Override
@PreAuthorize("isAuthenticated()")
public List<InterposedQuestion> getInterposedQuestions(final String sessionKey, final int offset, final int limit) {
final Session session = this.getSession(sessionKey);
final User user = getCurrentUser();
if (session.isCreator(user)) {
return databaseDao.getInterposedQuestions(session, offset, limit);
} else {
return databaseDao.getInterposedQuestions(session, user, offset, limit);
}
}
@Override
@PreAuthorize("isAuthenticated()")
public InterposedQuestion readInterposedQuestion(final String questionId) {
final User user = userService.getCurrentUser();
return this.readInterposedQuestionInternal(questionId, user);
}
/*
* The "internal" suffix means it is called by internal services that have no authentication!
* TODO: Find a better way of doing this...
*/
@Override
public InterposedQuestion readInterposedQuestionInternal(final String questionId, User user) {
final InterposedQuestion question = databaseDao.getInterposedQuestion(questionId);
if (question == null) {
throw new NotFoundException();
}
final Session session = databaseDao.getSessionFromKeyword(question.getSessionId());
if (!question.isCreator(user) && !session.isCreator(user)) {
throw new UnauthorizedException();
}
if (session.isCreator(user)) {
databaseDao.markInterposedQuestionAsRead(question);
}
return question;
}
@Override
@PreAuthorize("isAuthenticated()")
public Question update(final Question question) {
final User user = userService.getCurrentUser();
return update(question, user);
}
@Override
@PreAuthorize("isAuthenticated()")
public Question update(final Question question, User user) {
final Question oldQuestion = databaseDao.getQuestion(question.get_id());
if (null == oldQuestion) {
throw new NotFoundException();
}
final Session session = databaseDao.getSessionFromKeyword(question.getSessionKeyword());
if (user == null || session == null || !session.isCreator(user)) {
throw new UnauthorizedException();
}
if ("freetext".equals(question.getQuestionType())) {
question.setPiRound(0);
} else if (question.getPiRound() < 1 || question.getPiRound() > 2) {
question.setPiRound(oldQuestion.getPiRound() > 0 ? oldQuestion.getPiRound() : 1);
}
final Question result = databaseDao.updateQuestion(question);
if (!oldQuestion.isActive() && question.isActive()) {
final UnlockQuestionEvent event = new UnlockQuestionEvent(this, session, result);
this.publisher.publishEvent(event);
} else if (oldQuestion.isActive() && !question.isActive()) {
final LockQuestionEvent event = new LockQuestionEvent(this, session, result);
this.publisher.publishEvent(event);
}
return result;
}
@Override
@PreAuthorize("isAuthenticated()")
public Answer saveAnswer(final String questionId, final de.thm.arsnova.entities.transport.Answer answer) {
final User user = getCurrentUser();
final Question question = getQuestion(questionId);
if (question == null) {
throw new NotFoundException();
}
Answer theAnswer = answer.generateAnswerEntity(user, question);
if ("freetext".equals(question.getQuestionType())) {
imageUtils.generateThumbnailImage(theAnswer);
if (question.isFixedAnswer() && question.getText() != null) {
theAnswer.setAnswerTextRaw(theAnswer.getAnswerText());
if (question.isStrictMode()) {
question.checkTextStrictOptions(theAnswer);
}
theAnswer.setQuestionValue(question.evaluateCorrectAnswerFixedText(theAnswer.getAnswerTextRaw()));
theAnswer.setSuccessfulFreeTextAnswer(question.isSuccessfulFreeTextAnswer(theAnswer.getAnswerTextRaw()));
}
}
return databaseDao.saveAnswer(theAnswer, user, question, getSession(question.getSessionKeyword()));
}
@Override
@PreAuthorize("isAuthenticated()")
public Answer updateAnswer(final Answer answer) {
final User user = userService.getCurrentUser();
final Answer realAnswer = this.getMyAnswer(answer.getQuestionId());
if (user == null || realAnswer == null || !user.getUsername().equals(realAnswer.getUser())) {
throw new UnauthorizedException();
}
final Question question = getQuestion(answer.getQuestionId());
if ("freetext".equals(question.getQuestionType())) {
imageUtils.generateThumbnailImage(realAnswer);
question.checkTextStrictOptions(realAnswer);
}
final Answer result = databaseDao.updateAnswer(realAnswer);
final Session session = databaseDao.getSessionFromKeyword(question.getSessionKeyword());
this.publisher.publishEvent(new NewAnswerEvent(this, session, result, user, question));
return result;
}
@Override
@PreAuthorize("isAuthenticated()")
public void deleteAnswer(final String questionId, final String answerId) {
final Question question = databaseDao.getQuestion(questionId);
if (question == null) {
throw new NotFoundException();
}
final User user = userService.getCurrentUser();
final Session session = databaseDao.getSessionFromKeyword(question.getSessionKeyword());
if (user == null || session == null || !session.isCreator(user)) {
throw new UnauthorizedException();
}
databaseDao.deleteAnswer(answerId);
this.publisher.publishEvent(new DeleteAnswerEvent(this, session, question));
}
@Override
@PreAuthorize("isAuthenticated()")
public List<Question> getLectureQuestions(final String sessionkey) {
final Session session = getSession(sessionkey);
final User user = userService.getCurrentUser();
if (session.isCreator(user)) {
return databaseDao.getLectureQuestionsForTeachers(session);
} else {
return databaseDao.getLectureQuestionsForUsers(session);
}
}
@Override
@PreAuthorize("isAuthenticated()")
public List<Question> getFlashcards(final String sessionkey) {
final Session session = getSession(sessionkey);
final User user = userService.getCurrentUser();
if (session.isCreator(user)) {
return databaseDao.getFlashcardsForTeachers(session);
} else {
return databaseDao.getFlashcardsForUsers(session);
}
}
@Override
@PreAuthorize("isAuthenticated()")
public List<Question> getPreparationQuestions(final String sessionkey) {
final Session session = getSession(sessionkey);
final User user = userService.getCurrentUser();
if (session.isCreator(user)) {
return databaseDao.getPreparationQuestionsForTeachers(session);
} else {
return databaseDao.getPreparationQuestionsForUsers(session);
}
}
@Override
@PreAuthorize("isAuthenticated()")
public List<Question> replaceImageData(final List<Question> questions) {
for (Question q : questions) {
if (q.getImage() != null && q.getImage().startsWith("data:image/")) {
q.setImage("true");
}
}
return questions;
}
private Session getSession(final String sessionkey) {
final Session session = databaseDao.getSessionFromKeyword(sessionkey);
if (session == null) {
throw new NotFoundException();
}
return session;
}
@Override
@PreAuthorize("isAuthenticated()")
public int getLectureQuestionCount(final String sessionkey) {
return databaseDao.getLectureQuestionCount(getSession(sessionkey));
}
@Override
@PreAuthorize("isAuthenticated()")
public int getFlashcardCount(final String sessionkey) {
return databaseDao.getFlashcardCount(getSession(sessionkey));
}
@Override
@PreAuthorize("isAuthenticated()")
public int getPreparationQuestionCount(final String sessionkey) {
return databaseDao.getPreparationQuestionCount(getSession(sessionkey));
}
@Override
@PreAuthorize("isAuthenticated()")
public int countLectureQuestionAnswers(final String sessionkey) {
return this.countLectureQuestionAnswersInternal(sessionkey);
}
/*
* The "internal" suffix means it is called by internal services that have no authentication!
* TODO: Find a better way of doing this...
*/
@Override
public int countLectureQuestionAnswersInternal(final String sessionkey) {
return databaseDao.countLectureQuestionAnswers(getSession(sessionkey));
}
@Override
public Map<String, Object> getAnswerAndAbstentionCountInternal(final String questionId) {
final Question question = getQuestion(questionId);
HashMap<String, Object> map = new HashMap<>();
if (question == null) {
return null;
}
map.put("_id", questionId);
map.put("answers", databaseDao.getAnswerCount(question, question.getPiRound()));
map.put("abstentions", databaseDao.getAbstentionAnswerCount(questionId));
return map;
}
@Override
@PreAuthorize("isAuthenticated()")
public int countPreparationQuestionAnswers(final String sessionkey) {
return this.countPreparationQuestionAnswersInternal(sessionkey);
}
/*
* The "internal" suffix means it is called by internal services that have no authentication!
* TODO: Find a better way of doing this...
*/
@Override
public int countPreparationQuestionAnswersInternal(final String sessionkey) {
return databaseDao.countPreparationQuestionAnswers(getSession(sessionkey));
}
/*
* The "internal" suffix means it is called by internal services that have no authentication!
* TODO: Find a better way of doing this...
*/
@Override
public int countFlashcardsForUserInternal(final String sessionkey) {
return databaseDao.getFlashcardsForUsers(getSession(sessionkey)).size();
}
@Override
@PreAuthorize("isAuthenticated()")
public void deleteLectureQuestions(final String sessionkey) {
final Session session = getSessionWithAuthCheck(sessionkey);
databaseDao.deleteAllLectureQuestionsWithAnswers(session);
}
@Override
@PreAuthorize("isAuthenticated()")
public void deleteFlashcards(final String sessionkey) {
final Session session = getSessionWithAuthCheck(sessionkey);
databaseDao.deleteAllFlashcardsWithAnswers(session);
}
@Override
@PreAuthorize("isAuthenticated()")
public void deletePreparationQuestions(final String sessionkey) {
final Session session = getSessionWithAuthCheck(sessionkey);
databaseDao.deleteAllPreparationQuestionsWithAnswers(session);
}
@Override
@PreAuthorize("isAuthenticated()")
public List<String> getUnAnsweredLectureQuestionIds(final String sessionkey) {
final User user = getCurrentUser();
return this.getUnAnsweredLectureQuestionIds(sessionkey, user);
}
@Override
public List<String> getUnAnsweredLectureQuestionIds(final String sessionkey, final User user) {
final Session session = getSession(sessionkey);
return databaseDao.getUnAnsweredLectureQuestionIds(session, user);
}
@Override
@PreAuthorize("isAuthenticated()")
public List<String> getUnAnsweredPreparationQuestionIds(final String sessionkey) {
final User user = getCurrentUser();
return this.getUnAnsweredPreparationQuestionIds(sessionkey, user);
}
@Override
public List<String> getUnAnsweredPreparationQuestionIds(final String sessionkey, final User user) {
final Session session = getSession(sessionkey);
return databaseDao.getUnAnsweredPreparationQuestionIds(session, user);
}
@Override
@PreAuthorize("isAuthenticated()")
public void publishAll(final String sessionkey, final boolean publish) {
final User user = getCurrentUser();
final Session session = getSession(sessionkey);
if (!session.isCreator(user)) {
throw new UnauthorizedException();
}
final List<Question> questions = databaseDao.publishAllQuestions(session, publish);
NovaEvent event;
if (publish) {
event = new UnlockQuestionsEvent(this, session, questions);
} else {
event = new LockQuestionsEvent(this, session, questions);
}
this.publisher.publishEvent(event);
}
@Override
@PreAuthorize("isAuthenticated()")
public void publishQuestions(final String sessionkey, final boolean publish, List<Question> questions) {
final User user = getCurrentUser();
final Session session = getSession(sessionkey);
if (!session.isCreator(user)) {
throw new UnauthorizedException();
}
databaseDao.publishQuestions(session, publish, questions);
NovaEvent event;
if (publish) {
event = new UnlockQuestionsEvent(this, session, questions);
} else {
event = new LockQuestionsEvent(this, session, questions);
}
this.publisher.publishEvent(event);
}
@Override
@PreAuthorize("isAuthenticated()")
public void deleteAllQuestionsAnswers(final String sessionkey) {
final User user = getCurrentUser();
final Session session = getSession(sessionkey);
if (!session.isCreator(user)) {
throw new UnauthorizedException();
}
databaseDao.deleteAllQuestionsAnswers(session);
this.publisher.publishEvent(new DeleteAllQuestionsAnswersEvent(this, session));
}
@Override
@PreAuthorize("isAuthenticated() and hasPermission(#sessionkey, 'session', 'owner')")
public void deleteAllPreparationAnswers(String sessionkey) {
final Session session = getSession(sessionkey);
databaseDao.deleteAllPreparationAnswers(session);
this.publisher.publishEvent(new DeleteAllPreparationAnswersEvent(this, session));
}
@Override
@PreAuthorize("isAuthenticated() and hasPermission(#sessionkey, 'session', 'owner')")
public void deleteAllLectureAnswers(String sessionkey) {
final Session session = getSession(sessionkey);
databaseDao.deleteAllLectureAnswers(session);
this.publisher.publishEvent(new DeleteAllLectureAnswersEvent(this, session));
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
this.publisher = publisher;
}
@Override
public String getImage(String questionId, String answerId) {
final List<Answer> answers = getAnswers(questionId, -1, -1);
Answer answer = null;
for (Answer a : answers) {
if (answerId.equals(a.get_id())) {
answer = a;
break;
}
}
if (answer == null) {
throw new NotFoundException();
}
return answer.getAnswerImage();
}
@Override
public String getQuestionImage(String questionId) {
Question question = databaseDao.getQuestion(questionId);
String imageData = question.getImage();
if (imageData == null) {
imageData = "";
}
return imageData;
}
@Override
public String getQuestionFcImage(String questionId) {
Question question = databaseDao.getQuestion(questionId);
String imageData = question.getFcImage();
if (imageData == null) {
imageData = "";
}
return imageData;
}
}