From 10f4cbc258edf736a37fb49b3d0f5108e7259ce0 Mon Sep 17 00:00:00 2001 From: Jan Tymel <410388@mail.muni.cz> Date: Sun, 15 Nov 2020 10:32:42 +0100 Subject: [PATCH] First trivial iteration of working REST API that successfully saves training definition with corresponding levels --- .../controller/GameDefinitionController.java | 8 +- .../com/example/demo/domain/BaseLevel.java | 11 +++ .../demo/domain/TrainingDefinition.java | 17 ++++ .../com/example/demo/domain/UnityLevel.java | 6 +- .../com/example/demo/dto/BaseLevelDto.java | 11 +++ .../demo/dto/TrainingDefinitionDto.java | 13 +++ .../com/example/demo/dto/UnityLevelDto.java | 2 +- .../dto/input/GameDefinitionCreateDto.java | 85 +++++++++++++++++++ .../com/example/demo/mapper/BeanMapper.java | 29 +++++++ .../TrainingDefinitionRepository.java | 7 ++ .../demo/service/GameDefinitionService.java | 59 ++++++++----- 11 files changed, 218 insertions(+), 30 deletions(-) create mode 100644 src/main/java/com/example/demo/repository/TrainingDefinitionRepository.java diff --git a/src/main/java/com/example/demo/controller/GameDefinitionController.java b/src/main/java/com/example/demo/controller/GameDefinitionController.java index 18b333e2..00ef5d0c 100644 --- a/src/main/java/com/example/demo/controller/GameDefinitionController.java +++ b/src/main/java/com/example/demo/controller/GameDefinitionController.java @@ -1,5 +1,6 @@ package com.example.demo.controller; +import com.example.demo.dto.TrainingDefinitionDto; import com.example.demo.dto.input.GameDefinitionCreateDto; import com.example.demo.service.GameDefinitionService; import io.swagger.annotations.Api; @@ -40,8 +41,9 @@ public class GameDefinitionController { @ApiOperation(value = "Create a new game definition") @ApiResponses(value = {@ApiResponse(code = 200, message = "New game definition created"), @ApiResponse(code = 500, message = "Unexpected application error")}) - public GameDefinitionCreateDto createGameLevel(@ApiParam(value = "Game definition", required = true) @RequestBody(required = true) - List<GameDefinitionCreateDto> gameDefinition) { - return gameDefinitionService.createGameDefinition(gameDefinition); + public GameDefinitionCreateDto createGameLevel( + @ApiParam(value = "Game definition", required = true) @RequestBody(required = true) + TrainingDefinitionDto trainingDefinitionDto) { + return gameDefinitionService.createGameDefinition(trainingDefinitionDto); } } diff --git a/src/main/java/com/example/demo/domain/BaseLevel.java b/src/main/java/com/example/demo/domain/BaseLevel.java index 37f6ddf3..7d62c686 100644 --- a/src/main/java/com/example/demo/domain/BaseLevel.java +++ b/src/main/java/com/example/demo/domain/BaseLevel.java @@ -28,6 +28,9 @@ public abstract class BaseLevel { @ManyToOne(fetch = FetchType.LAZY) private UnityLevel unityLevel; + @ManyToOne(fetch = FetchType.LAZY) + private TrainingDefinition trainingDefinition; + public String getTitle() { return title; } @@ -76,6 +79,14 @@ public abstract class BaseLevel { this.unityLevel = unityLevel; } + public TrainingDefinition getTrainingDefinition() { + return trainingDefinition; + } + + public void setTrainingDefinition(TrainingDefinition trainingDefinition) { + this.trainingDefinition = trainingDefinition; + } + @Override public String toString() { return "BaseLevel{" + "title='" + title + '\'' + ", estimatedDuration='" + estimatedDuration + '\'' + diff --git a/src/main/java/com/example/demo/domain/TrainingDefinition.java b/src/main/java/com/example/demo/domain/TrainingDefinition.java index 79b634f7..243ce4da 100644 --- a/src/main/java/com/example/demo/domain/TrainingDefinition.java +++ b/src/main/java/com/example/demo/domain/TrainingDefinition.java @@ -1,10 +1,15 @@ package com.example.demo.domain; +import javax.persistence.CascadeType; import javax.persistence.Entity; +import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.Id; +import javax.persistence.OneToMany; +import javax.persistence.OrderBy; import java.time.LocalDateTime; import java.util.Arrays; +import java.util.List; @Entity public class TrainingDefinition { @@ -23,6 +28,10 @@ public class TrainingDefinition { private byte[] outcomes; private byte[] prerequisites; + @OrderBy + @OneToMany(mappedBy = "trainingDefinition", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY) + private List<BaseLevel> levels; + public Long getId() { return id; } @@ -103,6 +112,14 @@ public class TrainingDefinition { this.prerequisites = prerequisites; } + public List<BaseLevel> getLevels() { + return levels; + } + + public void setLevels(List<BaseLevel> levels) { + this.levels = levels; + } + @Override public String toString() { return "TrainingDefinition{" + "id=" + id + ", title='" + title + '\'' + ", lastEdited=" + lastEdited + diff --git a/src/main/java/com/example/demo/domain/UnityLevel.java b/src/main/java/com/example/demo/domain/UnityLevel.java index fe50f737..1b351a42 100644 --- a/src/main/java/com/example/demo/domain/UnityLevel.java +++ b/src/main/java/com/example/demo/domain/UnityLevel.java @@ -12,13 +12,13 @@ public class UnityLevel extends BaseLevel { @OrderBy @OneToMany(mappedBy = "unityLevel", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY) - private List<BaseLevel> subLevels; + private List<GameLevel> subLevels; - public List<BaseLevel> getSubLevels() { + public List<GameLevel> getSubLevels() { return subLevels; } - public void setSubLevels(List<BaseLevel> subLevels) { + public void setSubLevels(List<GameLevel> subLevels) { this.subLevels = subLevels; } } diff --git a/src/main/java/com/example/demo/dto/BaseLevelDto.java b/src/main/java/com/example/demo/dto/BaseLevelDto.java index b00c134c..d53d125c 100644 --- a/src/main/java/com/example/demo/dto/BaseLevelDto.java +++ b/src/main/java/com/example/demo/dto/BaseLevelDto.java @@ -1,5 +1,7 @@ package com.example.demo.dto; +import com.example.demo.dto.input.LevelType; + import java.io.Serializable; public abstract class BaseLevelDto implements Serializable { @@ -9,6 +11,7 @@ public abstract class BaseLevelDto implements Serializable { private Integer order; private String estimatedDuration; private Long maxScore; + private LevelType type; public Long getId() { return id; @@ -50,6 +53,14 @@ public abstract class BaseLevelDto implements Serializable { this.maxScore = maxScore; } + public LevelType getType() { + return type; + } + + public void setType(LevelType type) { + this.type = type; + } + @Override public String toString() { return "BaseLevelDto{" + "id=" + id + ", title='" + title + '\'' + ", order=" + order + diff --git a/src/main/java/com/example/demo/dto/TrainingDefinitionDto.java b/src/main/java/com/example/demo/dto/TrainingDefinitionDto.java index 8db7e68b..b2b16036 100644 --- a/src/main/java/com/example/demo/dto/TrainingDefinitionDto.java +++ b/src/main/java/com/example/demo/dto/TrainingDefinitionDto.java @@ -1,8 +1,11 @@ package com.example.demo.dto; +import com.example.demo.dto.input.GameDefinitionCreateDto; + import java.io.Serializable; import java.time.LocalDateTime; import java.util.Arrays; +import java.util.List; public class TrainingDefinitionDto implements Serializable { @@ -17,6 +20,8 @@ public class TrainingDefinitionDto implements Serializable { private byte[] outcomes; private byte[] prerequisites; + private List<GameDefinitionCreateDto> levels; + public Long getId() { return id; } @@ -97,6 +102,14 @@ public class TrainingDefinitionDto implements Serializable { this.prerequisites = prerequisites; } + public List<GameDefinitionCreateDto> getLevels() { + return levels; + } + + public void setLevels(List<GameDefinitionCreateDto> levels) { + this.levels = levels; + } + @Override public String toString() { return "TrainingDefinitionDto{" + "id=" + id + ", title='" + title + '\'' + ", lastEdited=" + lastEdited + diff --git a/src/main/java/com/example/demo/dto/UnityLevelDto.java b/src/main/java/com/example/demo/dto/UnityLevelDto.java index be0ac4af..aec241f7 100644 --- a/src/main/java/com/example/demo/dto/UnityLevelDto.java +++ b/src/main/java/com/example/demo/dto/UnityLevelDto.java @@ -4,7 +4,7 @@ import java.util.List; public class UnityLevelDto extends BaseLevelDto { - // TODO any class extending BaseLevel could be used here - this piece of art is here in order to make mapstruct happy + // TODO any class extending BaseLevel probable should be used here - this piece of art is here in order to make mapstruct happy private List<GameLevelDto> subLevels; public List<GameLevelDto> getSubLevels() { diff --git a/src/main/java/com/example/demo/dto/input/GameDefinitionCreateDto.java b/src/main/java/com/example/demo/dto/input/GameDefinitionCreateDto.java index c19d1608..5beacd53 100644 --- a/src/main/java/com/example/demo/dto/input/GameDefinitionCreateDto.java +++ b/src/main/java/com/example/demo/dto/input/GameDefinitionCreateDto.java @@ -1,5 +1,8 @@ package com.example.demo.dto.input; +import com.example.demo.dto.AttachmentDto; +import com.example.demo.dto.HintDto; + import java.util.List; public class GameDefinitionCreateDto { @@ -7,6 +10,24 @@ public class GameDefinitionCreateDto { private String title; private Integer order; private LevelType type; + + // assessment level fields + private String assessmentType; + + // game level fields + private String content; + private boolean solutionPenalized; + private String flag; + private String solution; + private Long incorrectFlagLimit; + + private List<AttachmentDto> attachments; + private List<HintDto> hints; + + // info level fields + // currently none special + + // unity level fields private List<? extends GameDefinitionCreateDto> subLevels; public Long getId() { @@ -41,6 +62,70 @@ public class GameDefinitionCreateDto { this.type = type; } + public String getAssessmentType() { + return assessmentType; + } + + public void setAssessmentType(String assessmentType) { + this.assessmentType = assessmentType; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public boolean isSolutionPenalized() { + return solutionPenalized; + } + + public void setSolutionPenalized(boolean solutionPenalized) { + this.solutionPenalized = solutionPenalized; + } + + public String getFlag() { + return flag; + } + + public void setFlag(String flag) { + this.flag = flag; + } + + public String getSolution() { + return solution; + } + + public void setSolution(String solution) { + this.solution = solution; + } + + public Long getIncorrectFlagLimit() { + return incorrectFlagLimit; + } + + public void setIncorrectFlagLimit(Long incorrectFlagLimit) { + this.incorrectFlagLimit = incorrectFlagLimit; + } + + public List<AttachmentDto> getAttachments() { + return attachments; + } + + public void setAttachments(List<AttachmentDto> attachments) { + this.attachments = attachments; + } + + public List<HintDto> getHints() { + return hints; + } + + public void setHints(List<HintDto> hints) { + this.hints = hints; + } + public List<? extends GameDefinitionCreateDto> getSubLevels() { return subLevels; } diff --git a/src/main/java/com/example/demo/mapper/BeanMapper.java b/src/main/java/com/example/demo/mapper/BeanMapper.java index 3707c0d0..ecc34bf7 100644 --- a/src/main/java/com/example/demo/mapper/BeanMapper.java +++ b/src/main/java/com/example/demo/mapper/BeanMapper.java @@ -5,6 +5,7 @@ import com.example.demo.domain.Attachment; import com.example.demo.domain.GameLevel; import com.example.demo.domain.Hint; import com.example.demo.domain.InfoLevel; +import com.example.demo.domain.TrainingDefinition; import com.example.demo.domain.UnityLevel; import com.example.demo.dto.AssessmentLevelDto; import com.example.demo.dto.AttachmentDto; @@ -15,8 +16,11 @@ import com.example.demo.dto.HintDto; import com.example.demo.dto.InfoLevelCreateDto; import com.example.demo.dto.InfoLevelDto; import com.example.demo.dto.InfoLevelUpdateDto; +import com.example.demo.dto.TrainingDefinitionDto; import com.example.demo.dto.UnityLevelDto; +import com.example.demo.dto.input.GameDefinitionCreateDto; import org.mapstruct.Mapper; +import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; @@ -27,22 +31,29 @@ public interface BeanMapper { AssessmentLevelDto toDto(AssessmentLevel assessmentLevel); + @Mapping(target = "orderInTrainingDefinition", source = "order") AssessmentLevel toEntity(AssessmentLevelDto assessmentLevel); GameLevelDto toDto(GameLevel gameLevel); + @Mapping(target = "orderInTrainingDefinition", source = "order") GameLevel toEntity(GameLevelDto gameLevel); + @Mapping(target = "orderInTrainingDefinition", source = "order") GameLevel toEntity(GameLevelCreateDto gameLevel); + @Mapping(target = "orderInTrainingDefinition", source = "order") GameLevel toEntity(GameLevelUpdateDto gameLevel); InfoLevelDto toDto(InfoLevel infoLevel); + @Mapping(target = "orderInTrainingDefinition", source = "order") InfoLevel toEntity(InfoLevelDto infoLevel); + @Mapping(target = "orderInTrainingDefinition", source = "order") InfoLevel toEntity(InfoLevelCreateDto gameLevel); + @Mapping(target = "orderInTrainingDefinition", source = "order") InfoLevel toEntity(InfoLevelUpdateDto gameLevel); HintDto toDto(Hint hint); @@ -55,5 +66,23 @@ public interface BeanMapper { UnityLevelDto toDto(UnityLevel unityLevel); + @Mapping(target = "orderInTrainingDefinition", source = "order") UnityLevel toEntity(UnityLevelDto unityLevel); + + @Mapping(target = "orderInTrainingDefinition", source = "order") + AssessmentLevel toAssessmentLevel(GameDefinitionCreateDto gameDefinitionCreateDto); + + @Mapping(target = "orderInTrainingDefinition", source = "order") + InfoLevel toInfoLevel(GameDefinitionCreateDto gameDefinitionCreateDto); + + @Mapping(target = "orderInTrainingDefinition", source = "order") + GameLevel toGameLevel(GameDefinitionCreateDto gameDefinitionCreateDto); + + @Mapping(target = "orderInTrainingDefinition", source = "order") + UnityLevel toUnityLevel(GameDefinitionCreateDto gameDefinitionCreateDto); + + @Mapping(target = "levels", ignore = true) + TrainingDefinition toEntity(TrainingDefinitionDto trainingDefinition); + + TrainingDefinitionDto toDto(TrainingDefinition trainingDefinition); } diff --git a/src/main/java/com/example/demo/repository/TrainingDefinitionRepository.java b/src/main/java/com/example/demo/repository/TrainingDefinitionRepository.java new file mode 100644 index 00000000..19236c16 --- /dev/null +++ b/src/main/java/com/example/demo/repository/TrainingDefinitionRepository.java @@ -0,0 +1,7 @@ +package com.example.demo.repository; + +import com.example.demo.domain.TrainingDefinition; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface TrainingDefinitionRepository extends JpaRepository<TrainingDefinition, Long> { +} diff --git a/src/main/java/com/example/demo/service/GameDefinitionService.java b/src/main/java/com/example/demo/service/GameDefinitionService.java index 5dc2624f..1cc5fd61 100644 --- a/src/main/java/com/example/demo/service/GameDefinitionService.java +++ b/src/main/java/com/example/demo/service/GameDefinitionService.java @@ -3,14 +3,21 @@ package com.example.demo.service; import com.example.demo.domain.AssessmentLevel; import com.example.demo.domain.BaseLevel; import com.example.demo.domain.GameLevel; +import com.example.demo.domain.InfoLevel; +import com.example.demo.domain.TrainingDefinition; import com.example.demo.domain.UnityLevel; +import com.example.demo.dto.TrainingDefinitionDto; import com.example.demo.dto.input.GameDefinitionCreateDto; import com.example.demo.dto.input.LevelType; +import com.example.demo.mapper.BeanMapper; import com.example.demo.repository.AssessmentLevelRepository; import com.example.demo.repository.GameLevelRepository; +import com.example.demo.repository.InfoLevelRepository; +import com.example.demo.repository.TrainingDefinitionRepository; import com.example.demo.repository.UnityLevelRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; import java.util.ArrayList; import java.util.List; @@ -27,37 +34,43 @@ public class GameDefinitionService { @Autowired private GameLevelRepository gameLevelRepository; - public GameDefinitionCreateDto createGameDefinition(List<GameDefinitionCreateDto> gameDefinition) { + @Autowired + private InfoLevelRepository infoLevelRepository; - for (GameDefinitionCreateDto gameDefinitionCreateDto : gameDefinition) { - if (gameDefinitionCreateDto.getType() == LevelType.assessment) { - AssessmentLevel assessmentLevel = new AssessmentLevel(); - assessmentLevel.setTitle(gameDefinitionCreateDto.getTitle()); - assessmentLevel.setOrderInTrainingDefinition(gameDefinitionCreateDto.getOrder()); + @Autowired + private TrainingDefinitionRepository trainingDefinitionRepository; - assessmentLevelRepository.save(assessmentLevel); - } else if (gameDefinitionCreateDto.getType() == LevelType.unity) { - UnityLevel unityLevel = new UnityLevel(); - unityLevel.setTitle(gameDefinitionCreateDto.getTitle()); - unityLevel.setOrderInTrainingDefinition(gameDefinitionCreateDto.getOrder()); + public GameDefinitionCreateDto createGameDefinition(TrainingDefinitionDto trainingDefinitionDto) { - unityLevelRepository.save(unityLevel); + TrainingDefinition trainingDefinition = BeanMapper.INSTANCE.toEntity(trainingDefinitionDto); + trainingDefinitionRepository.save(trainingDefinition); - List<BaseLevel> subLevels = new ArrayList<>(); - for (GameDefinitionCreateDto subLevel : gameDefinitionCreateDto.getSubLevels()) { - if (subLevel.getType() == LevelType.game) { - GameLevel gameLevel = new GameLevel(); - gameLevel.setTitle(subLevel.getTitle()); - gameLevel.setOrderInTrainingDefinition(subLevel.getOrder()); - gameLevel.setUnityLevel(unityLevel); + // TODO refactor this, it's really ugly + for (GameDefinitionCreateDto gameDefinitionCreateDto : trainingDefinitionDto.getLevels()) { + if (gameDefinitionCreateDto.getType() == LevelType.assessment) { + AssessmentLevel assessmentLevel = BeanMapper.INSTANCE.toAssessmentLevel(gameDefinitionCreateDto); + assessmentLevel.setTrainingDefinition(trainingDefinition); + assessmentLevelRepository.save(assessmentLevel); + } else if (gameDefinitionCreateDto.getType() == LevelType.unity) { + UnityLevel unityLevel = BeanMapper.INSTANCE.toUnityLevel(gameDefinitionCreateDto); + unityLevel.setTrainingDefinition(trainingDefinition); - subLevels.add(gameLevel); - gameLevelRepository.save(gameLevel); - } + if (!CollectionUtils.isEmpty(unityLevel.getSubLevels())) { + unityLevel.getSubLevels().forEach(x -> x.setUnityLevel(unityLevel)); + unityLevel.getSubLevels().forEach(x -> x.setTrainingDefinition(trainingDefinition)); } - unityLevel.setSubLevels(subLevels); + unityLevelRepository.save(unityLevel); + } else if (gameDefinitionCreateDto.getType() == LevelType.game) { + GameLevel gameLevel = BeanMapper.INSTANCE.toGameLevel(gameDefinitionCreateDto); + gameLevel.setTrainingDefinition(trainingDefinition); + gameLevelRepository.save(gameLevel); + + } else if (gameDefinitionCreateDto.getType() == LevelType.info) { + InfoLevel infoLevel = BeanMapper.INSTANCE.toInfoLevel(gameDefinitionCreateDto); + infoLevel.setTrainingDefinition(trainingDefinition); + infoLevelRepository.save(infoLevel); } } -- GitLab