Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package de.unistuttgart.bugfinder.code;

import java.util.UUID;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface CodeRepository extends JpaRepository<Code, UUID> {}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package de.unistuttgart.bugfinder.configuration;

import de.unistuttgart.bugfinder.configuration.vm.ConfigurationVM;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -27,13 +27,32 @@ public ConfigurationDTO get(@PathVariable final UUID id) {
return configurationService.find(id);
}

@GetMapping("/configurations/vm/{id}")
public ConfigurationVM getVM(@PathVariable final UUID id) {
log.debug("GET /configurations/{}", id);
return configurationService.getViewModel(id);
}

@ResponseStatus(HttpStatus.CREATED)
@PostMapping("/configurations")
public ConfigurationDTO createConfiguration(@RequestBody final ConfigurationDTO configurationDTO) {
log.debug("POST /configurations with body {}", configurationDTO);
return configurationService.save(configurationDTO);
}

/**
* used by the lecture interface to build a configuration by the view model
*
* @param configurationBuilderCodeDTO
* @return
*/
@ResponseStatus(HttpStatus.CREATED)
@PostMapping("/configurations/build")
public ConfigurationDTO buildConfiguration(@RequestBody final ConfigurationVM configurationBuilderCodeDTO) {
log.debug("POST /configurations/builder with body {}", configurationBuilderCodeDTO);
return configurationService.build(configurationBuilderCodeDTO);
}

