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

feat: codelists endpoints #343

Open
wants to merge 41 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
8186af5
chore(model): create codeList model
laurentC35 Feb 20, 2025
67b09b8
chore(model): create utils function to convert model
laurentC35 Feb 20, 2025
44712ff
feat: create new Service to manage codeLists
laurentC35 Feb 20, 2025
caa406b
feat: create CodesList controller
laurentC35 Feb 20, 2025
1db67d3
ref: update controller numbering
laurentC35 Feb 20, 2025
b398abf
test: handle new feature (codesList)
laurentC35 Feb 20, 2025
a2c161f
bump: 4.12.0-SNAPSHOT
laurentC35 Feb 20, 2025
cab9cbc
fix: add empty parent to code
laurentC35 Feb 20, 2025
822d04e
bump: 4.12.0-SNAPSHOT.1
laurentC35 Feb 20, 2025
da58832
ref: rename to CodesListService
laurentC35 Feb 20, 2025
5ea6e27
ref: improve method with stream
laurentC35 Feb 20, 2025
049423d
ref: simplify impl
laurentC35 Feb 20, 2025
2848a2f
wip: create VariableService
laurentC35 Feb 20, 2025
4135c28
ref: remove cast to QuestionType
laurentC35 Feb 21, 2025
855524f
ref: move PoguesModelUtils
laurentC35 Feb 21, 2025
ced4e84
ref: move utils function to CodeList class
laurentC35 Feb 21, 2025
ee74e87
ref: create utils class according to Poges-Model
laurentC35 Feb 21, 2025
ce4faa8
ref: simplify variableService
laurentC35 Feb 21, 2025
b5f8fdc
ref: remove VariableService
laurentC35 Feb 21, 2025
678e3a7
fix: variableName generation
laurentC35 Feb 21, 2025
0ea1ace
test: perform new tests
laurentC35 Feb 21, 2025
158bfed
bump; 4.12.0-SNAPSHOT.2
laurentC35 Feb 21, 2025
7f15bc8
ref: split codes
laurentC35 Feb 25, 2025
c163028
test: add test for heart method
laurentC35 Feb 25, 2025
9f66a54
bump: 4.12.0-SNAPSHOT.3
laurentC35 Feb 25, 2025
eb3ab7a
ref: simplify variables generation
laurentC35 Feb 25, 2025
a14574e
fix: mapping with response collected variables Id
laurentC35 Feb 25, 2025
4d673d4
test: check variable factory
laurentC35 Feb 25, 2025
e7acd31
fix: update table condition
laurentC35 Feb 25, 2025
a62e57b
feat: remove clarification Question for question with updatedCodeList
laurentC35 Feb 25, 2025
704fda2
bump: 4.12.0-SNAPSHOT.4
laurentC35 Feb 25, 2025
2ee1efa
fix: naming convention (keep only allow char for variable name)
laurentC35 Feb 26, 2025
7d691bf
fix: getNeededCollectedVariablesInQuestionnaire method (add arbitrary…
laurentC35 Feb 26, 2025
5f8b1a7
bump: 4.12.0-SNAPSHOT.5
laurentC35 Feb 26, 2025
5ce4ed9
fix: name of MultipleChoice variables
laurentC35 Feb 27, 2025
cef2818
ref: Exception to handle CodeList custom message
laurentC35 Feb 27, 2025
540e2f3
test: fix test with exception
laurentC35 Feb 27, 2025
132ac5f
chore: add content type
laurentC35 Feb 27, 2025
2e70108
bump: 4.12.0-SNAPSHOT.6
laurentC35 Feb 27, 2025
461da5e
feat: return list of updatedQuestion
laurentC35 Feb 27, 2025
4c36dcd
Merge branch 'main' into feat/codelists-endpoints
laurentC35 Mar 12, 2025
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
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<groupId>fr.insee</groupId>
<artifactId>Pogues-BO</artifactId>
<packaging>jar</packaging>
<version>4.11.2</version>
<version>4.12.0-SNAPSHOT.6</version>
<name>Pogues-Back-Office</name>

<properties>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package fr.insee.pogues.api.remote.eno.transforms;

import fr.insee.pogues.exception.EnoException;
import fr.insee.pogues.webservice.rest.PoguesException;
import fr.insee.pogues.exception.PoguesException;

import java.io.IOException;
import java.net.URISyntaxException;
Expand All @@ -19,14 +19,14 @@ public interface EnoClient {

String getDDIToODT (String inputAsString) throws EnoException, PoguesException;

String getDDIToFO(String inputAsString) throws URISyntaxException, IOException, EnoException;
String getDDIToFO(String inputAsString) throws URISyntaxException, IOException, EnoException, PoguesException;

String getDDIToXForms(String inputAsString) throws URISyntaxException, IOException, EnoException;
String getDDIToXForms(String inputAsString) throws URISyntaxException, IOException, EnoException, PoguesException;

/** @deprecated Use Pogues to Lunatic method instead. */
@Deprecated(since = "4.9.2")
String getDDIToLunaticJSON(String inputAsString, Map<String, Object> params) throws URISyntaxException, IOException, EnoException;
String getDDIToLunaticJSON(String inputAsString, Map<String, Object> params) throws URISyntaxException, IOException, EnoException, PoguesException;

String getPoguesJsonToLunaticJson(String inputAsString, Map<String, Object> params) throws URISyntaxException, IOException, EnoException;
String getPoguesJsonToLunaticJson(String inputAsString, Map<String, Object> params) throws URISyntaxException, IOException, EnoException, PoguesException;

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import fr.insee.pogues.exception.EnoException;
import fr.insee.pogues.webservice.model.EnoContext;
import fr.insee.pogues.webservice.rest.PoguesException;
import fr.insee.pogues.exception.PoguesException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
Expand Down Expand Up @@ -96,7 +96,7 @@ public String getDDIToLunaticJSON(String inputAsString, Map<String, Object> para
}

@Override
public String getPoguesJsonToLunaticJson(String inputAsString, Map<String, Object> params) throws IOException, EnoException {
public String getPoguesJsonToLunaticJson(String inputAsString, Map<String, Object> params) throws EnoException, PoguesException {
log.info("getJSONPoguesToLunaticJson - started");

EnoContext context = getContextParam(params);
Expand Down
24 changes: 24 additions & 0 deletions src/main/java/fr/insee/pogues/exception/CodesListException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package fr.insee.pogues.exception;

import fr.insee.pogues.webservice.error.ApiMessage;
import fr.insee.pogues.webservice.error.CodesListMessage;
import lombok.Getter;

import java.util.List;

@Getter
public class CodesListException extends PoguesException {

private List<String> questionIds;

public CodesListException(int status, String message, String details, List<String> questionIds) {
super(status, message, details);
this.questionIds = questionIds;
}

@Override
public ApiMessage toApiMessage(){
return new CodesListMessage(this.getStatus(), this.getMessage(),this.getDetails(), questionIds);
}

}
19 changes: 19 additions & 0 deletions src/main/java/fr/insee/pogues/exception/GenericException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package fr.insee.pogues.exception;

import fr.insee.pogues.webservice.error.ApiMessage;
import lombok.Getter;

@Getter
public abstract class GenericException extends Exception {

private String details;

public GenericException(String message, String details){
super(message);
this.details = details;
}

public ApiMessage toApiMessage() {
return new ApiMessage(500, this.getMessage(), details);
}
}
28 changes: 28 additions & 0 deletions src/main/java/fr/insee/pogues/exception/PoguesException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package fr.insee.pogues.exception;

import fr.insee.pogues.webservice.error.ApiMessage;
import lombok.Getter;

@Getter
public class PoguesException extends GenericException {

private int status;
private String details;

/**
*
* @param status
* @param message
* @param details
*/
public PoguesException(int status, String message, String details) {
super(message, details);
this.status = status;
this.details = details;
}

@Override
public ApiMessage toApiMessage(){
return new ApiMessage(this.status, this.getMessage(), this.details);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package fr.insee.pogues.metadata.client;

import fr.insee.pogues.metadata.model.ddias.Unit;
import fr.insee.pogues.webservice.rest.PoguesException;
import fr.insee.pogues.exception.PoguesException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import fr.insee.pogues.metadata.model.magma.Operation;
import fr.insee.pogues.metadata.model.magma.Serie;
import fr.insee.pogues.webservice.rest.PoguesException;
import fr.insee.pogues.exception.PoguesException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import fr.insee.pogues.configuration.auth.security.restrictions.StampsRestrictionsService;
import fr.insee.pogues.configuration.cache.CacheName;
import fr.insee.pogues.persistence.repository.QuestionnaireRepository;
import fr.insee.pogues.webservice.rest.PoguesException;
import fr.insee.pogues.exception.PoguesException;
import lombok.extern.slf4j.Slf4j;
import org.postgresql.util.PGobject;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@

import fr.insee.pogues.domain.entity.db.Version;
import fr.insee.pogues.persistence.repository.QuestionnaireVersionRepository;
import fr.insee.pogues.webservice.rest.PoguesException;
import fr.insee.pogues.exception.PoguesException;
import lombok.extern.slf4j.Slf4j;
import org.postgresql.util.PGobject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
import fr.insee.pogues.transforms.visualize.composition.QuestionnaireComposition;
import fr.insee.pogues.utils.PoguesDeserializer;
import fr.insee.pogues.utils.PoguesSerializer;
import fr.insee.pogues.utils.json.JSONFunctions;
import fr.insee.pogues.webservice.rest.PoguesException;
import fr.insee.pogues.exception.PoguesException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
Expand Down
164 changes: 164 additions & 0 deletions src/main/java/fr/insee/pogues/service/CodesListService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
package fr.insee.pogues.service;

import fr.insee.pogues.exception.CodesListException;
import fr.insee.pogues.model.*;
import fr.insee.pogues.persistence.service.QuestionnairesService;
import fr.insee.pogues.utils.PoguesDeserializer;
import fr.insee.pogues.utils.PoguesSerializer;
import fr.insee.pogues.webservice.model.dtd.codeList.CodesList;
import fr.insee.pogues.exception.PoguesException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import java.util.function.Predicate;

import static fr.insee.pogues.utils.CodesListConverter.*;
import static fr.insee.pogues.utils.json.JSONFunctions.jsonStringtoJsonNode;
import static fr.insee.pogues.utils.model.CodesList.getListOfQuestionIdWhereCodesListIsUsed;
import static fr.insee.pogues.utils.model.CodesList.getListOfQuestionWhereCodesListIsUsed;
import static fr.insee.pogues.utils.model.Variables.getNeededCollectedVariablesInQuestionnaire;
import static fr.insee.pogues.utils.model.question.Common.removeClarificationQuestion;
import static fr.insee.pogues.utils.model.question.MultipleChoice.updateMultipleChoiceQuestionAccordingToCodeList;
import static fr.insee.pogues.utils.model.question.Table.updateTableQuestionAccordingToCodeList;

@Service
@Slf4j
public class CodesListService {
private QuestionnairesService questionnairesService;

@Autowired

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Plus besoin du @Autowired comme tu utilises déjà l'injection par constructeur. tu eux remove

Suggested change
@Autowired

public CodesListService(QuestionnairesService questionnairesService){
this.questionnairesService = questionnairesService;
}

/**
*
* @param questionnaireId
* @param idCodesList
* @param codesList
* @return the list of question's id updated (or null if created)
* @throws Exception
*/
public List<String> updateOrAddCodeListToQuestionnaire(String questionnaireId, String idCodesList, CodesList codesList) throws Exception {
Questionnaire questionnaire = retrieveQuestionnaireWithId(questionnaireId);
List<String> updatedQuestionIds = updateOrAddCodeListToQuestionnaire(questionnaire, idCodesList, codesList);
updateQuestionnaireInDataBase(questionnaire);
return updatedQuestionIds;
}
/**
*
* @param questionnaire
* @param idCodesList
* @param codesList
* @return the list of question's id updated (or null if created)
* @throws Exception
*/
public List<String> updateOrAddCodeListToQuestionnaire(Questionnaire questionnaire, String idCodesList, CodesList codesList) {
List<fr.insee.pogues.model.CodeList> codesLists = questionnaire.getCodeLists().getCodeList();
boolean created = updateOrAddCodeListDTD(codesLists, idCodesList, codesList);
if(!created) return updateQuestionAndVariablesAccordingToCodesList(questionnaire, idCodesList);
return null;
}

public void deleteCodeListOfQuestionnaireWithId(String questionnaireId, String codesListId) throws Exception {
Questionnaire questionnaire = retrieveQuestionnaireWithId(questionnaireId);
deleteCodeListOfQuestionnaire(questionnaire, codesListId);
updateQuestionnaireInDataBase(questionnaire);
}

public void deleteCodeListOfQuestionnaire(Questionnaire questionnaire, String codesListId) throws Exception {
List<String> questionIds = getListOfQuestionIdWhereCodesListIsUsed(questionnaire, codesListId);
if(!questionIds.isEmpty()){
throw new CodesListException(400, String.format("CodesList with id %s is required.", codesListId), "", questionIds);

}
List<fr.insee.pogues.model.CodeList> codesLists = questionnaire.getCodeLists().getCodeList();
removeCodeListDTD(codesLists, codesListId);
}

private Questionnaire retrieveQuestionnaireWithId(String id) throws Exception {
return PoguesDeserializer.questionnaireToJavaObject(questionnairesService.getQuestionnaireByID(id));
}

private void updateQuestionnaireInDataBase(Questionnaire questionnaire) throws Exception {
questionnairesService.updateQuestionnaire(
questionnaire.getId(),
jsonStringtoJsonNode(PoguesSerializer.questionnaireJavaToString(questionnaire)));
}

/**
*
* @param existingCodeLists
* @param idCodesList
* @param codesListDtdToUpdate
* @return true if new codeList is created
*/
boolean updateOrAddCodeListDTD(List<CodeList> existingCodeLists, String idCodesList, CodesList codesListDtdToUpdate) {
if(existingCodeLists.stream().noneMatch(codeList -> Objects.equals(idCodesList, codeList.getId()))){
addCodeListDTD(existingCodeLists, codesListDtdToUpdate);
return true;
}
codesListDtdToUpdate.setId(idCodesList);
replaceElementInListAccordingCondition(
existingCodeLists,
codeList -> Objects.equals(idCodesList, codeList.getId()),
codesListDtdToUpdate,
codesList -> convertFromCodeListDTDtoCodeListModel(codesListDtdToUpdate));
return false;
}


void addCodeListDTD(List<CodeList> existingCodeLists, CodesList codesListDtdToAdd){
existingCodeLists.add(convertFromCodeListDTDtoCodeListModel(codesListDtdToAdd));
}

void removeCodeListDTD(List<CodeList> existingCodeLists, String id) throws CodesListException {
boolean deleted = existingCodeLists.removeIf(codeList -> id.equals(codeList.getId()));
if(!deleted) throw new CodesListException(404, "Not found", String.format("CodesList with id %s doesn't exist in questionnaire", id),null);
}

List<String> updateQuestionAndVariablesAccordingToCodesList(Questionnaire questionnaire, String updatedCodeListId){
// Retrieve updatedCodeList in questionnaire
CodeList codeList = questionnaire.getCodeLists().getCodeList().stream().filter(cL -> updatedCodeListId.equals(cL.getId())).findFirst().get();
// Just retrieve MULTIPLE_CHOICE and TABLE questions
List<QuestionType> questionsToModify = getListOfQuestionWhereCodesListIsUsed(questionnaire, updatedCodeListId);
// Clear Clarification question for concerned question
questionsToModify.forEach(question -> removeClarificationQuestion(question));
// modify Multiple and Table question and get there new Variables
List<QuestionType> multipleAndTableQuestion = questionsToModify.stream()
.filter(questionType -> {
QuestionTypeEnum questionTypeEnum = questionType.getQuestionType();
return QuestionTypeEnum.MULTIPLE_CHOICE.equals(questionTypeEnum) || QuestionTypeEnum.TABLE.equals(questionTypeEnum);})
.toList();
List<VariableType> variables = multipleAndTableQuestion.stream()
.map(questionType -> {
QuestionTypeEnum questionTypeEnum = questionType.getQuestionType();
if(QuestionTypeEnum.MULTIPLE_CHOICE.equals(questionTypeEnum)) return updateMultipleChoiceQuestionAccordingToCodeList(questionType, codeList);
return updateTableQuestionAccordingToCodeList(questionType, codeList, questionnaire.getCodeLists().getCodeList());
})
.flatMap(Collection::stream)
.toList();
// add new variables to questionnaire
questionnaire.getVariables().getVariable().addAll(variables);
// Delete variables that are not referenced in response
List<String> neededCollectedVariables = getNeededCollectedVariablesInQuestionnaire(questionnaire);
questionnaire.getVariables().getVariable().removeIf(variableType -> !neededCollectedVariables.contains(variableType.getId()));
return questionsToModify.stream().map(question -> question.getId()).toList();
}

private <T,G> void replaceElementInListAccordingCondition(List<T> elements, Predicate<T> conditionFunction, G newElement, Function<G,T> factory){
for (int i = 0; i < elements.size(); i++) {
T element = elements.get(i);
if (conditionFunction.test(element)) {
elements.set(i, factory.apply(newElement));
break;
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import java.util.List;

import static fr.insee.pogues.utils.PoguesModelUtils.getSequences;
import static fr.insee.pogues.utils.model.PoguesModelUtils.getSequences;

/**
* Implementation of CompositionStep to replace questionnaire reference by its sequences.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@

import java.util.List;

import static fr.insee.pogues.utils.PoguesModelUtils.getFlowControlBounds;
import static fr.insee.pogues.utils.PoguesModelUtils.getSequences;
import static fr.insee.pogues.utils.model.PoguesModelUtils.getFlowControlBounds;
import static fr.insee.pogues.utils.model.PoguesModelUtils.getSequences;

/**
* Implementation of CompositionStep to update FlowControl (filters) objects when de-referencing a questionnaire.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@

import java.util.List;

import static fr.insee.pogues.utils.PoguesModelUtils.getIterationBounds;
import static fr.insee.pogues.utils.PoguesModelUtils.getSequences;
import static fr.insee.pogues.utils.model.PoguesModelUtils.getIterationBounds;
import static fr.insee.pogues.utils.model.PoguesModelUtils.getSequences;

/**
* Implementation of CompositionStep to update Iteration (loops) objects when de-referencing a questionnaire.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
import fr.insee.pogues.model.IterationType;
import fr.insee.pogues.model.Questionnaire;
import fr.insee.pogues.model.VariableType;
import fr.insee.pogues.utils.PoguesModelUtils;
import fr.insee.pogues.utils.model.PoguesModelUtils;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

import static fr.insee.pogues.utils.PoguesModelUtils.getIterationBounds;
import static fr.insee.pogues.utils.model.PoguesModelUtils.getIterationBounds;

/**
* Implementation of CompositionStep to update variable scopes when de-referencing a questionnaire.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import com.fasterxml.jackson.databind.JsonNode;
import fr.insee.pogues.persistence.service.QuestionnairesService;
import fr.insee.pogues.utils.suggester.SuggesterVisuService;
import fr.insee.pogues.webservice.rest.PoguesException;
import fr.insee.pogues.exception.PoguesException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
Expand Down
Loading