ProgramProgressServiceImpl.java
package fr.avenirsesr.portfolio.api.domain.service;
import fr.avenirsesr.portfolio.api.domain.model.ProgramProgress;
import fr.avenirsesr.portfolio.api.domain.model.Skill;
import fr.avenirsesr.portfolio.api.domain.model.SkillLevel;
import fr.avenirsesr.portfolio.api.domain.model.SortCriteria;
import fr.avenirsesr.portfolio.api.domain.model.Student;
import fr.avenirsesr.portfolio.api.domain.model.enums.ESkillLevelStatus;
import fr.avenirsesr.portfolio.api.domain.model.enums.ESortField;
import fr.avenirsesr.portfolio.api.domain.model.enums.ESortOrder;
import fr.avenirsesr.portfolio.api.domain.port.input.ProgramProgressService;
import fr.avenirsesr.portfolio.api.domain.port.output.repository.ProgramProgressRepository;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Slf4j
@AllArgsConstructor
@Service
public class ProgramProgressServiceImpl implements ProgramProgressService {
private static final int MAX_SKILLS = 6;
private final ProgramProgressRepository programProgressRepository;
private static SkillLevel findCurrentOrNextSkillLevel(Set<SkillLevel> skillLevels) {
if (skillLevels == null || skillLevels.isEmpty()) {
return null;
}
return skillLevels.stream()
.filter(
sl ->
(sl.getStatus() == ESkillLevelStatus.UNDER_REVIEW
|| sl.getStatus() == ESkillLevelStatus.UNDER_ACQUISITION)
&& (sl.getEndDate() == null || sl.getEndDate().isAfter(LocalDate.now())))
.findFirst()
.orElseGet(
() ->
skillLevels.stream()
.filter(
sl ->
sl.getStatus() == ESkillLevelStatus.TO_BE_EVALUATED
|| sl.getStatus() == ESkillLevelStatus.NOT_STARTED)
.findFirst()
.orElse(null));
}
private static Map<ProgramProgress, Set<Skill>> cleanProgramProgressList(
List<ProgramProgress> programProgressList, boolean needToLimitSkills) {
final int skillLimit =
!programProgressList.isEmpty() ? MAX_SKILLS / programProgressList.size() : 0;
return programProgressList.stream()
.collect(
Collectors.toMap(
programProgress -> programProgress,
programProgress ->
programProgress.getSkills().stream()
.sorted(Comparator.comparing(Skill::getName))
.limit(needToLimitSkills ? skillLimit : programProgress.getSkills().size())
.map(
skill -> {
SkillLevel selectedSkillLevel =
findCurrentOrNextSkillLevel(skill.getSkillLevels());
Set<SkillLevel> selectedSkillLevelSet =
selectedSkillLevel != null
? Set.of(selectedSkillLevel)
: Set.of();
if (selectedSkillLevelSet.isEmpty()) {
return null;
}
return Skill.toDomain(
skill.getId(), skill.getName(), selectedSkillLevelSet);
})
.filter(Objects::nonNull)
.collect(Collectors.toCollection(LinkedHashSet::new)),
(existing, replacement) -> existing,
LinkedHashMap::new));
}
@Override
public Map<ProgramProgress, Set<Skill>> getSkillsOverview(Student student) {
SortCriteria sortCriteria = new SortCriteria(ESortField.NAME, ESortOrder.ASC);
return cleanProgramProgressList(
programProgressRepository.findAllByStudent(student, sortCriteria), true);
}
@Override
public boolean isStudentFollowingAPCProgram(Student student) {
var programProgress = programProgressRepository.findAllAPCByStudent(student);
return !programProgress.isEmpty();
}
@Override
public Map<ProgramProgress, Set<Skill>> getSkillsView(
Student student, SortCriteria sortCriteria) {
if (sortCriteria == null) {
sortCriteria = new SortCriteria(ESortField.NAME, ESortOrder.ASC);
}
return cleanProgramProgressList(
programProgressRepository.findAllByStudent(student, sortCriteria), false);
}
@Override
public List<ProgramProgress> getAllProgramProgress(Student student) {
return programProgressRepository.findAllWithoutSkillsByStudent(student).stream()
.sorted(Comparator.comparing(p -> p.getProgram().getName()))
.collect(Collectors.toList());
}
}