@PutMapping("/configurations/{id}")
public ConfigurationDTO updateConfiguration(
@PathVariable final UUID id,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package de.unistuttgart.bugfinder.configuration;

import de.unistuttgart.bugfinder.code.Code;
import de.unistuttgart.bugfinder.code.CodeDTO;
import java.util.List;
import java.util.UUID;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
package de.unistuttgart.bugfinder.configuration;

import static org.springframework.http.HttpStatus.NOT_FOUND;

import de.unistuttgart.bugfinder.code.Code;
import de.unistuttgart.bugfinder.code.CodeDTO;
import de.unistuttgart.bugfinder.code.CodeMapper;
import de.unistuttgart.bugfinder.code.CodeService;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import de.unistuttgart.bugfinder.code.CodeRepository;
import de.unistuttgart.bugfinder.code.word.Word;
import de.unistuttgart.bugfinder.code.word.WordRepository;
import de.unistuttgart.bugfinder.configuration.vm.CodeVM;
import de.unistuttgart.bugfinder.configuration.vm.ConfigurationVM;
import de.unistuttgart.bugfinder.configuration.vm.WordVM;
import de.unistuttgart.bugfinder.solution.Solution;
import de.unistuttgart.bugfinder.solution.SolutionRepository;
import de.unistuttgart.bugfinder.solution.bug.Bug;
import de.unistuttgart.bugfinder.solution.bug.BugRepository;
import java.util.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
Expand All @@ -27,11 +33,24 @@ public class ConfigurationService {
@Autowired
private CodeMapper codeMapper;

@Autowired
private CodeRepository codeRepository;

@Autowired
private SolutionRepository solutionRepository;

@Autowired
private WordRepository wordRepository;

@Autowired
private BugRepository bugRepository;

/**
* Get a configuration by its id.
*
* @param id the id of the configuration
* @throws ResponseStatusException (404) when configuration with its id does not exist
* @return the found configuration
* @throws ResponseStatusException (404) when configuration with its id does not exist
*/
public Configuration getConfiguration(final UUID id) {
return configurationRepository
Expand All @@ -51,9 +70,10 @@ public List<ConfigurationDTO> findAll() {

/**
* Get the configuration by its id as DTO.
*
* @param id the id of the configuration
* @throws ResponseStatusException (404) when configuration with its id does not exist
* @return the found configuration as DTO
* @throws ResponseStatusException (404) when configuration with its id does not exist
*/
public ConfigurationDTO find(final UUID id) {
log.debug("get configuration {}", id);
Expand All @@ -72,6 +92,53 @@ public ConfigurationDTO save(final ConfigurationDTO configurationDTO) {
return configurationMapper.toDTO(configurationRepository.save(configurationMapper.fromDTO(configurationDTO)));
}

public ConfigurationDTO build(final ConfigurationVM configurationVM) {
Set<Code> codesToPersist = new HashSet<>(configurationVM.getCodes().size());
for (CodeVM codeVM : configurationVM.getCodes()) {
List<Word> wordsToPersistToCode = new ArrayList<>(codeVM.getWords().size());
Set<Bug> bugsToPersistToSolution = new HashSet<>();
bugsToPersistToSolution = new HashSet<>();
for (List<WordVM> row : codeVM.getWords()) {
// check if the row only contains blank strings
// the first row will never contain only blank strings since it comes from the lecture interface
if (row.stream().allMatch(wordVM -> wordVM.getCorrectValue().isBlank())) {
continue;
}
// if it is not the first row in the code we add a new line
if (codeVM.getWords().indexOf(row) != 0) {
wordsToPersistToCode.add(wordRepository.save(new Word(null, "\n")));
}
for (WordVM wordVM : row) {
// check if the word is blank
// the first word will never be blank since it comes from the lecture interface
if (wordVM.getCorrectValue().isBlank()) {
continue;
}
// if it is not the first word in the row we add a space
if (row.indexOf(wordVM) != 0) {
wordsToPersistToCode.add(wordRepository.save(new Word(null, " ")));
}
String displayValue = wordVM.getDisplayValue() != null ? wordVM.getDisplayValue() : wordVM.getCorrectValue();
Word word = new Word(null, displayValue);
word = wordRepository.save(word);
wordsToPersistToCode.add(word);
if (wordVM.getErrorType() != null) {
Bug bug = new Bug(word, wordVM.getErrorType(), wordVM.getCorrectValue());
bugsToPersistToSolution.add(bug);
bug = bugRepository.save(bug);
}
}
}
Code code = new Code(null, wordsToPersistToCode);
codesToPersist.add(code);
Solution solution = new Solution(null, bugsToPersistToSolution, code);
code = codeRepository.save(code);
solution = solutionRepository.save(solution);
}
Configuration configuration = new Configuration(null, codesToPersist);
return configurationMapper.toDTO(configurationRepository.save(configuration));
}

/**
* Deletes the configuration with the given ID, if present.
*
Expand Down Expand Up @@ -99,4 +166,51 @@ public List<CodeDTO> getCodes(final UUID id) {
final Configuration configuration = getConfiguration(id);
return codeMapper.toDTO(configuration.getCodes());
}

public ConfigurationVM getViewModel(UUID id) {
log.debug("get configuration view model {}", id);
final Configuration configuration = getConfiguration(id);
final ConfigurationVM configurationVM = new ConfigurationVM(new ArrayList<>());
for (Code code : configuration.getCodes()) {
final CodeVM codeVM = new CodeVM(new ArrayList<>());
final Solution solution = solutionRepository
.findByCodeId(code.getId())
.orElseThrow(() ->
new ResponseStatusException(
HttpStatus.NOT_FOUND,
String.format("Solution with code id %s not found.", code.getId())
)
);

List<WordVM> row = new ArrayList<>();
for (Word word : code.getWords()) {
if (word.getWord().equals(" ")) {
continue;
}
if (word.getWord().equals("\n")) {
codeVM.getWords().add(row);
row = new ArrayList<>();
continue;
}
Optional<Bug> bug = solution
.getBugs()
.stream()
.filter(b -> b.getWord().getId().equals(word.getId()))
.findFirst();
final WordVM wordVM = new WordVM();
if (bug.isPresent()) {
wordVM.setErrorType(bug.get().getErrorType());
wordVM.setCorrectValue(bug.get().getCorrectValue());
wordVM.setDisplayValue(word.getWord());
} else {
wordVM.setCorrectValue(word.getWord());
}
row.add(wordVM);
}
codeVM.getWords().add(row);
configurationVM.getCodes().add(codeVM);
}

return configurationVM;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package de.unistuttgart.bugfinder.configuration.vm;

import java.util.List;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.FieldDefaults;

@Data
@NoArgsConstructor
@AllArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE)
public class CodeVM {

List<List<WordVM>> words;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package de.unistuttgart.bugfinder.configuration.vm;

import java.util.List;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.FieldDefaults;

/**
* describes the view model of the lecture interface and is used to build configurations
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE)
public class ConfigurationVM {

List<CodeVM> codes;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package de.unistuttgart.bugfinder.configuration.vm;

import de.unistuttgart.bugfinder.solution.bug.ErrorType;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.FieldDefaults;
import org.springframework.lang.Nullable;

@Data
@NoArgsConstructor
@AllArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE)
public class WordVM {

String correctValue;

@Nullable
String displayValue;

@Nullable
ErrorType errorType;
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class ConfigurationControllerTest {

private final String API_URL = "/configurations";

@Autowired
private MockMvc mvc;

Expand All @@ -39,7 +41,6 @@ public class ConfigurationControllerTest {
@Autowired
private ConfigurationRepository configurationRepository;

private final String API_URL = "/configurations";
private ObjectMapper objectMapper;
private Configuration initialConfig;
private ConfigurationDTO initialConfigDTO;
Expand Down