diff --git a/src/main/java/cz/muni/ics/kypo/training/adaptive/controller/TasksController.java b/src/main/java/cz/muni/ics/kypo/training/adaptive/controller/TasksController.java index 2f3a89270658263c2462870e0fe66fde01441ab9..248854552e18f436e64205a1920b7f57711d1741 100644 --- a/src/main/java/cz/muni/ics/kypo/training/adaptive/controller/TasksController.java +++ b/src/main/java/cz/muni/ics/kypo/training/adaptive/controller/TasksController.java @@ -1,5 +1,6 @@ package cz.muni.ics.kypo.training.adaptive.controller; +import cz.muni.ics.kypo.training.adaptive.dto.training.TaskCopyDTO; import cz.muni.ics.kypo.training.adaptive.dto.training.TaskDTO; import cz.muni.ics.kypo.training.adaptive.dto.training.TaskUpdateDTO; import cz.muni.ics.kypo.training.adaptive.service.TaskService; @@ -82,8 +83,9 @@ public class TasksController { @ApiParam(value = "Training phase ID", required = true) @PathVariable(name = "phaseId") Long phaseId, @ApiParam(value = "Task ID", required = true) - @PathVariable(name = "taskId") Long taskId) { - TaskDTO createdTask = taskService.cloneTask(definitionId, phaseId, taskId); + @PathVariable(name = "taskId") Long taskId, + @RequestBody @Valid TaskCopyDTO taskCopyDTO) { + TaskDTO createdTask = taskService.cloneTask(definitionId, phaseId, taskId, taskCopyDTO); return new ResponseEntity<>(createdTask, HttpStatus.CREATED); } diff --git a/src/main/java/cz/muni/ics/kypo/training/adaptive/dto/training/TaskCopyDTO.java b/src/main/java/cz/muni/ics/kypo/training/adaptive/dto/training/TaskCopyDTO.java new file mode 100644 index 0000000000000000000000000000000000000000..942accf9ed48a05512b4348c08e6b2bb047d73fa --- /dev/null +++ b/src/main/java/cz/muni/ics/kypo/training/adaptive/dto/training/TaskCopyDTO.java @@ -0,0 +1,82 @@ +package cz.muni.ics.kypo.training.adaptive.dto.training; + +import io.swagger.annotations.ApiModelProperty; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.PositiveOrZero; + +public class TaskCopyDTO { + + @ApiModelProperty(value = "Short description of task", required = true, example = "Task title") + @NotEmpty(message = "Task title must not be blank") + private String title; + + @ApiModelProperty(value = "The information that are displayed to a player", required = true, example = "Capture the flag") + @NotEmpty(message = "Task content must not be blank") + private String content; + + @ApiModelProperty(value = "Keyword that must be found in the task. Necessary in order to get to the next phase", required = true, example = "secretFlag") + @NotEmpty(message = "Answer of task cannot be null") + private String answer; + + @ApiModelProperty(value = "Description how to get the answer", required = true, example = "Open secret.txt") + @NotEmpty(message = "Solution of task cannot be null") + private String solution; + + @ApiModelProperty(value = "It defines the allowed number of incorrect answers submitted by the player", required = true, example = "5") + @NotNull(message = "Limit of the number of provided incorrect answers must be specified") + @PositiveOrZero(message = "Limit of the number of provided incorrect answers must not be a negative number") + private Integer incorrectAnswerLimit; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public String getAnswer() { + return answer; + } + + public void setAnswer(String answer) { + this.answer = answer; + } + + public String getSolution() { + return solution; + } + + public void setSolution(String solution) { + this.solution = solution; + } + + public Integer getIncorrectAnswerLimit() { + return incorrectAnswerLimit; + } + + public void setIncorrectAnswerLimit(Integer incorrectAnswerLimit) { + this.incorrectAnswerLimit = incorrectAnswerLimit; + } + + @Override + public String toString() { + return "TaskCopyDTO{" + + "title='" + title + '\'' + + ", content='" + content + '\'' + + ", answer='" + answer + '\'' + + ", solution='" + solution + '\'' + + ", incorrectAnswerLimit=" + incorrectAnswerLimit + + '}'; + } +} diff --git a/src/main/java/cz/muni/ics/kypo/training/adaptive/mapper/BeanMapper.java b/src/main/java/cz/muni/ics/kypo/training/adaptive/mapper/BeanMapper.java index 861e6022770bed61c9232411b9d8d284e101c8f8..192e806c87e91ceaa035497ea765f44a0edf3b6f 100644 --- a/src/main/java/cz/muni/ics/kypo/training/adaptive/mapper/BeanMapper.java +++ b/src/main/java/cz/muni/ics/kypo/training/adaptive/mapper/BeanMapper.java @@ -20,6 +20,7 @@ import cz.muni.ics.kypo.training.adaptive.dto.questionnaire.QuestionUpdateDTO; import cz.muni.ics.kypo.training.adaptive.dto.questionnaire.QuestionnairePhaseDTO; import cz.muni.ics.kypo.training.adaptive.dto.questionnaire.QuestionnaireUpdateDTO; import cz.muni.ics.kypo.training.adaptive.dto.training.DecisionMatrixRowDTO; +import cz.muni.ics.kypo.training.adaptive.dto.training.TaskCopyDTO; import cz.muni.ics.kypo.training.adaptive.dto.training.TaskDTO; import cz.muni.ics.kypo.training.adaptive.dto.training.TaskUpdateDTO; import cz.muni.ics.kypo.training.adaptive.dto.training.TrainingPhaseDTO; @@ -59,6 +60,8 @@ public interface BeanMapper { Task toEntity(TaskUpdateDTO taskUpdateDto); + Task toEntity(TaskCopyDTO taskCopyDTO); + @Mapping(target = "phaseType", constant = "INFO") InfoPhaseDTO toDto(InfoPhase infoPhase); diff --git a/src/main/java/cz/muni/ics/kypo/training/adaptive/service/TaskService.java b/src/main/java/cz/muni/ics/kypo/training/adaptive/service/TaskService.java index e275b1efd99f3a92f7a21a5f628d66a42f7c5afb..a4498217eef466dea946e73f7b2d94c6e6c03997 100644 --- a/src/main/java/cz/muni/ics/kypo/training/adaptive/service/TaskService.java +++ b/src/main/java/cz/muni/ics/kypo/training/adaptive/service/TaskService.java @@ -2,6 +2,7 @@ package cz.muni.ics.kypo.training.adaptive.service; import cz.muni.ics.kypo.training.adaptive.domain.Task; import cz.muni.ics.kypo.training.adaptive.domain.TrainingPhase; +import cz.muni.ics.kypo.training.adaptive.dto.training.TaskCopyDTO; import cz.muni.ics.kypo.training.adaptive.dto.training.TaskDTO; import cz.muni.ics.kypo.training.adaptive.dto.training.TaskUpdateDTO; import cz.muni.ics.kypo.training.adaptive.mapper.BeanMapper; @@ -9,7 +10,6 @@ import cz.muni.ics.kypo.training.adaptive.repository.TaskRepository; import cz.muni.ics.kypo.training.adaptive.repository.TrainingPhaseRepository; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -50,19 +50,14 @@ public class TaskService { return BeanMapper.INSTANCE.toDto(persistedEntity); } - public TaskDTO cloneTask(Long trainingDefinitionId, Long phaseId, Long taskId) { - Task taskToBeCloned = taskRepository.findById(taskId) - .orElseThrow(() -> new RuntimeException("Task was not found")); - // TODO throw proper exception once kypo2-training is migrated + public TaskDTO cloneTask(Long trainingDefinitionId, Long phaseId, Long taskId, TaskCopyDTO taskCopyDTO) { + Task task = BeanMapper.INSTANCE.toEntity(taskCopyDTO); TrainingPhase trainingPhase = trainingPhaseRepository.findById(phaseId) .orElseThrow(() -> new RuntimeException("Game phase was not found")); // TODO add check to trainingDefinitionId (field structure will be probably changed) - Task task = new Task(); - BeanUtils.copyProperties(taskToBeCloned, task); - task.setId(null); task.setTrainingPhase(trainingPhase); task.setOrder(taskRepository.getCurrentMaxOrder(phaseId) + 1);