AdditionalSkillCacheImpl.java
package fr.avenirsesr.portfolio.additionalskill.infrastructure.adapter.cache;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import fr.avenirsesr.portfolio.additionalskill.domain.exception.AdditionalSkillNotFoundException;
import fr.avenirsesr.portfolio.additionalskill.domain.model.AdditionalSkill;
import fr.avenirsesr.portfolio.additionalskill.domain.port.output.AdditionalSkillCache;
import fr.avenirsesr.portfolio.additionalskill.infrastructure.adapter.mapper.AdditionalSkillMapper;
import fr.avenirsesr.portfolio.additionalskill.infrastructure.adapter.model.CompetenceComplementaireDetaillee;
import fr.avenirsesr.portfolio.shared.domain.model.PageCriteria;
import fr.avenirsesr.portfolio.shared.domain.model.PageInfo;
import fr.avenirsesr.portfolio.shared.domain.model.PagedResult;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class AdditionalSkillCacheImpl implements AdditionalSkillCache {
private final String jsonPath;
private final ObjectMapper objectMapper;
public AdditionalSkillCacheImpl(
@Value("${mock.additional-skills.path:/mock/mock-additional-skills.json}") String jsonPath) {
this.jsonPath = jsonPath;
this.objectMapper = new ObjectMapper();
}
private static <T> PagedResult<T> paginate(List<T> data, PageCriteria pageCriteria) {
int totalElements = data.size();
int page = pageCriteria.page();
int start = Math.min(page * pageCriteria.pageSize(), totalElements);
int end = Math.min(start + pageCriteria.pageSize(), totalElements);
List<T> paginatedSkills = data.subList(start, end);
return new PagedResult<>(
paginatedSkills, new PageInfo(pageCriteria.page(), pageCriteria.pageSize(), data.size()));
}
@Override
public PagedResult<AdditionalSkill> findAll(PageCriteria pageCriteria) {
List<AdditionalSkill> additionalSkills =
loadAdditionalSkills().stream().map(AdditionalSkillMapper::toDomain).toList();
return paginate(additionalSkills, pageCriteria);
}
@Override
public PagedResult<AdditionalSkill> findBySkillTitle(String keyword, PageCriteria pageCriteria) {
String normalizedKeyword = keyword == null ? "" : keyword.trim().toLowerCase();
List<AdditionalSkill> filteredSkills = loadAdditionalSkillsByLibelle(normalizedKeyword);
return paginate(filteredSkills, pageCriteria);
}
private List<CompetenceComplementaireDetaillee> loadAdditionalSkills() {
try (InputStream is = getClass().getResourceAsStream(jsonPath)) {
return objectMapper.readValue(is, new TypeReference<>() {});
} catch (Exception e) {
throw new RuntimeException("Unable to load mock additional skills", e);
}
}
private List<AdditionalSkill> loadAdditionalSkillsByLibelle(String keyword) {
return loadAdditionalSkills().stream()
.filter(skill -> skill.libelle().toLowerCase().contains(keyword.toLowerCase()))
.map(AdditionalSkillMapper::toDomain)
.toList();
}
@Override
public AdditionalSkill findById(UUID id) {
return loadAdditionalSkills().stream()
.filter(skill -> skill.id().equals(id))
.map(AdditionalSkillMapper::toDomain)
.findFirst()
.orElseThrow(AdditionalSkillNotFoundException::new);
}
@Override
public List<AdditionalSkill> findAllByIds(List<UUID> ids) {
return loadAdditionalSkills().stream()
.filter(skill -> ids.contains(skill.id()))
.map(AdditionalSkillMapper::toDomain)
.toList();
}
}