de.thm.arsnova.services.QuestionService.java Source code

Java tutorial

Introduction

Here is the source code for de.thm.arsnova.services.QuestionService.java

Source

/*
 * This file is part of ARSnova Backend.
 * Copyright (C) 2012-2015 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 java.util.AbstractMap;
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import java.util.Timer;
import java.util.TimerTask;

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 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.DeleteAllLectureAnswersEvent;
import de.thm.arsnova.events.DeleteAllPreparationAnswersEvent;
import de.thm.arsnova.events.DeleteAllQuestionsAnswersEvent;
import de.thm.arsnova.events.DeleteAnswerEvent;
import de.thm.arsnova.events.DeleteInterposedQuestionEvent;
import de.thm.arsnova.events.DeleteQuestionEvent;
import de.thm.arsnova.events.NewAnswerEvent;
import de.thm.arsnova.events.NewInterposedQuestionEvent;
import de.thm.arsnova.events.NewQuestionEvent;
import de.thm.arsnova.events.PiRoundDelayedStartEvent;
import de.thm.arsnova.events.PiRoundEndEvent;
import de.thm.arsnova.exceptions.BadRequestException;
import de.thm.arsnova.exceptions.ForbiddenException;
import de.thm.arsnova.exceptions.NotFoundException;
import de.thm.arsnova.exceptions.UnauthorizedException;

@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;

    public static final Logger LOGGER = LoggerFactory.getLogger(QuestionService.class);

    private HashMap<String, Timer> timerList = new HashMap<String, Timer>();

    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());

        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())) {
            if (question.getImage().startsWith("http")) {
                final String base64ImageString = imageUtils.encodeImageToString(question.getImage());
                if (base64ImageString == null) {
                    throw new BadRequestException();
                }
                question.setImage(base64ImageString);
            }

            // 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 " + fileSize + " Byte.");
                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);
        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 DeleteQuestionEvent event = new DeleteQuestionEvent(this, session);
        this.publisher.publishEvent(event);
    }

    @Override
    public void startNewPiRound(final String questionId, User user) {
        if (null == user) {
            user = userService.getCurrentUser();
        }

        cancelDelayedPiRoundChange(questionId);

        final Question question = databaseDao.getQuestion(questionId);
        final Session session = databaseDao.getSessionFromKeyword(question.getSessionKeyword());

        question.setPiRound(question.getPiRound() + 1);
        question.setActive(false);
        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 Timer timer = new Timer();
        final Date date = new Date();
        final Date endDate = new Date(date.getTime() + (time * 1000));
        final IQuestionService questionService = this;
        final User user = userService.getCurrentUser();
        final Question question = databaseDao.getQuestion(questionId);
        final Session session = databaseDao.getSessionFromKeyword(question.getSessionKeyword());

        cancelDelayedPiRoundChange(questionId);

        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                questionService.startNewPiRound(questionId, user);
            }
        }, endDate);

        timerList.put(questionId, timer);
        question.setPiRoundActive(true);
        question.setPiRoundStartTime(date.getTime());
        question.setPiRoundEndTime(endDate.getTime());
        update(question);

        this.publisher.publishEvent(new PiRoundDelayedStartEvent(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();
        }
    }

    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);
        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
    @PreAuthorize("isAuthenticated()")
    public List<Answer> getAnswers(final String questionId, final int piRound) {
        final Question question = databaseDao.getQuestion(questionId);
        if (question == null) {
            throw new NotFoundException();
        }
        return "freetext".equals(question.getQuestionType()) ? getFreetextAnswers(questionId)
                : databaseDao.getAnswers(question, piRound);
    }

    @Override
    @PreAuthorize("isAuthenticated()")
    public List<Answer> getAnswers(final String questionId) {
        final Question question = getQuestion(questionId);
        if (question == null) {
            throw new NotFoundException();
        }
        if ("freetext".equals(question.getQuestionType())) {
            return getFreetextAnswers(questionId);
        } else {
            return databaseDao.getAnswers(question);
        }
    }

    @Override
    @PreAuthorize("isAuthenticated()")
    public int getAnswerCount(final String questionId) {
        final Question question = getQuestion(questionId);
        if (question == null) {
            return 0;
        }

        return databaseDao.getAnswerCount(question, question.getPiRound());
    }

    @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 List<Answer> getFreetextAnswers(final String questionId) {
        final List<Answer> answers = databaseDao.getFreetextAnswers(questionId);
        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<String, Question>();
        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<Answer>();
        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 Session session = this.getSession(sessionKey);
        final User user = getCurrentUser();
        if (session.isCreator(user)) {
            return databaseDao.getInterposedQuestions(session);
        } else {
            return databaseDao.getInterposedQuestions(session, user);
        }
    }

    @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 NewQuestionEvent event = new NewQuestionEvent(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);
        }

        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);
        }
        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);
        }
    }

    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 SimpleEntry<String, List<Integer>> getAnswerAndAbstentionCountByQuestion(final String questionid) {
        final List<Integer> countList = Arrays.asList(getAnswerCount(questionid),
                getAbstentionAnswerCount(questionid));

        return new AbstractMap.SimpleEntry<String, List<Integer>>(questionid, countList);
    }

    @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
    @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));
    }

    @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();
        }
        databaseDao.publishAllQuestions(session, publish);
    }

    @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);
    }

    @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);
        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();
    }
}