Completed
Push — dev ( 9cd69f...ee7eb8 )
by Konstantin
10s
created

create(Question)   A

Complexity

Conditions 2

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 14
rs 9.7
cc 2
1
package easytests.api.v1.controllers;
2
3
import easytests.api.v1.exceptions.*;
4
import easytests.api.v1.mappers.QuestionsMapper;
5
import easytests.api.v1.models.Identity;
6
import easytests.api.v1.models.Question;
7
import easytests.core.models.QuestionModel;
8
import easytests.core.models.QuestionModelInterface;
9
import easytests.core.models.TopicModelInterface;
10
import easytests.core.options.AnswersOptions;
11
import easytests.core.options.QuestionsOptions;
12
import easytests.core.options.QuestionsOptionsInterface;
13
import easytests.core.options.builder.QuestionsOptionsBuilderInterface;
14
import easytests.core.options.builder.TopicsOptionsBuilderInterface;
15
import easytests.core.services.QuestionsServiceInterface;
16
import easytests.core.services.TopicsServiceInterface;
17
import java.util.List;
18
import java.util.stream.Collectors;
19
import org.springframework.beans.factory.annotation.Autowired;
20
import org.springframework.beans.factory.annotation.Qualifier;
21
import org.springframework.http.HttpStatus;
22
import org.springframework.web.bind.annotation.*;
23
24
25
/**
26
 * @author RisaMagpie
27
 */
28
@RestController("QuestionsControllerV1")
29
@SuppressWarnings("checkstyle:MultipleStringLiterals")
30
@RequestMapping("/v1/questions")
31
public class QuestionsController extends AbstractController {
32
    @Autowired
33
    protected QuestionsServiceInterface questionsService;
34
35
    @Autowired
36
    protected TopicsServiceInterface topicsService;
37
38
    @Autowired
39
    protected QuestionsOptionsBuilderInterface questionsOptionsBuilder;
40
41
    @Autowired
42
    protected TopicsOptionsBuilderInterface topicsOptionsBuilder;
43
44
    @Autowired
45
    @Qualifier("QuestionsMapperV1")
46
    private QuestionsMapper questionsMapper;
47
48
    @GetMapping
49
    public List<Question> list(@RequestParam(name = "topicId", required = true) Integer topicId)
50
            throws NotFoundException, ForbiddenException {
51
        final TopicModelInterface topicModel = this.topicsService.find(topicId, this.topicsOptionsBuilder.forAuth());
52
53
        if (topicModel == null) {
54
            throw new NotFoundException();
55
        }
56
57
        if (!this.acl.hasAccess(topicModel)) {
58
            throw new ForbiddenException();
59
        }
60
61
        final List<QuestionModelInterface> questionsModels =
62
                this.questionsService.findByTopic(topicModel, new QuestionsOptions().withAnswers(new AnswersOptions()));
63
64
        return questionsModels
65
                .stream()
66
                .map(model -> this.questionsMapper.map(model, Question.class))
67
                .collect(Collectors.toList());
68
    }
69
70
    @PostMapping("")
71
    @ResponseStatus(HttpStatus.CREATED)
72
    public Identity create(@RequestBody Question question) throws Exception {
0 ignored issues
show
Best Practice introduced by
Dedicated exceptions should be preferred over throwing the generic Exception.
Loading history...
73
        if (question.getId() != null) {
74
            throw new IdentifiedModelException();
75
        }
76
77
        this.checkTopic(question.getTopic().getId());
78
79
        final QuestionModelInterface questionModel = this.questionsMapper.map(question, QuestionModel.class);
80
81
        this.questionsService.save(questionModel, new QuestionsOptions().withAnswers(new AnswersOptions()));
82
83
        return this.questionsMapper.map(questionModel, Identity.class);
84
    }
85
86
    @PutMapping("")
87
    public void update(@RequestBody Question question)
88
            throws ForbiddenException, NotFoundException, BadRequestException {
89
        if (question.getId() == null) {
90
            throw new UnidentifiedModelException();
91
        }
92
93
        final QuestionModelInterface questionModel = this.getQuestionModel(question.getId());
94
95
        if (!this.acl.hasAccess(questionModel)) {
96
            throw new ForbiddenException();
97
        }
98
        this.checkTopic(question.getTopic().getId());
99
100
        final QuestionsOptionsInterface questionOptionWithAnswers =
101
                new QuestionsOptions().withAnswers(new AnswersOptions());
102
103
        final QuestionModelInterface questionModelWithAnswers =
104
                this.questionsService.find(question.getId(), questionOptionWithAnswers);
105
106
        this.questionsMapper.map(question, questionModelWithAnswers);
107
        this.questionsService.save(questionModelWithAnswers, questionOptionWithAnswers);
108
    }
109
110
    @GetMapping("/{questionId}")
111
    public Question show(@PathVariable Integer questionId) throws NotFoundException, ForbiddenException {
112
        final QuestionModelInterface questionModel = this.getQuestionModel(
113
                questionId,
114
                this.questionsOptionsBuilder.forAuth().withAnswers(new AnswersOptions())
115
        );
116
        if (!this.acl.hasAccess(questionModel)) {
117
            throw new ForbiddenException();
118
        }
119
        return this.questionsMapper.map(questionModel, Question.class);
120
    }
121
122
    @DeleteMapping("/{questionId}")
123
    public void delete(@PathVariable Integer questionId) throws NotFoundException, ForbiddenException {
124
        final QuestionModelInterface questionModel = this.getQuestionModel(questionId);
125
        final QuestionsOptionsInterface questionOption = this.questionsOptionsBuilder.forDelete();
126
127
        if (!this.acl.hasAccess(questionModel)) {
128
            throw new ForbiddenException();
129
        }
130
131
        final QuestionModelInterface questionModelForDelete = this.questionsService.find(questionId, questionOption);
132
        this.questionsService.delete(questionModelForDelete, questionOption);
133
    }
134
135
    private void checkTopic(Integer topicId) throws BadRequestException {
136
        final TopicModelInterface topicModel = this.topicsService
137
                .find(topicId, this.topicsOptionsBuilder.forAuth());
138
139
        if (!this.acl.hasAccess(topicModel)) {
140
            throw new BadRequestException();
141
        }
142
    }
143
144
    private QuestionModelInterface getQuestionModel(Integer id, QuestionsOptionsInterface
145
            questionOptions) throws NotFoundException {
146
        final QuestionModelInterface questionModel = this.questionsService.find(id, questionOptions);
147
        if (questionModel == null) {
148
            throw new NotFoundException();
149
        }
150
        return questionModel;
151
    }
152
153
    private QuestionModelInterface getQuestionModel(Integer id) throws NotFoundException {
154
        return this.getQuestionModel(id, this.questionsOptionsBuilder.forAuth());
155
    }
156
}
157