From 103a3e39814617c751dbd24f502b821c76945b22 Mon Sep 17 00:00:00 2001 From: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com> Date: Wed, 17 Jul 2024 16:52:36 +0200 Subject: [PATCH] feat: constraint instances (#101) * feat: constraint instances * feat: constraint signatures * WIP * feat: constraint instances * feat: constraint signatures * WIP * Pushing this because I need the code on another device * Added a method to the SpecificationBuilder class (It has yet to be tested) Removed useless test class * Fixed the constraint arguments filter * Refactored SpecificationBuilder * Removed test code from controller * Fixed the create method of the constraint instance service Adjusted and added other tests Added an annotation to suppress warnings in SpecificationBuilder * Update server/src/main/java/de/uftos/services/ConstraintInstanceService.java Co-authored-by: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com> * Fixed typo Changed method name Converted a String[] to List * Fixed import * Renamed method Javadoc * Suppressing tests javadoc --------- Co-authored-by: Marco --- .../controller/ConstraintController.java | 10 +- .../de/uftos/entities/ConstraintArgument.java | 14 +- .../de/uftos/entities/ConstraintInstance.java | 2 +- .../uftos/entities/ConstraintParameter.java | 7 + .../uftos/entities/ConstraintSignature.java | 4 +- .../ConstraintInstanceRepository.java | 7 +- .../ConstraintSignatureRepository.java | 3 +- .../services/ConstraintInstanceService.java | 131 +++++++++++++- .../services/ConstraintSignatureService.java | 7 +- .../de/uftos/utils/SpecificationBuilder.java | 58 +++++- .../ConstraintInstanceServiceTest.java | 170 ++++++++++++++++++ .../uftos/services/TeacherServiceTests.java | 1 + 12 files changed, 399 insertions(+), 15 deletions(-) create mode 100644 server/src/test/java/de/uftos/services/ConstraintInstanceServiceTest.java diff --git a/server/src/main/java/de/uftos/controller/ConstraintController.java b/server/src/main/java/de/uftos/controller/ConstraintController.java index 17f96eb1c..f11b484d4 100644 --- a/server/src/main/java/de/uftos/controller/ConstraintController.java +++ b/server/src/main/java/de/uftos/controller/ConstraintController.java @@ -3,6 +3,8 @@ import de.uftos.dto.ConstraintInstanceRequestDto; import de.uftos.entities.ConstraintInstance; import de.uftos.entities.ConstraintSignature; +import de.uftos.repositories.database.ConstraintInstanceRepository; +import de.uftos.repositories.database.ConstraintSignatureRepository; import de.uftos.services.ConstraintInstanceService; import de.uftos.services.ConstraintSignatureService; import java.util.Optional; @@ -26,6 +28,8 @@ public class ConstraintController { private final ConstraintSignatureService constraintSignatureService; private final ConstraintInstanceService constraintInstanceService; + private final ConstraintInstanceRepository constraintInstanceRepository; + private final ConstraintSignatureRepository constraintSignatureRepository; /** * Creates the constraint controller. @@ -35,9 +39,13 @@ public class ConstraintController { */ @Autowired public ConstraintController(ConstraintSignatureService constraintSignatureService, - ConstraintInstanceService constraintInstanceService) { + ConstraintInstanceService constraintInstanceService, + ConstraintInstanceRepository constraintInstanceRepository, + ConstraintSignatureRepository constraintSignatureRepository) { this.constraintSignatureService = constraintSignatureService; this.constraintInstanceService = constraintInstanceService; + this.constraintInstanceRepository = constraintInstanceRepository; + this.constraintSignatureRepository = constraintSignatureRepository; } /** diff --git a/server/src/main/java/de/uftos/entities/ConstraintArgument.java b/server/src/main/java/de/uftos/entities/ConstraintArgument.java index 33dae7c6f..47fb0d299 100644 --- a/server/src/main/java/de/uftos/entities/ConstraintArgument.java +++ b/server/src/main/java/de/uftos/entities/ConstraintArgument.java @@ -1,11 +1,15 @@ package de.uftos.entities; +import jakarta.persistence.CascadeType; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; import java.util.Objects; import lombok.Data; +import lombok.NoArgsConstructor; /** * The database table for constraint arguments. @@ -14,14 +18,22 @@ */ @Entity(name = "constraint_argument") @Data +@NoArgsConstructor public class ConstraintArgument { @Id @GeneratedValue(strategy = GenerationType.UUID) private String id; - private String name; + @ManyToOne(cascade = CascadeType.ALL) + @JoinColumn(name = "constraint_parameter_id", nullable = false) + private ConstraintParameter constraintParameter; private String value; + + public ConstraintArgument(String name, String value) { + this.value = value; + } + @Override public boolean equals(Object other) { if (this == other) { diff --git a/server/src/main/java/de/uftos/entities/ConstraintInstance.java b/server/src/main/java/de/uftos/entities/ConstraintInstance.java index ac1a67ba1..494644c20 100644 --- a/server/src/main/java/de/uftos/entities/ConstraintInstance.java +++ b/server/src/main/java/de/uftos/entities/ConstraintInstance.java @@ -32,7 +32,7 @@ public class ConstraintInstance { private ConstraintSignature signature; @NotNull - @OneToMany(cascade = CascadeType.REMOVE) + @OneToMany(cascade = CascadeType.ALL) private List arguments; @NotNull diff --git a/server/src/main/java/de/uftos/entities/ConstraintParameter.java b/server/src/main/java/de/uftos/entities/ConstraintParameter.java index 2c5cbee4c..58c70c501 100644 --- a/server/src/main/java/de/uftos/entities/ConstraintParameter.java +++ b/server/src/main/java/de/uftos/entities/ConstraintParameter.java @@ -1,5 +1,6 @@ package de.uftos.entities; +import com.fasterxml.jackson.annotation.JsonIgnore; import de.uftos.dto.ResourceType; import jakarta.persistence.Entity; import jakarta.persistence.EnumType; @@ -7,6 +8,8 @@ import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; +import java.util.List; import java.util.Objects; import lombok.Data; @@ -23,6 +26,10 @@ public class ConstraintParameter { private String parameterName; + @JsonIgnore + @OneToMany(mappedBy = "constraintParameter") + private List constraintArguments; + @Enumerated(EnumType.STRING) private ResourceType parameterType; diff --git a/server/src/main/java/de/uftos/entities/ConstraintSignature.java b/server/src/main/java/de/uftos/entities/ConstraintSignature.java index 74bafb335..d299a2755 100644 --- a/server/src/main/java/de/uftos/entities/ConstraintSignature.java +++ b/server/src/main/java/de/uftos/entities/ConstraintSignature.java @@ -30,11 +30,11 @@ public class ConstraintSignature { private RewardPenalize defaultType; @NotNull - @OneToMany + @OneToMany(cascade = CascadeType.ALL) private List parameters; @JsonIgnore - @OneToMany(mappedBy = "signature", cascade = CascadeType.REMOVE) + @OneToMany(mappedBy = "signature", cascade = CascadeType.ALL) private List instances; @Override diff --git a/server/src/main/java/de/uftos/repositories/database/ConstraintInstanceRepository.java b/server/src/main/java/de/uftos/repositories/database/ConstraintInstanceRepository.java index 92a2518f7..56ce34f52 100644 --- a/server/src/main/java/de/uftos/repositories/database/ConstraintInstanceRepository.java +++ b/server/src/main/java/de/uftos/repositories/database/ConstraintInstanceRepository.java @@ -1,6 +1,9 @@ package de.uftos.repositories.database; import de.uftos.entities.ConstraintInstance; +import de.uftos.entities.ConstraintSignature; +import java.util.Optional; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.repository.ListCrudRepository; import org.springframework.data.repository.ListPagingAndSortingRepository; @@ -9,5 +12,7 @@ */ public interface ConstraintInstanceRepository extends ListPagingAndSortingRepository, - ListCrudRepository { + ListCrudRepository, JpaSpecificationExecutor { + + Optional findBySignatureAndId(ConstraintSignature signature, String id); } diff --git a/server/src/main/java/de/uftos/repositories/database/ConstraintSignatureRepository.java b/server/src/main/java/de/uftos/repositories/database/ConstraintSignatureRepository.java index 9f13eef95..5b44ddb73 100644 --- a/server/src/main/java/de/uftos/repositories/database/ConstraintSignatureRepository.java +++ b/server/src/main/java/de/uftos/repositories/database/ConstraintSignatureRepository.java @@ -1,6 +1,7 @@ package de.uftos.repositories.database; import de.uftos.entities.ConstraintSignature; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.repository.ListCrudRepository; import org.springframework.data.repository.ListPagingAndSortingRepository; @@ -9,5 +10,5 @@ */ public interface ConstraintSignatureRepository extends ListPagingAndSortingRepository, - ListCrudRepository { + ListCrudRepository, JpaSpecificationExecutor { } diff --git a/server/src/main/java/de/uftos/services/ConstraintInstanceService.java b/server/src/main/java/de/uftos/services/ConstraintInstanceService.java index 0dbff6820..c69020f2a 100644 --- a/server/src/main/java/de/uftos/services/ConstraintInstanceService.java +++ b/server/src/main/java/de/uftos/services/ConstraintInstanceService.java @@ -1,12 +1,31 @@ package de.uftos.services; import de.uftos.dto.ConstraintInstanceRequestDto; +import de.uftos.dto.ResourceType; +import de.uftos.entities.ConstraintArgument; import de.uftos.entities.ConstraintInstance; +import de.uftos.entities.ConstraintParameter; +import de.uftos.entities.ConstraintSignature; import de.uftos.repositories.database.ConstraintInstanceRepository; +import de.uftos.repositories.database.ConstraintSignatureRepository; +import de.uftos.repositories.database.GradeRepository; +import de.uftos.repositories.database.LessonRepository; +import de.uftos.repositories.database.RoomRepository; +import de.uftos.repositories.database.StudentGroupRepository; +import de.uftos.repositories.database.StudentRepository; +import de.uftos.repositories.database.SubjectRepository; +import de.uftos.repositories.database.TagRepository; +import de.uftos.repositories.database.TeacherRepository; +import de.uftos.repositories.database.TimeslotRepository; +import de.uftos.utils.SpecificationBuilder; +import java.util.AbstractMap; +import java.util.List; +import java.util.Map; import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.domain.Specification; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; import org.springframework.web.server.ResponseStatusException; @@ -17,6 +36,17 @@ @Service public class ConstraintInstanceService { private final ConstraintInstanceRepository repository; + private final ConstraintSignatureRepository signatureRepository; + private final GradeRepository gradeRepository; + private final LessonRepository lessonRepository; + private final RoomRepository roomRepository; + private final StudentRepository studentRepository; + private final StudentGroupRepository studentGroupRepository; + private final SubjectRepository subjectRepository; + private final TagRepository tagRepository; + private final TeacherRepository teacherRepository; + private final TimeslotRepository timeslotRepository; + /** * Creates a constraintInstance service. @@ -24,8 +54,28 @@ public class ConstraintInstanceService { * @param repository the repository for accessing the constraintInstance entity. */ @Autowired - public ConstraintInstanceService(ConstraintInstanceRepository repository) { + public ConstraintInstanceService(ConstraintInstanceRepository repository, + ConstraintSignatureRepository signatureRepository, + GradeRepository gradeRepository, + LessonRepository lessonRepository, + RoomRepository roomRepository, + StudentRepository studentRepository, + StudentGroupRepository studentGroupRepository, + SubjectRepository subjectRepository, + TagRepository tagRepository, + TeacherRepository teacherRepository, + TimeslotRepository timeslotRepository) { this.repository = repository; + this.signatureRepository = signatureRepository; + this.gradeRepository = gradeRepository; + this.lessonRepository = lessonRepository; + this.roomRepository = roomRepository; + this.studentRepository = studentRepository; + this.studentGroupRepository = studentGroupRepository; + this.subjectRepository = subjectRepository; + this.tagRepository = tagRepository; + this.teacherRepository = teacherRepository; + this.timeslotRepository = timeslotRepository; } /** @@ -36,7 +86,36 @@ public ConstraintInstanceService(ConstraintInstanceRepository repository) { * @return the newly created constraint instance. */ public ConstraintInstance create(String signatureId, ConstraintInstanceRequestDto request) { - return null; + ConstraintSignature signature = this.signatureRepository.findById(signatureId) + .orElseThrow(() -> new ResponseStatusException(HttpStatus.BAD_REQUEST)); + + if (signature.getParameters().size() != request.arguments().size()) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST); + } + + for (ConstraintParameter parameter : signature.getParameters()) { + String value = request.arguments().get(parameter.getParameterName()); + if (value == null || value.isEmpty()) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, + "Parameter %s could not be found".formatted(parameter.getParameterName())); + } + + boolean exists = this.getResourceTypeMapping(value).get(parameter.getParameterType()); + if (!exists) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, + "%s with id %s could not be found".formatted(parameter.getParameterName(), + parameter.getId())); + } + } + + ConstraintInstance instance = new ConstraintInstance(); + List arguments = request.arguments().entrySet().stream() + .map(item -> new ConstraintArgument(item.getKey(), item.getValue())).toList(); + instance.setArguments(arguments); + instance.setSignature(signature); + instance.setType(request.type()); + + return this.repository.save(instance); } /** @@ -48,7 +127,12 @@ public ConstraintInstance create(String signatureId, ConstraintInstanceRequestDt */ public Page get(String signatureId, Pageable pageable, Optional argument) { - return this.repository.findAll(pageable); + Specification specification = new SpecificationBuilder() + .andJoinEquals(signatureId, "signature", "name") + .optionalAndJoinLikeIgnoreCase(argument, "arguments", "value") + .build(); + + return this.repository.findAll(specification, pageable); } /** @@ -59,7 +143,10 @@ public Page get(String signatureId, Pageable pageable, * @throws ResponseStatusException if the ID doesn't have a corresponding constraintInstance. */ public ConstraintInstance getById(String signatureId, String id) { - return this.repository.findById(id) + ConstraintSignature signature = this.signatureRepository.findById(signatureId) + .orElseThrow(() -> new ResponseStatusException(HttpStatus.BAD_REQUEST)); + + return this.repository.findBySignatureAndId(signature, id) .orElseThrow(() -> new ResponseStatusException(HttpStatus.BAD_REQUEST)); } @@ -72,7 +159,15 @@ public ConstraintInstance getById(String signatureId, String id) { */ public ConstraintInstance update(String signatureId, String id, ConstraintInstanceRequestDto request) { - return null; + ConstraintInstance instance = this.getById(signatureId, id); + + List arguments = request.arguments().entrySet().stream() + .map(item -> new ConstraintArgument(item.getKey(), item.getValue())).toList(); + + instance.setArguments(arguments); + instance.setType(request.type()); + + return this.repository.save(instance); } /** @@ -82,6 +177,32 @@ public ConstraintInstance update(String signatureId, String id, * @param id the ID of the constraintInstance. */ public void delete(String signatureId, String id) { + ConstraintInstance instance = this.getById(signatureId, id); + + this.repository.delete(instance); + } + + private Map getResourceTypeMapping(String id) { + return Map.ofEntries( + new AbstractMap.SimpleEntry<>(ResourceType.GRADE, + this.gradeRepository.findById(id).isPresent()), + new AbstractMap.SimpleEntry<>(ResourceType.LESSON, + this.lessonRepository.findById(id).isPresent()), + new AbstractMap.SimpleEntry<>(ResourceType.ROOM, + this.roomRepository.findById(id).isPresent()), + new AbstractMap.SimpleEntry<>(ResourceType.STUDENT, + this.studentRepository.findById(id).isPresent()), + new AbstractMap.SimpleEntry<>(ResourceType.STUDENT_GROUP, + this.studentGroupRepository.findById(id).isPresent()), + new AbstractMap.SimpleEntry<>(ResourceType.SUBJECT, + this.subjectRepository.findById(id).isPresent()), + new AbstractMap.SimpleEntry<>(ResourceType.TAG, + this.tagRepository.findById(id).isPresent()), + new AbstractMap.SimpleEntry<>(ResourceType.TEACHER, + this.teacherRepository.findById(id).isPresent()), + new AbstractMap.SimpleEntry<>(ResourceType.TIMESLOT, + this.timeslotRepository.findById(id).isPresent()) + ); } } diff --git a/server/src/main/java/de/uftos/services/ConstraintSignatureService.java b/server/src/main/java/de/uftos/services/ConstraintSignatureService.java index 9e5838e7b..ea9e0121e 100644 --- a/server/src/main/java/de/uftos/services/ConstraintSignatureService.java +++ b/server/src/main/java/de/uftos/services/ConstraintSignatureService.java @@ -6,6 +6,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.domain.Specification; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; import org.springframework.web.server.ResponseStatusException; @@ -35,7 +36,11 @@ public ConstraintSignatureService(ConstraintSignatureRepository repository) { * @return the page of the entries fitting the parameters. */ public Page get(Pageable pageable, Optional name) { - return this.repository.findAll(pageable); + Specification specification = Specification.where( + ((root, query, cb) -> cb.like(cb.lower(root.get("id")), + "%" + name.orElse("").toLowerCase() + "%"))); + + return this.repository.findAll(specification, pageable); } /** diff --git a/server/src/main/java/de/uftos/utils/SpecificationBuilder.java b/server/src/main/java/de/uftos/utils/SpecificationBuilder.java index bf76522f2..70f7ebad0 100644 --- a/server/src/main/java/de/uftos/utils/SpecificationBuilder.java +++ b/server/src/main/java/de/uftos/utils/SpecificationBuilder.java @@ -1,6 +1,9 @@ package de.uftos.utils; -import java.util.List; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.Expression; +import jakarta.persistence.criteria.Predicate; +import java.util.Arrays; import java.util.Optional; import org.springframework.data.jpa.domain.Specification; @@ -9,6 +12,7 @@ * * @param The type of the entity to which the specification applies. */ +@SuppressWarnings("OptionalUsedAsFieldOrParameterType") public class SpecificationBuilder { private Specification specification; @@ -64,8 +68,58 @@ public SpecificationBuilder optionalAndJoinIn(Optional attributeVal } specification = specification.and( (root, query, cb) -> root.join(relationName).get(attributeName) - .in(List.of(attributeValue.get())) + .in(Arrays.stream(attributeValue.get()).toList()) ); return this; } + + /** + * Adds a filter to the specification by joining with another relation if the + * provided attribute value array is present and checking whether the given attribute + * has a similar value to the wanted one. + * + * @param attributeValue The optional attribute value to filter by. + * @param relationName The name of the relation to join. + * @param attributeName The name of the attribute in the joined relation to filter on. + * @return The current instance of {@code SpecificationBuilder} with the join filter + * added if the attribute value is present. + */ + public SpecificationBuilder optionalAndJoinLikeIgnoreCase(Optional attributeValue, + String relationName, + String attributeName) { + if (attributeValue.isEmpty()) { + return this; + } + specification = specification.and( + (root, query, cb) -> likeIgnoreCase(cb, root.join(relationName).get(attributeName), + attributeValue.get()) + ); + return this; + } + + /** + * Adds a filter to the specification by joining with another relation if the + * provided attribute value array is present and checking whether the given attribute + * has the exact same value as the wanted one. + * + * @param attributeValue The optional attribute value to filter by. + * @param relationName The name of the relation to join. + * @param attributeName The name of the attribute in the joined relation to filter on. + * @return The current instance of {@code SpecificationBuilder} with the join filter + * added if the attribute value is present. + */ + public SpecificationBuilder andJoinEquals(String attributeValue, + String relationName, String attributeName) { + if (attributeValue.isEmpty()) { + return this; + } + specification = specification.and( + (root, query, cb) -> cb.equal(root.join(relationName).get(attributeName), attributeValue) + ); + return this; + } + + private Predicate likeIgnoreCase(CriteriaBuilder cb, Expression value, String pattern) { + return cb.like(cb.lower(value), "%" + pattern.toLowerCase() + "%"); + } } diff --git a/server/src/test/java/de/uftos/services/ConstraintInstanceServiceTest.java b/server/src/test/java/de/uftos/services/ConstraintInstanceServiceTest.java new file mode 100644 index 000000000..f05840f51 --- /dev/null +++ b/server/src/test/java/de/uftos/services/ConstraintInstanceServiceTest.java @@ -0,0 +1,170 @@ +package de.uftos.services; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.when; + +import de.uftos.dto.ConstraintInstanceRequestDto; +import de.uftos.dto.ResourceType; +import de.uftos.dto.solver.RewardPenalize; +import de.uftos.entities.ConstraintArgument; +import de.uftos.entities.ConstraintInstance; +import de.uftos.entities.ConstraintParameter; +import de.uftos.entities.ConstraintSignature; +import de.uftos.entities.Teacher; +import de.uftos.repositories.database.ConstraintInstanceRepository; +import de.uftos.repositories.database.ConstraintSignatureRepository; +import de.uftos.repositories.database.GradeRepository; +import de.uftos.repositories.database.LessonRepository; +import de.uftos.repositories.database.RoomRepository; +import de.uftos.repositories.database.StudentGroupRepository; +import de.uftos.repositories.database.StudentRepository; +import de.uftos.repositories.database.SubjectRepository; +import de.uftos.repositories.database.TagRepository; +import de.uftos.repositories.database.TeacherRepository; +import de.uftos.repositories.database.TimeslotRepository; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; +import org.springframework.web.server.ResponseStatusException; + +@SuppressWarnings("checkstyle:MissingJavadocType") +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) +public class ConstraintInstanceServiceTest { + + @Mock + private ConstraintInstanceRepository constraintInstanceRepository; + @Mock + private ConstraintSignatureRepository constraintSignatureRepository; + @Mock + private GradeRepository gradeRepository; + @Mock + private LessonRepository lessonRepository; + @Mock + private RoomRepository roomRepository; + @Mock + private StudentRepository studentRepository; + @Mock + private StudentGroupRepository studentGroupRepository; + @Mock + private SubjectRepository subjectRepository; + @Mock + private TagRepository tagRepository; + @Mock + private TeacherRepository teacherRepository; + @Mock + private TimeslotRepository timeslotRepository; + + @InjectMocks + private ConstraintInstanceService constraintInstanceService; + + @BeforeEach + void setUp() { + ConstraintSignature constraintSignature = new ConstraintSignature(); + constraintSignature.setName("test constraint"); + + ConstraintParameter constraintParameter = new ConstraintParameter(); + constraintParameter.setParameterType(ResourceType.TEACHER); + constraintParameter.setParameterName("teacher123"); + constraintParameter.setId("456"); + + ConstraintArgument constraintArgument = new ConstraintArgument(); + constraintArgument.setId("789"); + constraintArgument.setValue("qwerty"); + constraintArgument.setConstraintParameter(constraintParameter); + + constraintParameter.setConstraintArguments(List.of(constraintArgument)); + + ConstraintInstance constraintInstance = new ConstraintInstance(); + constraintInstance.setId("123"); + constraintInstance.setSignature(constraintSignature); + constraintInstance.setArguments(List.of(constraintArgument)); + + constraintSignature.setInstances(List.of(constraintInstance)); + constraintSignature.setParameters(List.of(constraintParameter)); + + when(constraintInstanceRepository.findById("123")).thenReturn( + Optional.of(constraintInstance)); + when(constraintInstanceRepository.findBySignatureAndId(constraintSignature, "123")).thenReturn( + Optional.of(constraintInstance)); + when(constraintSignatureRepository.findById("test constraint")).thenReturn( + Optional.of(constraintSignature)); + + Teacher teacher = new Teacher("teacherId1"); + + when(teacherRepository.findById("teacherId1")).thenReturn(Optional.of(teacher)); + when(teacherRepository.findById("teacherId2")).thenReturn(Optional.empty()); + when(gradeRepository.findById("teacherId1")).thenReturn(Optional.empty()); + when(gradeRepository.findById("teacherId2")).thenReturn(Optional.empty()); + when(lessonRepository.findById("teacherId1")).thenReturn(Optional.empty()); + when(lessonRepository.findById("teacherId2")).thenReturn(Optional.empty()); + when(studentGroupRepository.findById("teacherId1")).thenReturn(Optional.empty()); + when(studentGroupRepository.findById("teacherId2")).thenReturn(Optional.empty()); + when(subjectRepository.findById("teacherId1")).thenReturn(Optional.empty()); + when(subjectRepository.findById("teacherId2")).thenReturn(Optional.empty()); + when(tagRepository.findById("teacherId1")).thenReturn(Optional.empty()); + when(tagRepository.findById("teacherId2")).thenReturn(Optional.empty()); + when(roomRepository.findById("teacherId1")).thenReturn(Optional.empty()); + when(roomRepository.findById("teacherId2")).thenReturn(Optional.empty()); + when(studentRepository.findById("teacherId1")).thenReturn(Optional.empty()); + when(studentRepository.findById("teacherId2")).thenReturn(Optional.empty()); + when(timeslotRepository.findById("teacherId1")).thenReturn(Optional.empty()); + when(timeslotRepository.findById("teacherId2")).thenReturn(Optional.empty()); + } + + @Test + void constrainInstanceById() { + ConstraintInstance constraintInstance = + constraintInstanceService.getById("test constraint", "123"); + assertNotNull(constraintInstance); + assertEquals("123", constraintInstance.getId()); + assertEquals("test constraint", constraintInstance.getSignature().getName()); + assertFalse(constraintInstance.getArguments().isEmpty()); + } + + @Test + void nonExistentParameter() { + ConstraintInstanceRequestDto constraintInstanceRequestDto = new ConstraintInstanceRequestDto( + Map.of( + "teacher123", "teacherId2" + ), RewardPenalize.HARD_PENALIZE); + + assertThrows(ResponseStatusException.class, + () -> constraintInstanceService.create("test constraint", constraintInstanceRequestDto)); + } + + @Test + void tooManyParameter() { + ConstraintInstanceRequestDto constraintInstanceRequestDto = new ConstraintInstanceRequestDto( + Map.of( + "teacher123", "teacherId1", + "teacher456", "teacherId1" + ), RewardPenalize.HARD_PENALIZE); + + assertThrows(ResponseStatusException.class, + () -> constraintInstanceService.create("test constraint", constraintInstanceRequestDto)); + } + + @Test + void createConstraintInstance() { + ConstraintInstanceRequestDto constraintInstanceRequestDto = new ConstraintInstanceRequestDto( + Map.of( + "teacher123", "teacherId1" + ), RewardPenalize.HARD_PENALIZE); + + assertDoesNotThrow( + () -> constraintInstanceService.create("test constraint", constraintInstanceRequestDto)); + } +} diff --git a/server/src/test/java/de/uftos/services/TeacherServiceTests.java b/server/src/test/java/de/uftos/services/TeacherServiceTests.java index 2c328fbdb..f40bb42d9 100644 --- a/server/src/test/java/de/uftos/services/TeacherServiceTests.java +++ b/server/src/test/java/de/uftos/services/TeacherServiceTests.java @@ -31,6 +31,7 @@ import org.mockito.junit.jupiter.MockitoSettings; import org.mockito.quality.Strictness; +@SuppressWarnings("checkstyle:MissingJavadocType") @ExtendWith(MockitoExtension.class) @MockitoSettings(strictness = Strictness.LENIENT) public class TeacherServiceTests {