Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Development: Add simple repository service #9871

Closed
wants to merge 20 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
2907c17
Add abstract simple repository service
ole-ve Nov 26, 2024
3195bd6
Move default methods from CompetencyRepository to CompetencySimpleRep…
ole-ve Nov 26, 2024
7d4693e
Add JavaDoc for AbstractSimpleRepositoryService
ole-ve Nov 26, 2024
755c449
Rename AbstractSimpleRepositoryService to AbstractSimpleRepository
ole-ve Nov 26, 2024
b2e8134
Move default methods from CourseCompetencyRepository to CourseCompete…
ole-ve Nov 26, 2024
479c405
Annotate SimpleRepository with profile
ole-ve Nov 26, 2024
1c62cdb
Fix missing autowiring
ole-ve Nov 26, 2024
98a226e
Adjust AbstractModuleServiceArchitectureTest to allow simple reposito…
ole-ve Nov 26, 2024
1e1b3c9
Rename SimpleRepository to SimpleService and use generics
ole-ve Nov 28, 2024
4f6db42
Move atlas SimpleServices to subpackage
ole-ve Nov 28, 2024
3a1cd24
Adapt service arch tests to consider SimpleServices
ole-ve Nov 28, 2024
b80b453
Add arch test to enforce that repositories have no default methods
ole-ve Nov 28, 2024
b22daac
Disable enforceNoDefaultMethodsInRepository for now
ole-ve Nov 28, 2024
61f0e05
Add arch test to enforce single autowired candidate
ole-ve Nov 28, 2024
ca07539
Merge branch 'develop' into chore/add-simple-repository-service
ole-ve Nov 28, 2024
4da414e
fix field naming of SimpleService
ole-ve Dec 17, 2024
bbadbe6
use abstract getEntityName in AbstractSimpleService
ole-ve Dec 17, 2024
d31c49a
fmt
ole-ve Dec 17, 2024
4f050e0
change AbstractSimpleService from abstract class to interface
ole-ve Dec 17, 2024
902a7ed
change test for ensuring single autowire in SimpleServices to allow f…
ole-ve Dec 17, 2024
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
Expand Up @@ -56,14 +56,6 @@ public interface CompetencyRepository extends ArtemisJpaRepository<Competency, L
""")
Optional<Competency> findByIdWithLectureUnitsAndExercises(@Param("competencyId") long competencyId);

default Competency findByIdWithLectureUnitsAndExercisesElseThrow(long competencyId) {
return getValueElseThrow(findByIdWithLectureUnitsAndExercises(competencyId), competencyId);
}

default Competency findByIdWithLectureUnitsElseThrow(long competencyId) {
return getValueElseThrow(findByIdWithLectureUnits(competencyId), competencyId);
}

long countByCourse(Course course);

List<Competency> findByCourseIdOrderById(long courseId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import de.tum.cit.aet.artemis.atlas.domain.LearningObject;
import de.tum.cit.aet.artemis.atlas.domain.competency.CourseCompetency;
import de.tum.cit.aet.artemis.atlas.dto.metrics.CompetencyExerciseMasteryCalculationDTO;
import de.tum.cit.aet.artemis.atlas.dto.metrics.CompetencyLectureUnitMasteryCalculationDTO;
Expand Down Expand Up @@ -80,10 +79,6 @@ public interface CourseCompetencyRepository extends ArtemisJpaRepository<CourseC
""")
Optional<CourseCompetency> findByIdWithExercisesAndLectureUnitsAndLectures(@Param("id") long id);

default CourseCompetency findByIdWithExercisesAndLectureUnitsAndLecturesElseThrow(long id) {
return getValueElseThrow(findByIdWithExercisesAndLectureUnitsAndLectures(id), id);
}

@Query("""
SELECT c
FROM CourseCompetency c
Expand Down Expand Up @@ -259,40 +254,6 @@ Page<CourseCompetency> findForImportAndUserHasAccessToCourse(@Param("partialTitl
""")
Optional<CourseCompetency> findByIdWithLectureUnitsAndExercises(@Param("competencyId") long competencyId);

default CourseCompetency findByIdWithLectureUnitsElseThrow(long competencyId) {
return getValueElseThrow(findByIdWithLectureUnits(competencyId), competencyId);
}

default CourseCompetency findByIdWithExercisesAndLectureUnitsElseThrow(long competencyId) {
return getValueElseThrow(findByIdWithExercisesAndLectureUnits(competencyId), competencyId);
}

default CourseCompetency findByIdWithExercisesAndLectureUnitsBidirectionalElseThrow(long competencyId) {
return getValueElseThrow(findByIdWithExercisesAndLectureUnitsBidirectional(competencyId), competencyId);
}

/**
* Finds the set of ids of course competencies that are linked to a given learning object
*
* @param learningObject the learning object to find the course competencies for
* @return the set of ids of course competencies linked to the learning object
*/
default Set<Long> findAllIdsByLearningObject(LearningObject learningObject) {
return switch (learningObject) {
case LectureUnit lectureUnit -> findAllIdsByLectureUnit(lectureUnit);
case Exercise exercise -> findAllIdsByExercise(exercise);
default -> throw new IllegalArgumentException("Unknown LearningObject type: " + learningObject.getClass());
};
}

default CourseCompetency findByIdWithExercisesElseThrow(long competencyId) {
return getValueElseThrow(findByIdWithExercises(competencyId), competencyId);
}

default CourseCompetency findByIdWithLectureUnitsAndExercisesElseThrow(long competencyId) {
return getValueElseThrow(findByIdWithLectureUnitsAndExercises(competencyId), competencyId);
}

List<CourseCompetency> findByCourseIdOrderById(long courseId);

boolean existsByIdAndCourseId(long competencyId, long courseId);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package de.tum.cit.aet.artemis.atlas.repository.simple;

import static de.tum.cit.aet.artemis.core.config.Constants.PROFILE_CORE;

import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;

import de.tum.cit.aet.artemis.atlas.domain.competency.Competency;
import de.tum.cit.aet.artemis.atlas.repository.CompetencyRepository;
import de.tum.cit.aet.artemis.core.repository.base.ISimpleService;

@Profile(PROFILE_CORE)
@Service
public class CompetencySimpleService implements ISimpleService<Competency> {

private final CompetencyRepository competencyRepository;

@Override
public String getEntityName() {
return "Competency";
}

public CompetencySimpleService(CompetencyRepository competencyRepository) {
this.competencyRepository = competencyRepository;
}

public Competency findByIdWithLectureUnitsAndExercisesElseThrow(long competencyId) {
return getValueElseThrow(competencyRepository.findByIdWithLectureUnitsAndExercises(competencyId));
}

public Competency findByIdWithLectureUnitsElseThrow(long competencyId) {
return getValueElseThrow(competencyRepository.findByIdWithLectureUnitsAndExercises(competencyId));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package de.tum.cit.aet.artemis.atlas.repository.simple;

import static de.tum.cit.aet.artemis.core.config.Constants.PROFILE_CORE;

import java.util.Set;

import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;

import de.tum.cit.aet.artemis.atlas.domain.LearningObject;
import de.tum.cit.aet.artemis.atlas.domain.competency.CourseCompetency;
import de.tum.cit.aet.artemis.atlas.repository.CourseCompetencyRepository;
import de.tum.cit.aet.artemis.core.repository.base.ISimpleService;
import de.tum.cit.aet.artemis.exercise.domain.Exercise;
import de.tum.cit.aet.artemis.lecture.domain.LectureUnit;

@Profile(PROFILE_CORE)
@Service
public class CourseCompetencySimpleService implements ISimpleService<CourseCompetency> {

private final CourseCompetencyRepository courseCompetencyRepository;

@Override
public String getEntityName() {
return "CourseCompetency";
}

public CourseCompetencySimpleService(CourseCompetencyRepository courseCompetencyRepository) {
this.courseCompetencyRepository = courseCompetencyRepository;
}

public CourseCompetency findByIdWithExercisesAndLectureUnitsAndLecturesElseThrow(long id) {
return getValueElseThrow(courseCompetencyRepository.findByIdWithExercisesAndLectureUnitsAndLectures(id));
}

public CourseCompetency findByIdWithExercisesAndLectureUnitsElseThrow(long competencyId) {
return getValueElseThrow(courseCompetencyRepository.findByIdWithExercisesAndLectureUnits(competencyId));
}

public CourseCompetency findByIdWithExercisesAndLectureUnitsBidirectionalElseThrow(long competencyId) {
return getValueElseThrow(courseCompetencyRepository.findByIdWithExercisesAndLectureUnitsBidirectional(competencyId));
}

/**
* Finds the set of ids of course competencies that are linked to a given learning object
*
* @param learningObject the learning object to find the course competencies for
* @return the set of ids of course competencies linked to the learning object
*/
public Set<Long> findAllIdsByLearningObject(LearningObject learningObject) {
return switch (learningObject) {
case LectureUnit lectureUnit -> courseCompetencyRepository.findAllIdsByLectureUnit(lectureUnit);
case Exercise exercise -> courseCompetencyRepository.findAllIdsByExercise(exercise);
default -> throw new IllegalArgumentException("Unknown LearningObject type: " + learningObject.getClass());
};
}
ole-ve marked this conversation as resolved.
Show resolved Hide resolved

public CourseCompetency findByIdWithExercisesElseThrow(long competencyId) {
return getValueElseThrow(courseCompetencyRepository.findByIdWithExercises(competencyId));
}

public CourseCompetency findByIdWithLectureUnitsAndExercisesElseThrow(long competencyId) {
return getValueElseThrow(courseCompetencyRepository.findByIdWithLectureUnitsAndExercises(competencyId));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import de.tum.cit.aet.artemis.atlas.dto.metrics.CompetencyLectureUnitMasteryCalculationDTO;
import de.tum.cit.aet.artemis.atlas.repository.CompetencyProgressRepository;
import de.tum.cit.aet.artemis.atlas.repository.CourseCompetencyRepository;
import de.tum.cit.aet.artemis.atlas.repository.simple.CourseCompetencySimpleService;
import de.tum.cit.aet.artemis.atlas.service.learningpath.LearningPathService;
import de.tum.cit.aet.artemis.core.domain.Course;
import de.tum.cit.aet.artemis.core.domain.User;
Expand Down Expand Up @@ -62,6 +63,8 @@ public class CompetencyProgressService {

private final CourseCompetencyRepository courseCompetencyRepository;

private final CourseCompetencySimpleService courseCompetencySimpleService;

private static final int MIN_EXERCISES_RECENCY_CONFIDENCE = 3;

private static final int MAX_SUBMISSIONS_FOR_QUICK_SOLVE_HEURISTIC = 3;
Expand All @@ -75,13 +78,14 @@ public class CompetencyProgressService {
private static final double CONFIDENCE_REASON_DEADZONE = 0.05;

public CompetencyProgressService(CompetencyProgressRepository competencyProgressRepository, LearningPathService learningPathService,
ParticipantScoreService participantScoreService, LectureUnitCompletionRepository lectureUnitCompletionRepository,
CourseCompetencyRepository courseCompetencyRepository) {
ParticipantScoreService participantScoreService, LectureUnitCompletionRepository lectureUnitCompletionRepository, CourseCompetencyRepository courseCompetencyRepository,
CourseCompetencySimpleService courseCompetencySimpleService) {
this.competencyProgressRepository = competencyProgressRepository;
this.learningPathService = learningPathService;
this.participantScoreService = participantScoreService;
this.lectureUnitCompletionRepository = lectureUnitCompletionRepository;
this.courseCompetencyRepository = courseCompetencyRepository;
this.courseCompetencySimpleService = courseCompetencySimpleService;
}

/**
Expand All @@ -104,7 +108,7 @@ public void updateProgressByLearningObjectForParticipantAsync(LearningObject lea
@Async
public void updateProgressByLearningObjectAsync(LearningObject learningObject) {
SecurityUtils.setAuthorizationObject(); // Required for async
Set<Long> competencyIds = courseCompetencyRepository.findAllIdsByLearningObject(learningObject);
Set<Long> competencyIds = courseCompetencySimpleService.findAllIdsByLearningObject(learningObject);

for (long competencyId : competencyIds) {
Set<User> users = competencyProgressRepository.findAllByCompetencyId(competencyId).stream().map(CompetencyProgress::getUser).collect(Collectors.toSet());
Expand Down Expand Up @@ -183,7 +187,7 @@ private void updateProgressByCompetencyIdsAndLearningObject(Set<Long> competency
* @param users The users for which to update the progress
*/
public void updateProgressByLearningObjectSync(LearningObject learningObject, Set<User> users) {
Set<Long> competencyIds = courseCompetencyRepository.findAllIdsByLearningObject(learningObject);
Set<Long> competencyIds = courseCompetencySimpleService.findAllIdsByLearningObject(learningObject);

for (long competencyId : competencyIds) {
log.debug("Updating competency progress synchronously for {} users.", users.size());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import de.tum.cit.aet.artemis.atlas.repository.CompetencyRepository;
import de.tum.cit.aet.artemis.atlas.repository.CourseCompetencyRepository;
import de.tum.cit.aet.artemis.atlas.repository.StandardizedCompetencyRepository;
import de.tum.cit.aet.artemis.atlas.repository.simple.CompetencySimpleService;
import de.tum.cit.aet.artemis.atlas.repository.simple.CourseCompetencySimpleService;
import de.tum.cit.aet.artemis.atlas.service.LearningObjectImportService;
import de.tum.cit.aet.artemis.atlas.service.learningpath.LearningPathService;
import de.tum.cit.aet.artemis.core.domain.Course;
Expand All @@ -42,17 +44,21 @@ public class CompetencyService extends CourseCompetencyService {

private final CompetencyRepository competencyRepository;

private final CompetencySimpleService competencySimpleService;

private final CompetencyExerciseLinkRepository competencyExerciseLinkRepository;

public CompetencyService(CompetencyRepository competencyRepository, AuthorizationCheckService authCheckService, CompetencyRelationRepository competencyRelationRepository,
LearningPathService learningPathService, CompetencyProgressService competencyProgressService, LectureUnitService lectureUnitService,
CompetencyProgressRepository competencyProgressRepository, LectureUnitCompletionRepository lectureUnitCompletionRepository,
CourseCompetencySimpleService courseCompetencySimpleService, LearningPathService learningPathService, CompetencyProgressService competencyProgressService,
LectureUnitService lectureUnitService, CompetencyProgressRepository competencyProgressRepository, LectureUnitCompletionRepository lectureUnitCompletionRepository,
StandardizedCompetencyRepository standardizedCompetencyRepository, CourseCompetencyRepository courseCompetencyRepository, ExerciseService exerciseService,
LearningObjectImportService learningObjectImportService, CompetencyLectureUnitLinkRepository competencyLectureUnitLinkRepository, CourseRepository courseRepository,
CompetencyExerciseLinkRepository competencyExerciseLinkRepository) {
super(competencyProgressRepository, courseCompetencyRepository, competencyRelationRepository, competencyProgressService, exerciseService, lectureUnitService,
learningPathService, authCheckService, standardizedCompetencyRepository, lectureUnitCompletionRepository, learningObjectImportService, courseRepository);
CompetencySimpleService competencySimpleService, CompetencyExerciseLinkRepository competencyExerciseLinkRepository) {
super(competencyProgressRepository, courseCompetencyRepository, courseCompetencySimpleService, competencyRelationRepository, competencyProgressService, exerciseService,
lectureUnitService, learningPathService, authCheckService, standardizedCompetencyRepository, lectureUnitCompletionRepository, learningObjectImportService,
courseRepository);
this.competencyRepository = competencyRepository;
this.competencySimpleService = competencySimpleService;
this.competencyExerciseLinkRepository = competencyExerciseLinkRepository;
}

Expand Down Expand Up @@ -100,7 +106,7 @@ public List<Competency> createCompetencies(List<Competency> competencies, Course
* @return The found competency
*/
public Competency findCompetencyWithExercisesAndLectureUnitsAndProgressForUser(Long competencyId, Long userId) {
Competency competency = competencyRepository.findByIdWithLectureUnitsAndExercisesElseThrow(competencyId);
Competency competency = competencySimpleService.findByIdWithLectureUnitsAndExercisesElseThrow(competencyId);
return findProgressAndLectureUnitCompletionsForUser(competency, userId);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import de.tum.cit.aet.artemis.atlas.repository.CompetencyRelationRepository;
import de.tum.cit.aet.artemis.atlas.repository.CourseCompetencyRepository;
import de.tum.cit.aet.artemis.atlas.repository.StandardizedCompetencyRepository;
import de.tum.cit.aet.artemis.atlas.repository.simple.CourseCompetencySimpleService;
import de.tum.cit.aet.artemis.atlas.service.LearningObjectImportService;
import de.tum.cit.aet.artemis.atlas.service.learningpath.LearningPathService;
import de.tum.cit.aet.artemis.core.domain.Course;
Expand Down Expand Up @@ -64,6 +65,8 @@ public class CourseCompetencyService {

protected final CourseCompetencyRepository courseCompetencyRepository;

private final CourseCompetencySimpleService courseCompetencySimpleService;

protected final CompetencyRelationRepository competencyRelationRepository;

protected final CompetencyProgressService competencyProgressService;
Expand All @@ -85,12 +88,13 @@ public class CourseCompetencyService {
private final CourseRepository courseRepository;

public CourseCompetencyService(CompetencyProgressRepository competencyProgressRepository, CourseCompetencyRepository courseCompetencyRepository,
CompetencyRelationRepository competencyRelationRepository, CompetencyProgressService competencyProgressService, ExerciseService exerciseService,
LectureUnitService lectureUnitService, LearningPathService learningPathService, AuthorizationCheckService authCheckService,
StandardizedCompetencyRepository standardizedCompetencyRepository, LectureUnitCompletionRepository lectureUnitCompletionRepository,
LearningObjectImportService learningObjectImportService, CourseRepository courseRepository) {
CourseCompetencySimpleService courseCompetencySimpleService, CompetencyRelationRepository competencyRelationRepository,
CompetencyProgressService competencyProgressService, ExerciseService exerciseService, LectureUnitService lectureUnitService, LearningPathService learningPathService,
AuthorizationCheckService authCheckService, StandardizedCompetencyRepository standardizedCompetencyRepository,
LectureUnitCompletionRepository lectureUnitCompletionRepository, LearningObjectImportService learningObjectImportService, CourseRepository courseRepository) {
this.competencyProgressRepository = competencyProgressRepository;
this.courseCompetencyRepository = courseCompetencyRepository;
this.courseCompetencySimpleService = courseCompetencySimpleService;
this.competencyRelationRepository = competencyRelationRepository;
this.competencyProgressService = competencyProgressService;
this.exerciseService = exerciseService;
Expand All @@ -113,7 +117,7 @@ public CourseCompetencyService(CompetencyProgressRepository competencyProgressRe
* @return The found competency
*/
public CourseCompetency findCompetencyWithExercisesAndLectureUnitsAndProgressForUser(Long competencyId, Long userId) {
CourseCompetency competency = courseCompetencyRepository.findByIdWithLectureUnitsAndExercisesElseThrow(competencyId);
CourseCompetency competency = courseCompetencySimpleService.findByIdWithLectureUnitsAndExercisesElseThrow(competencyId);
return findProgressAndLectureUnitCompletionsForUser(competency, userId);
}

Expand Down
Loading
Loading