diff --git a/src/main/java/fr/insee/genesis/controller/rest/responses/InterrogationController.java b/src/main/java/fr/insee/genesis/controller/rest/responses/InterrogationController.java index a9580988..f99f5788 100644 --- a/src/main/java/fr/insee/genesis/controller/rest/responses/InterrogationController.java +++ b/src/main/java/fr/insee/genesis/controller/rest/responses/InterrogationController.java @@ -28,6 +28,9 @@ public InterrogationController(SurveyUnitApiPort surveyUnitService) { } + /** + * !!!WARNING!!! : A CALL WITH THIS ENDPOINT ON A BIG COLLECTION (> 300k) MAY KILL THE GENESIS-API APP.!!! + */ @Operation(summary = "Retrieve all interrogations for a given questionnaire") @GetMapping(path = "/by-questionnaire") public ResponseEntity> getAllInterrogationIdsByQuestionnaire(@RequestParam("questionnaireId") String questionnaireId) { @@ -36,7 +39,6 @@ public ResponseEntity> getAllInterrogationIdsByQuestionnai } - //========= OPTIMISATIONS PERFS (START) ========== /** * @author Adrien Marchal */ @@ -63,7 +65,6 @@ public ResponseEntity> getPaginatedInterrogationIdsByQuest List responses = surveyUnitService.findDistinctPageableInterrogationIdsByQuestionnaireId(questionnaireId, totalSize, blockSize, page); return ResponseEntity.ok(responses); } - //======== OPTIMISATIONS PERFS (END) =========== } diff --git a/src/main/java/fr/insee/genesis/controller/rest/responses/ModeController.java b/src/main/java/fr/insee/genesis/controller/rest/responses/ModeController.java index d7fef093..54c6c888 100644 --- a/src/main/java/fr/insee/genesis/controller/rest/responses/ModeController.java +++ b/src/main/java/fr/insee/genesis/controller/rest/responses/ModeController.java @@ -40,20 +40,4 @@ public ResponseEntity> getModesByCampaign(@RequestParam("campaignId") return ResponseEntity.ok(modes); } - //========= OPTIMISATIONS PERFS (START) ========== - @Operation(summary = "List sources/modes used for a given questionnaire") - @GetMapping(path = "/by-questionnaireV2") - public ResponseEntity> getModesByQuestionnaireV2(@RequestParam("questionnaireId") String questionnaireId) { - List modes = surveyUnitService.findModesByQuestionnaireIdV2(questionnaireId); - return ResponseEntity.ok(modes); - } - - @Operation(summary = "List sources/modes used for a given campaign") - @GetMapping(path = "/by-campaignV2") - public ResponseEntity> getModesByCampaignV2(@RequestParam("campaignId") String campaignId) { - List modes = surveyUnitService.findModesByCampaignIdV2(campaignId); - return ResponseEntity.ok(modes); - } - //========= OPTIMISATIONS PERFS (END) ========== - } diff --git a/src/main/java/fr/insee/genesis/controller/rest/responses/QuestionnaireController.java b/src/main/java/fr/insee/genesis/controller/rest/responses/QuestionnaireController.java index 68baa76a..36f35888 100644 --- a/src/main/java/fr/insee/genesis/controller/rest/responses/QuestionnaireController.java +++ b/src/main/java/fr/insee/genesis/controller/rest/responses/QuestionnaireController.java @@ -46,24 +46,17 @@ public ResponseEntity> getQuestionnairesWithCamp return ResponseEntity.ok(questionnaireWithCampaignList); } - @Operation(summary = "List questionnaires used for a given campaign") - @GetMapping(path = "/by-campaign") - public ResponseEntity> getQuestionnairesByCampaign(@RequestParam("campaignId") String campaignId) { - Set questionnaires = surveyUnitService.findQuestionnaireIdsByCampaignId(campaignId); - return ResponseEntity.ok(questionnaires); - } - //========= OPTIMISATIONS PERFS (START) ========== /** * @author Adrien Marchal */ @Operation(summary = "List questionnaires used for a given campaign (using a DISTINCT query)") - @GetMapping(path = "/by-campaignV2") - public ResponseEntity> getQuestionnairesByCampaignV2(@RequestParam("campaignId") String campaignId) { - Set questionnaires = surveyUnitService.findQuestionnaireIdsByCampaignIdV2(campaignId); + @GetMapping(path = "/by-campaign") + public ResponseEntity> getQuestionnairesByCampaign(@RequestParam("campaignId") String campaignId) { + Set questionnaires = surveyUnitService.findQuestionnaireIdsByCampaignId(campaignId); return ResponseEntity.ok(questionnaires); } - //========= OPTIMISATIONS PERFS (END) ========== + @Operation(summary = "Get the questionnaireId corresponding to an interrogationId") @GetMapping(path = "/by-interrogation") diff --git a/src/main/java/fr/insee/genesis/controller/rest/responses/ResponseController.java b/src/main/java/fr/insee/genesis/controller/rest/responses/ResponseController.java index 5a490cca..a9347b6f 100644 --- a/src/main/java/fr/insee/genesis/controller/rest/responses/ResponseController.java +++ b/src/main/java/fr/insee/genesis/controller/rest/responses/ResponseController.java @@ -57,11 +57,9 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import java.util.Set; -import java.util.stream.Stream; @RequestMapping(path = "/responses" ) @Controller @@ -274,119 +272,39 @@ public ResponseEntity getLatestByInterrogationOneObject(@R } + /** + * @author Adrien Marchal + */ @Operation(summary = "Retrieve all responses for a questionnaire and a list of UE", description = "Return the latest state for each variable for the given ids and a given questionnaire.
" + "For a given id, the endpoint returns a document by collection mode (if there is more than one).") @PostMapping(path = "/simplified/by-list-interrogation-and-questionnaire/latest") @PreAuthorize("hasRole('USER_KRAFTWERK')") public ResponseEntity> getLatestForInterrogationList(@RequestParam("questionnaireId") String questionnaireId, - @RequestBody List interrogationIds) { - List results = new ArrayList<>(); - List modes = surveyUnitService.findModesByQuestionnaireId(questionnaireId); - interrogationIds.forEach(interrogationId -> { - List responses = surveyUnitService.findLatestByIdAndByQuestionnaireId(interrogationId.getInterrogationId(), questionnaireId); - modes.forEach(mode -> { - List outputVariables = new ArrayList<>(); - List outputExternalVariables = new ArrayList<>(); - responses.stream().filter(rep -> rep.getMode().equals(mode)).forEach(response -> { - outputVariables.addAll(response.getCollectedVariables()); - outputExternalVariables.addAll(response.getExternalVariables()); - }); - if (!outputVariables.isEmpty() || !outputExternalVariables.isEmpty()) { - results.add(SurveyUnitSimplified.builder() - .questionnaireId(responses.getFirst().getQuestionnaireId()) - .campaignId(responses.getFirst().getCampaignId()) - .interrogationId(responses.getFirst().getInterrogationId()) - .mode(mode) - .variablesUpdate(outputVariables) - .externalVariables(outputExternalVariables) - .build()); - } - }); - }); - return ResponseEntity.ok(results); + @RequestBody List interrogationIds) { + List enumModes = surveyUnitService.findModesByQuestionnaireId(questionnaireId); + // => convertion of "List" -> "List" for query using lamda + List modes = enumModes.stream().map(Mode::getModeName).toList(); + return getLatestForInterrogationListWithModes(questionnaireId, modes, interrogationIds); } - //========= OPTIMISATIONS PERFS (START) ========== /** * @author Adrien Marchal */ @Operation(summary = "Retrieve all responses for a questionnaire and a list of UE", description = "Return the latest state for each variable for the given ids and a given questionnaire.
" + "For a given id, the endpoint returns a document by collection mode (if there is more than one).") - @PostMapping(path = "/simplified/by-list-interrogation-and-questionnaire/latestV2") + @PostMapping(path = "/simplified/by-list-interrogation-and-questionnaire-and-modes/latest") @PreAuthorize("hasRole('USER_KRAFTWERK')") - public ResponseEntity> getLatestForInterrogationListV2(@RequestParam("questionnaireId") String questionnaireId, + public ResponseEntity> getLatestForInterrogationListWithModes(@RequestParam("questionnaireId") String questionnaireId, @RequestParam List modes, @RequestBody List interrogationIds) { - List results = new ArrayList<>(); - - //!!!WARNING!!! : FOR PERFORMANCES PURPOSES, WE DONT'MAKE REQUESTS ON INDIVIDUAL ELEMENTS ANYMORE, BUT ON A SUBLIST OF THE INPUTLIST - final int SUBBLOCK_SIZE = 100; - int offset = 0; - List interrogationIdsSubList = null; - - for(String mode : modes) { - - while(offset <= interrogationIds.size()) { - //extract part of input list - int endOffset = Math.min(offset + SUBBLOCK_SIZE, interrogationIds.size()); - interrogationIdsSubList = interrogationIds.subList(offset, endOffset); - - //1) For each InterrogationId, we collect all responses versions, in which ONLY THE LATEST VERSION of each variable is kept. - List> responses = surveyUnitService.findLatestByIdAndByQuestionnaireIdAndModeOrdered(questionnaireId, mode, interrogationIdsSubList); - - responses.forEach(responsesForSingleInterrId -> { - SurveyUnitSimplified simplifiedResponse = fusionWithLastUpdated(responsesForSingleInterrId, mode); - if(simplifiedResponse != null) { - results.add(simplifiedResponse); - } - }); - - offset = offset + SUBBLOCK_SIZE; - } - } - + List results = surveyUnitService.getLatestForInterrogationListWithModes(questionnaireId, modes, interrogationIds); return ResponseEntity.ok(results); } - private SurveyUnitSimplified fusionWithLastUpdated(List responsesForSingleInterrId, String mode) { - //NOTE : 1) "responses" in input here corresponds to all collected responses versions of a given "InterrogationId", - // in which ONLY THE LATEST VERSION of each variable is kept. - - //return simplifiedResponse - SurveyUnitSimplified simplifiedResponse = null; - - //2) storage of the !!!FUSION!!! OF ALL LATEST UPDATED variables (located in the different versions of the stored "InterrogationId") - List outputVariables = new ArrayList<>(); - List outputExternalVariables = new ArrayList<>(); - - responsesForSingleInterrId.forEach(response -> { - outputVariables.addAll(response.getCollectedVariables()); - outputExternalVariables.addAll(response.getExternalVariables()); - }); - - //3) add to the result list the compiled fusion of all the latest variables - if (!outputVariables.isEmpty() || !outputExternalVariables.isEmpty()) { - Mode modeWrapped = Mode.getEnumFromModeName(mode); - - simplifiedResponse = SurveyUnitSimplified.builder() - .questionnaireId(responsesForSingleInterrId.getFirst().getQuestionnaireId()) - .campaignId(responsesForSingleInterrId.getFirst().getCampaignId()) - .interrogationId(responsesForSingleInterrId.getFirst().getInterrogationId()) - .mode(modeWrapped) - .variablesUpdate(outputVariables) - .externalVariables(outputExternalVariables) - .build(); - } - - return simplifiedResponse; - } - //========= OPTIMISATIONS PERFS (END) ========== - - @Operation(summary = "Save edited variables", description = "Save edited variables document into database") @PostMapping(path = "/save-edited") diff --git a/src/main/java/fr/insee/genesis/domain/ports/api/SurveyUnitApiPort.java b/src/main/java/fr/insee/genesis/domain/ports/api/SurveyUnitApiPort.java index d690ec42..e69cbd14 100644 --- a/src/main/java/fr/insee/genesis/domain/ports/api/SurveyUnitApiPort.java +++ b/src/main/java/fr/insee/genesis/domain/ports/api/SurveyUnitApiPort.java @@ -6,6 +6,7 @@ import fr.insee.genesis.controller.dto.QuestionnaireWithCampaign; import fr.insee.genesis.controller.dto.SurveyUnitDto; import fr.insee.genesis.controller.dto.SurveyUnitInputDto; +import fr.insee.genesis.controller.dto.SurveyUnitSimplified; import fr.insee.genesis.domain.model.surveyunit.Mode; import fr.insee.genesis.domain.model.surveyunit.SurveyUnitModel; import fr.insee.genesis.exceptions.GenesisException; @@ -27,45 +28,36 @@ public interface SurveyUnitApiPort { List findLatestByIdAndByQuestionnaireId(String interrogationId, String questionnaireId); - //========= OPTIMISATIONS PERFS (START) ========== - List> findLatestByIdAndByQuestionnaireIdAndModeOrdered(String questionnaireId, String mode, List interrogationIds); - //========= OPTIMISATIONS PERFS (END) ========== + List getLatestForInterrogationListWithModes(String questionnaireId, List modes, List interrogationIds); SurveyUnitDto findLatestValuesByStateByIdAndByQuestionnaireId(String interrogationId, String questionnaireId); List findInterrogationIdsAndModesByQuestionnaireId(String questionnaireId); + /** + * !!!WARNING!!! : A CALL WITH THIS ENDPOINT ON A BIG COLLECTION (> 300k) MAY KILL THE GENESIS-API APP.!!! + */ List findDistinctInterrogationIdsByQuestionnaireId(String questionnaireId); - //========= OPTIMISATIONS PERFS (START) ========== long countInterrogationIdsByQuestionnaireId(String questionnaireId); List findDistinctPageableInterrogationIdsByQuestionnaireId(String questionnaireId, long totalSize, long blockSize, long page); - List findModesByQuestionnaireIdV2(String questionnaireId); - //========= OPTIMISATIONS PERFS (END) ========== - List findModesByQuestionnaireId(String questionnaireId); - List findModesByCampaignId(String campaignId); - //========= OPTIMISATIONS PERFS (START) ========== - List findModesByCampaignIdV2(String campaignId); - //========= OPTIMISATIONS PERFS (END) ========== + List findModesByCampaignId(String campaignId); Long deleteByQuestionnaireId(String questionnaireId); long countResponses(); - Set findQuestionnaireIdsByCampaignId(String campaignId); - //========= OPTIMISATIONS PERFS (START) ========== /** * @author Adrien Marchal */ - Set findQuestionnaireIdsByCampaignIdV2(String campaignId); - //========= OPTIMISATIONS PERFS (END) ========== + Set findQuestionnaireIdsByCampaignId(String campaignId); Set findDistinctCampaignIds(); diff --git a/src/main/java/fr/insee/genesis/domain/ports/spi/SurveyUnitPersistencePort.java b/src/main/java/fr/insee/genesis/domain/ports/spi/SurveyUnitPersistencePort.java index 7f69b753..d003180d 100644 --- a/src/main/java/fr/insee/genesis/domain/ports/spi/SurveyUnitPersistencePort.java +++ b/src/main/java/fr/insee/genesis/domain/ports/spi/SurveyUnitPersistencePort.java @@ -12,12 +12,10 @@ public interface SurveyUnitPersistencePort { List findByIds(String interrogationId, String questionnaireId); - //========= OPTIMISATIONS PERFS (START) ========== /** * @author Adrien Marchal */ List findBySetOfIdsAndQuestionnaireIdAndMode(String questionnaireId, String mode, List interrogationIdSet); - //========= OPTIMISATIONS PERFS (START) ========== List findByInterrogationId(String interrogationId); @@ -25,32 +23,29 @@ public interface SurveyUnitPersistencePort { Stream findByQuestionnaireId(String questionnaireId); + /** + * !!!WARNING!!! : A CALL WITH THIS ENDPOINT ON A BIG COLLECTION (> 300k) MAY KILL THE GENESIS-API APP.!!! + */ List findInterrogationIdsByQuestionnaireId(String questionnaireId); - //======== OPTIMISATIONS PERFS (START) ======== long countInterrogationIdsByQuestionnaireId(String questionnaireId); List findPageableInterrogationIdsByQuestionnaireId(String questionnaireId, Long skip, Long limit); - List findModesByCampaignIdV2(String campaignId); + List findModesByCampaignId(String campaignId); - List findModesByQuestionnaireIdV2(String questionnaireId); - //======= OPTIMISATIONS PERFS (END) ========= + List findModesByQuestionnaireId(String questionnaireId); - List findInterrogationIdsByCampaignId(String campaignId); Long deleteByQuestionnaireId(String questionnaireId); long count(); - Set findQuestionnaireIdsByCampaignId(String campaignId); - //========= OPTIMISATIONS PERFS (START) ========== /** * @author Adrien Marchal */ - Set findQuestionnaireIdsByCampaignIdV2(String campaignId); - //========= OPTIMISATIONS PERFS (END) ========== + Set findQuestionnaireIdsByCampaignId(String campaignId); Set findDistinctCampaignIds(); diff --git a/src/main/java/fr/insee/genesis/domain/service/surveyunit/SurveyUnitService.java b/src/main/java/fr/insee/genesis/domain/service/surveyunit/SurveyUnitService.java index 5bb0f435..ace65499 100644 --- a/src/main/java/fr/insee/genesis/domain/service/surveyunit/SurveyUnitService.java +++ b/src/main/java/fr/insee/genesis/domain/service/surveyunit/SurveyUnitService.java @@ -2,13 +2,7 @@ import fr.insee.bpm.metadata.model.VariableType; import fr.insee.bpm.metadata.model.VariablesMap; -import fr.insee.genesis.controller.dto.CampaignWithQuestionnaire; -import fr.insee.genesis.controller.dto.QuestionnaireWithCampaign; -import fr.insee.genesis.controller.dto.SurveyUnitDto; -import fr.insee.genesis.controller.dto.SurveyUnitInputDto; -import fr.insee.genesis.controller.dto.VariableDto; -import fr.insee.genesis.controller.dto.VariableInputDto; -import fr.insee.genesis.controller.dto.VariableStateDto; +import fr.insee.genesis.controller.dto.*; import fr.insee.genesis.controller.services.MetadataService; import fr.insee.genesis.domain.model.surveyunit.DataState; import fr.insee.genesis.domain.model.surveyunit.InterrogationId; @@ -74,6 +68,7 @@ public Stream findByQuestionnaireId(String questionnaireId) { return surveyUnitPersistencePort.findByQuestionnaireId(questionnaireId); } + /** * In this method we want to get the latest update for each variable of a survey unit * But we need to separate the updates by mode @@ -84,73 +79,68 @@ public Stream findByQuestionnaireId(String questionnaireId) { */ @Override public List findLatestByIdAndByQuestionnaireId(String interrogationId, String questionnaireId) { - List latestUpdatesbyVariables = new ArrayList<>(); - List surveyUnitModels = surveyUnitPersistencePort.findByIds(interrogationId, questionnaireId); - List modes = getDistinctsModes(surveyUnitModels); - modes.forEach(mode ->{ - List suByMode = surveyUnitModels.stream() - .filter(surveyUnitModel -> surveyUnitModel.getMode().equals(mode)) - .sorted((o1, o2) -> o2.getRecordDate().compareTo(o1.getRecordDate())) //Sorting update by date (latest updates first by date of upload in database) - .toList(); + List enumModes = findModesByQuestionnaireId(questionnaireId); + // => convertion of "List" -> "List" for query using lamda + List modes = enumModes.stream().map(Mode::getModeName).toList(); + List interrogationIds = List.of(new InterrogationId(interrogationId)); + + List responses = new ArrayList<>(); + for(String mode : modes) { + List> surveyUnitModels = findLatestByIdAndByQuestionnaireIdAndModeOrdered(questionnaireId, mode, interrogationIds); + for(List singleSurveyUnitModel : surveyUnitModels) { + responses.addAll(singleSurveyUnitModel); + } + } - //We had all the variables of the oldest update - latestUpdatesbyVariables.add(suByMode.getFirst()); - //We keep the name of already added variables to skip them in older updates - List addedVariables = new ArrayList<>(); - SurveyUnitModel latestUpdate = suByMode.getFirst(); + return responses; + } - if(latestUpdate.getCollectedVariables() == null){ - latestUpdate.setCollectedVariables(new ArrayList<>()); - } - if(latestUpdate.getExternalVariables() == null){ - latestUpdate.setExternalVariables(new ArrayList<>()); - } - latestUpdate.getCollectedVariables().forEach(colVar -> addedVariables.add(new VarIdScopeTuple(colVar.varId(), - colVar.scope(), colVar.iteration()))); - latestUpdate.getExternalVariables().forEach(extVar -> addedVariables.add(new VarIdScopeTuple(extVar.varId(), extVar.scope(), extVar.iteration()))); - - suByMode.forEach(surveyUnitModel -> { - List collectedVariablesToKeep = new ArrayList<>(); - List externalVariablesToKeep = new ArrayList<>(); - // We iterate over the variables of the update and add them to the list if they are not already added - if (surveyUnitModel.getCollectedVariables() != null) { - surveyUnitModel.getCollectedVariables().stream() - .filter(colVar -> !addedVariables.contains(new VarIdScopeTuple(colVar.varId(), colVar.scope() - , colVar.iteration()))) - .forEach(colVar -> { - collectedVariablesToKeep.add(colVar); - addedVariables.add(new VarIdScopeTuple(colVar.varId(), colVar.scope(), colVar.iteration())); - }); - } - if (surveyUnitModel.getExternalVariables() != null){ - surveyUnitModel.getExternalVariables().stream() - .filter(extVar -> !addedVariables.contains(new VarIdScopeTuple(extVar.varId(), extVar.scope(), - extVar.iteration()))) - .forEach(extVar -> { - externalVariablesToKeep.add(extVar); - addedVariables.add(new VarIdScopeTuple(extVar.varId(), extVar.scope(), extVar.iteration())); - }); - } + @Override + public List getLatestForInterrogationListWithModes(String questionnaireId, List modes, List interrogationIds) { + List results = new ArrayList<>(); - // If there are new variables, we add the update to the list of latest updates - if (!collectedVariablesToKeep.isEmpty() || !externalVariablesToKeep.isEmpty()){ - surveyUnitModel.setCollectedVariables(collectedVariablesToKeep); - surveyUnitModel.setExternalVariables(externalVariablesToKeep); - latestUpdatesbyVariables.add(surveyUnitModel); - } - }); - }); - return latestUpdatesbyVariables; + //!!!WARNING!!! : FOR PERFORMANCES PURPOSES, WE DON'T MAKE REQUESTS ON INDIVIDUAL ELEMENTS ANYMORE, BUT ON A SUBLIST OF THE INPUT LIST + final int SUBBLOCK_SIZE = 100; + int offset = 0; + List interrogationIdsSubList = null; + + for(String mode : modes) { + + while(offset <= interrogationIds.size()) { + //extract part of input list + int endOffset = Math.min(offset + SUBBLOCK_SIZE, interrogationIds.size()); + interrogationIdsSubList = interrogationIds.subList(offset, endOffset); + + //1) For each InterrogationId, we collect all responses versions, in which ONLY THE LATEST VERSION of each variable is kept. + List> responses = findLatestByIdAndByQuestionnaireIdAndModeOrdered(questionnaireId, mode, interrogationIdsSubList); + + responses.forEach(responsesForSingleInterrId -> { + SurveyUnitSimplified simplifiedResponse = fusionWithLastUpdated(responsesForSingleInterrId, mode); + if(simplifiedResponse != null) { + results.add(simplifiedResponse); + } + }); + + offset = offset + SUBBLOCK_SIZE; + } + } + + return results; } - //========= OPTIMISATIONS PERFS (START) ========== /** + * In this method we want to get the latest update for each variable of a survey unit + * But we need to separate the updates by mode + * So we will calculate the latest state for a given collection mode + * @param questionnaireId : Questionnaire id + * @param mode : collect mode + * @param interrogationIds : !!!A LIST OF!!! Survey unit ids + * @return the latest update for each variable of a survey unit * @author Adrien Marchal */ - @Override - public List> findLatestByIdAndByQuestionnaireIdAndModeOrdered(String questionnaireId, String mode, + private List> findLatestByIdAndByQuestionnaireIdAndModeOrdered(String questionnaireId, String mode, List interrogationIds) { //return object List> listLatestUpdatesbyVariables = new ArrayList<>(); @@ -225,7 +215,40 @@ private List extractLatestUpdates(List allResp return latestUpdatesbyVariables; } - //========= OPTIMISATIONS PERFS (END) ========== + + + private SurveyUnitSimplified fusionWithLastUpdated(List responsesForSingleInterrId, String mode) { + //NOTE : 1) "responses" in input here corresponds to all collected responses versions of a given "InterrogationId", + // in which ONLY THE LATEST VERSION of each variable is kept. + + //return simplifiedResponse + SurveyUnitSimplified simplifiedResponse = null; + + //2) storage of the !!!FUSION!!! OF ALL LATEST UPDATED variables (located in the different versions of the stored "InterrogationId") + List outputVariables = new ArrayList<>(); + List outputExternalVariables = new ArrayList<>(); + + responsesForSingleInterrId.forEach(response -> { + outputVariables.addAll(response.getCollectedVariables()); + outputExternalVariables.addAll(response.getExternalVariables()); + }); + + //3) add to the result list the compiled fusion of all the latest variables + if (!outputVariables.isEmpty() || !outputExternalVariables.isEmpty()) { + Mode modeWrapped = Mode.getEnumFromModeName(mode); + + simplifiedResponse = SurveyUnitSimplified.builder() + .questionnaireId(responsesForSingleInterrId.getFirst().getQuestionnaireId()) + .campaignId(responsesForSingleInterrId.getFirst().getCampaignId()) + .interrogationId(responsesForSingleInterrId.getFirst().getInterrogationId()) + .mode(modeWrapped) + .variablesUpdate(outputVariables) + .externalVariables(outputExternalVariables) + .build(); + } + + return simplifiedResponse; + } @Override @@ -265,6 +288,9 @@ public SurveyUnitDto findLatestValuesByStateByIdAndByQuestionnaireId(String inte return surveyUnitDto; } + /** + * !!!WARNING!!! : A CALL WITH THIS ENDPOINT ON A BIG COLLECTION (> 300k) MAY KILL THE GENESIS-API APP.!!! + */ @Override public List findDistinctInterrogationIdsByQuestionnaireId(String questionnaireId) { List surveyUnitModels = surveyUnitPersistencePort.findInterrogationIdsByQuestionnaireId(questionnaireId); @@ -273,7 +299,6 @@ public List findDistinctInterrogationIdsByQuestionnaireId(Strin return suIds.stream().distinct().toList(); } - //============ OPTIMISATIONS PERFS (START) ============ /** * @author Adrien Marchal @@ -312,18 +337,21 @@ public List findDistinctPageableInterrogationIdsByQuestionnaire public long countInterrogationIdsByQuestionnaireId(String questionnaireId) { return surveyUnitPersistencePort.countInterrogationIdsByQuestionnaireId(questionnaireId); } - //=========== OPTIMISATIONS PERFS (END) ============= + /** + * !!!WARNING!!! : A CALL WITH THIS ENDPOINT ON A BIG COLLECTION (> 300k) MAY KILL THE GENESIS-API APP.!!! + */ @Override public List findInterrogationIdsAndModesByQuestionnaireId(String questionnaireId) { List surveyUnitModels = surveyUnitPersistencePort.findInterrogationIdsByQuestionnaireId(questionnaireId); return surveyUnitModels.stream().distinct().toList(); } + @Override public List findModesByQuestionnaireId(String questionnaireId) { - List surveyUnitModels = surveyUnitPersistencePort.findInterrogationIdsByQuestionnaireId(questionnaireId); + List surveyUnitModels = surveyUnitPersistencePort.findModesByQuestionnaireId(questionnaireId); List sources = new ArrayList<>(); surveyUnitModels.forEach(surveyUnitModel -> sources.add(surveyUnitModel.getMode())); return sources.stream().distinct().toList(); @@ -331,29 +359,12 @@ public List findModesByQuestionnaireId(String questionnaireId) { @Override public List findModesByCampaignId(String campaignId) { - List surveyUnitModels = surveyUnitPersistencePort.findInterrogationIdsByCampaignId(campaignId); + List surveyUnitModels = surveyUnitPersistencePort.findModesByCampaignId(campaignId); List sources = new ArrayList<>(); surveyUnitModels.forEach(surveyUnitModel -> sources.add(surveyUnitModel.getMode())); return sources.stream().distinct().toList(); } - //========= OPTIMISATIONS PERFS (START) ========== - @Override - public List findModesByQuestionnaireIdV2(String questionnaireId) { - List surveyUnitModels = surveyUnitPersistencePort.findModesByQuestionnaireIdV2(questionnaireId); - List sources = new ArrayList<>(); - surveyUnitModels.forEach(surveyUnitModel -> sources.add(surveyUnitModel.getMode())); - return sources.stream().distinct().toList(); - } - - @Override - public List findModesByCampaignIdV2(String campaignId) { - List surveyUnitModels = surveyUnitPersistencePort.findModesByCampaignIdV2(campaignId); - List sources = new ArrayList<>(); - surveyUnitModels.forEach(surveyUnitModel -> sources.add(surveyUnitModel.getMode())); - return sources.stream().distinct().toList(); - } - //========= OPTIMISATIONS PERFS (END) ========== @Override public Long deleteByQuestionnaireId(String questionnaireId) { @@ -365,26 +376,22 @@ public long countResponses() { return surveyUnitPersistencePort.count(); } - @Override - public Set findQuestionnaireIdsByCampaignId(String campaignId) { - return surveyUnitPersistencePort.findQuestionnaireIdsByCampaignId(campaignId); - } - //========= OPTIMISATIONS PERFS (START) ========== /** * @author Adrien Marchal */ @Override - public Set findQuestionnaireIdsByCampaignIdV2(String campaignId) { - return surveyUnitPersistencePort.findQuestionnaireIdsByCampaignIdV2(campaignId); + public Set findQuestionnaireIdsByCampaignId(String campaignId) { + return surveyUnitPersistencePort.findQuestionnaireIdsByCampaignId(campaignId); } - //========= OPTIMISATIONS PERFS (END) ========== + @Override public Set findDistinctCampaignIds() { return surveyUnitPersistencePort.findDistinctCampaignIds(); } + @Override public List findCampaignsWithQuestionnaires() { List campaignsWithQuestionnaireList = new ArrayList<>(); @@ -395,6 +402,7 @@ public List findCampaignsWithQuestionnaires() { return campaignsWithQuestionnaireList; } + @Override public long countResponsesByCampaignId(String campaignId){ return surveyUnitPersistencePort.countByCampaignId(campaignId); diff --git a/src/main/java/fr/insee/genesis/infrastructure/adapter/SurveyUnitMongoAdapter.java b/src/main/java/fr/insee/genesis/infrastructure/adapter/SurveyUnitMongoAdapter.java index 5eec2c2c..a3c755f1 100644 --- a/src/main/java/fr/insee/genesis/infrastructure/adapter/SurveyUnitMongoAdapter.java +++ b/src/main/java/fr/insee/genesis/infrastructure/adapter/SurveyUnitMongoAdapter.java @@ -49,7 +49,6 @@ public List findByIds(String interrogationId, String questionna } - //========= OPTIMISATIONS PERFS (START) ========== /** * @author Adrien Marchal */ @@ -58,7 +57,7 @@ public List findBySetOfIdsAndQuestionnaireIdAndMode(String ques List surveyUnits = mongoRepository.findBySetOfIdsAndQuestionnaireIdAndMode(questionnaireId, mode, interrogationIdSet); return surveyUnits.isEmpty() ? Collections.emptyList() : SurveyUnitDocumentMapper.INSTANCE.listDocumentToListModel(surveyUnits); } - //========= OPTIMISATIONS PERFS (END) ========== + @Override public List findByInterrogationId(String questionnaireId) { @@ -93,34 +92,14 @@ public long count() { return mongoRepository.count(); } - @Override - public Set findQuestionnaireIdsByCampaignId(String campaignId){ - Set mongoResponse = - mongoRepository.findQuestionnaireIdsByCampaignId(campaignId); - - //Extract questionnaireIds from JSON response - Set questionnaireIds = new HashSet<>(); - for(String line : mongoResponse){ - ObjectMapper objectMapper = new ObjectMapper().findAndRegisterModules(); - try{ - JsonNode jsonNode = objectMapper.readTree(line); - questionnaireIds.add(jsonNode.get("questionnaireId").asText()); - }catch (JsonProcessingException e){ - log.error(e.getMessage()); - } - } - - return questionnaireIds; - } - //========= OPTIMISATIONS PERFS (START) ========== /** * @author Adrien Marchal */ @Override - public Set findQuestionnaireIdsByCampaignIdV2(String campaignId){ + public Set findQuestionnaireIdsByCampaignId(String campaignId){ Set mongoResponse = - mongoRepository.findQuestionnaireIdsByCampaignIdV2(campaignId); + mongoRepository.findQuestionnaireIdsByCampaignId(campaignId); //Extract questionnaireIds from JSON response Set questionnaireIds = new HashSet<>(); @@ -136,7 +115,7 @@ public Set findQuestionnaireIdsByCampaignIdV2(String campaignId){ return questionnaireIds; } - //========= OPTIMISATIONS PERFS (END) ========== + @Override public Set findDistinctCampaignIds() { @@ -148,13 +127,16 @@ public Set findDistinctCampaignIds() { return campaignIds; } + /** + * !!!WARNING!!! : A CALL WITH THIS ENDPOINT ON A BIG COLLECTION (> 300k) MAY KILL THE GENESIS-API APP.!!! + */ @Override public List findInterrogationIdsByQuestionnaireId(String questionnaireId) { List surveyUnits = mongoRepository.findInterrogationIdsByQuestionnaireId(questionnaireId); return surveyUnits.isEmpty() ? Collections.emptyList() : SurveyUnitDocumentMapper.INSTANCE.listDocumentToListModel(surveyUnits); } - //========== OPTIMISATIONS PERFS (START) =========== + @Override public long countInterrogationIdsByQuestionnaireId(String questionnaireId) { return mongoRepository.countInterrogationIdsByQuestionnaireId(questionnaireId); @@ -167,25 +149,18 @@ public List findPageableInterrogationIdsByQuestionnaireId(Strin } @Override - public List findModesByCampaignIdV2(String campaignId) { - List surveyUnits = mongoRepository.findModesByCampaignIdV2(campaignId); + public List findModesByCampaignId(String campaignId) { + List surveyUnits = mongoRepository.findModesByCampaignId(campaignId); return surveyUnits.isEmpty() ? Collections.emptyList() : SurveyUnitDocumentMapper.INSTANCE.listDocumentToListModel(surveyUnits); } @Override - public List findModesByQuestionnaireIdV2(String questionnaireId) { - List surveyUnits = mongoRepository.findModesByQuestionnaireIdV2(questionnaireId); + public List findModesByQuestionnaireId(String questionnaireId) { + List surveyUnits = mongoRepository.findModesByQuestionnaireId(questionnaireId); return surveyUnits.isEmpty() ? Collections.emptyList() : SurveyUnitDocumentMapper.INSTANCE.listDocumentToListModel(surveyUnits); } - //========== OPTIMISATIONS PERFS (END) ============ - @Override - public List findInterrogationIdsByCampaignId(String campaignId) { - List surveyUnits = mongoRepository.findInterrogationIdsByCampaignId(campaignId); - return surveyUnits.isEmpty() ? Collections.emptyList() : SurveyUnitDocumentMapper.INSTANCE.listDocumentToListModel(surveyUnits); - - } public long countByCampaignId(String campaignId){ return mongoRepository.countByCampaignId(campaignId); diff --git a/src/main/java/fr/insee/genesis/infrastructure/repository/SurveyUnitMongoDBRepository.java b/src/main/java/fr/insee/genesis/infrastructure/repository/SurveyUnitMongoDBRepository.java index dc915db9..86f7f7f3 100644 --- a/src/main/java/fr/insee/genesis/infrastructure/repository/SurveyUnitMongoDBRepository.java +++ b/src/main/java/fr/insee/genesis/infrastructure/repository/SurveyUnitMongoDBRepository.java @@ -18,18 +18,21 @@ public interface SurveyUnitMongoDBRepository extends MongoRepository findByInterrogationIdAndQuestionnaireId(String interrogationId, String questionnaireId); - //========= OPTIMISATIONS PERFS (START) ========== + /** * @author Adrien Marchal */ @Query("{ 'questionnaireId' : ?0, 'mode' : ?1, 'interrogationId' : { $in: ?2 } }") List findBySetOfIdsAndQuestionnaireIdAndMode(String questionnaireId, String mode, List interrogationIdSet); - //========= OPTIMISATIONS PERFS (END) ========== + + /** + * !!!WARNING!!! : A CALL WITH THIS ENDPOINT ON A BIG COLLECTION (> 300k) MAY KILL THE GENESIS-API APP.!!! + */ @Query(value = "{ 'questionnaireId' : ?0 }", fields = "{ 'interrogationId' : 1, 'mode' : 1 }") List findInterrogationIdsByQuestionnaireId(String questionnaireId); - //========= OPTIMISATIONS PERFS (START) ========== + /** * @author Adrien Marchal */ @@ -53,18 +56,15 @@ public interface SurveyUnitMongoDBRepository extends MongoRepository findModesByCampaignIdV2(String campaignId); + List findModesByCampaignId(String campaignId); @Aggregation(pipeline = { "{ '$match': { 'questionnaireId' : ?0 } }", "{ '$group': { '_id': '$mode' } }", "{ '$set': { 'mode': '$_id', '_id': '$$REMOVE' } }" }) - List findModesByQuestionnaireIdV2(String campaignId); - //========= OPTIMISATIONS PERFS (END) ========== + List findModesByQuestionnaireId(String questionnaireId); - @Query(value = "{ 'campaignId' : ?0 }", fields = "{ 'interrogationId' : 1, 'mode' : 1 }") - List findInterrogationIdsByCampaignId(String campaignId); Long deleteByQuestionnaireId(String questionnaireId); @@ -73,10 +73,7 @@ public interface SurveyUnitMongoDBRepository extends MongoRepository findQuestionnaireIdsByCampaignId(String campaignId); - //========= OPTIMISATIONS PERFS (START) ========== /** * @author Adrien Marchal * Here we make a "DISTINCT" query @@ -86,8 +83,8 @@ public interface SurveyUnitMongoDBRepository extends MongoRepository findQuestionnaireIdsByCampaignIdV2(String campaignId); - //========= OPTIMISATIONS PERFS (END) ========== + Set findQuestionnaireIdsByCampaignId(String campaignId); + long countByCampaignId(String campaignId); diff --git a/src/test/java/fr/insee/genesis/controller/rest/responses/ModeControllerTest.java b/src/test/java/fr/insee/genesis/controller/rest/responses/ModeControllerTest.java index db5c0f84..c83efdde 100644 --- a/src/test/java/fr/insee/genesis/controller/rest/responses/ModeControllerTest.java +++ b/src/test/java/fr/insee/genesis/controller/rest/responses/ModeControllerTest.java @@ -62,24 +62,4 @@ void getModesByCampaignTest() { Assertions.assertThat(response.getBody().getFirst()).isEqualTo(Mode.WEB); } - //========= OPTIMISATIONS PERFS (START) ========== - @Test - void getModesByQuestionnaireV2Test() { - ResponseEntity> response = modeControllerStatic.getModesByQuestionnaireV2(DEFAULT_QUESTIONNAIRE_ID); - - Assertions.assertThat(response.getStatusCode().is2xxSuccessful()).isTrue(); - Assertions.assertThat(response.getBody()).isNotNull().isNotEmpty().hasSize(1); - Assertions.assertThat(response.getBody().getFirst()).isEqualTo(Mode.WEB); - } - - @Test - void getModesByCampaignV2Test() { - ResponseEntity> response = modeControllerStatic.getModesByCampaignV2(CAMPAIGN_ID); - - Assertions.assertThat(response.getStatusCode().is2xxSuccessful()).isTrue(); - Assertions.assertThat(response.getBody()).isNotNull().isNotEmpty().hasSize(1); - Assertions.assertThat(response.getBody().getFirst()).isEqualTo(Mode.WEB); - } - //========= OPTIMISATIONS PERFS (END) ========== - } diff --git a/src/test/java/fr/insee/genesis/controller/rest/responses/ResponseControllerTest.java b/src/test/java/fr/insee/genesis/controller/rest/responses/ResponseControllerTest.java index 4b37f937..d1b107a7 100644 --- a/src/test/java/fr/insee/genesis/controller/rest/responses/ResponseControllerTest.java +++ b/src/test/java/fr/insee/genesis/controller/rest/responses/ResponseControllerTest.java @@ -782,4 +782,34 @@ void saveEditedTest_null() { Assertions.assertThat(docSaved.getModifiedBy()).isNull(); } + + + @Test + void getLatestForInterrogationListWithModes_performance() throws GenesisException { + //GIVEN + Utils.fillMongoStubForPerformances(DataState.COLLECTED, + LocalDateTime.of(1999,2,2,0,0,0), + LocalDateTime.of(1999,2,2,0,0,0), + surveyUnitPersistencePortStub + ); + + + //WHEN + List modes = new ArrayList<>(); + modes.add("WEB"); + List interrogationIds = Utils.generateInterrogationIds(); + long start = System.currentTimeMillis(); + ResponseEntity> response = responseControllerStatic.getLatestForInterrogationListWithModes( + DEFAULT_QUESTIONNAIRE_ID, + modes, + interrogationIds + ); + long end = System.currentTimeMillis(); + long delta = end - start; + + //THEN + Assertions.assertThat(delta < 3000).isTrue(); + } + + } diff --git a/src/test/java/fr/insee/genesis/controller/rest/responses/Utils.java b/src/test/java/fr/insee/genesis/controller/rest/responses/Utils.java index a4602276..25085637 100644 --- a/src/test/java/fr/insee/genesis/controller/rest/responses/Utils.java +++ b/src/test/java/fr/insee/genesis/controller/rest/responses/Utils.java @@ -1,11 +1,9 @@ package fr.insee.genesis.controller.rest.responses; import cucumber.TestConstants; -import fr.insee.genesis.domain.model.surveyunit.DataState; -import fr.insee.genesis.domain.model.surveyunit.Mode; -import fr.insee.genesis.domain.model.surveyunit.SurveyUnitModel; -import fr.insee.genesis.domain.model.surveyunit.VariableModel; +import fr.insee.genesis.domain.model.surveyunit.*; import fr.insee.genesis.stubs.SurveyUnitPersistencePortStub; +import org.apache.commons.lang3.StringUtils; import java.io.File; import java.io.IOException; @@ -310,4 +308,42 @@ static void addAdditionalSurveyUnitModelToMongoStub(DataState state, surveyUnitPersistencePortStub.getMongoStub().add(recentSurveyUnitModel); } + + static void fillMongoStubForPerformances(DataState state, + LocalDateTime fileDate, + LocalDateTime recordDate, + SurveyUnitPersistencePortStub surveyUnitPersistencePortStub) { + List sumList = new ArrayList<>(); + + + for (int i = 0; i < 1000 ; i++) { + SurveyUnitModel recentSurveyUnitModel = SurveyUnitModel.builder() + .campaignId("TEST-TABLEAUX") + .mode(Mode.WEB) + //interrogationId example : "UE000000001" + .interrogationId(StringUtils.leftPad(String.valueOf(i), 9, "0")) + .questionnaireId(DEFAULT_QUESTIONNAIRE_ID) + .state(state) + .fileDate(fileDate) + .recordDate(recordDate) + .externalVariables(new ArrayList<>()) + .collectedVariables(new ArrayList<>()) + .build(); + sumList.add(recentSurveyUnitModel); + } + + surveyUnitPersistencePortStub.getMongoStub().addAll(sumList); + } + + + static List generateInterrogationIds() { + List ids = new ArrayList<>(); + for (int i = 0; i < 1000; i++) { + InterrogationId interrogationId = new InterrogationId(StringUtils.leftPad(String.valueOf(i), 9, "0")); + ids.add(interrogationId); + } + return ids; + } + + } diff --git a/src/test/java/fr/insee/genesis/domain/service/SurveyUnitServiceTest.java b/src/test/java/fr/insee/genesis/domain/service/SurveyUnitServiceTest.java index d56d4b49..268eb620 100644 --- a/src/test/java/fr/insee/genesis/domain/service/SurveyUnitServiceTest.java +++ b/src/test/java/fr/insee/genesis/domain/service/SurveyUnitServiceTest.java @@ -240,21 +240,14 @@ void findDistinctInterrogationIdsByQuestionnaireIdTest(){ ).isNotEmpty().hasSize(1); } + @Test - void findInterrogationIdsByQuestionnaireIdTest(){ + void findModesByQuestionnaireIdTest(){ Assertions.assertThat(surveyUnitServiceStatic.findModesByQuestionnaireId(DEFAULT_QUESTIONNAIRE_ID)).filteredOn( mode -> mode.equals(Mode.WEB) ).isNotEmpty(); } - //========= OPTIMISATIONS PERFS (START) ========== - @Test - void findModesByQuestionnaireIdV2Test(){ - Assertions.assertThat(surveyUnitServiceStatic.findModesByQuestionnaireIdV2(DEFAULT_QUESTIONNAIRE_ID)).filteredOn( - mode -> mode.equals(Mode.WEB) - ).isNotEmpty(); - } - //========= OPTIMISATIONS PERFS (END) ========== @Test void getQuestionnairesByCampaignTest() { diff --git a/src/test/java/fr/insee/genesis/stubs/SurveyUnitPersistencePortStub.java b/src/test/java/fr/insee/genesis/stubs/SurveyUnitPersistencePortStub.java index b9d8b1c4..ea6e01de 100644 --- a/src/test/java/fr/insee/genesis/stubs/SurveyUnitPersistencePortStub.java +++ b/src/test/java/fr/insee/genesis/stubs/SurveyUnitPersistencePortStub.java @@ -30,14 +30,19 @@ public List findByIds(String interrogationId, String questionna return surveyUnitModelList; } - //========= OPTIMISATIONS PERFS (START) ========== + /** * @author Adrien Marchal */ public List findBySetOfIdsAndQuestionnaireIdAndMode(String questionnaireId, String mode, List interrogationIdSet) { - return new ArrayList(); + List surveyUnitModelList = new ArrayList<>(); + for(SurveyUnitModel SurveyUnitModel : mongoStub){ + if(interrogationIdSet.contains(SurveyUnitModel.getInterrogationId()) && SurveyUnitModel.getQuestionnaireId().equals(questionnaireId)) + surveyUnitModelList.add(SurveyUnitModel); + } + + return surveyUnitModelList; } - //========= OPTIMISATIONS PERFS (START) ========== @Override @@ -75,6 +80,9 @@ public Stream findByQuestionnaireId(String questionnaireId) { return surveyUnitModelList.stream(); } + /** + * !!!WARNING!!! : A CALL WITH THIS ENDPOINT ON A BIG COLLECTION (> 300k) MAY KILL THE GENESIS-API APP.!!! + */ @Override public List findInterrogationIdsByQuestionnaireId(String questionnaireId) { List surveyUnitModelList = new ArrayList<>(); @@ -89,7 +97,6 @@ public List findInterrogationIdsByQuestionnaireId(String questi } - //======== OPTIMISATIONS PERFS (START) ======== /** * @author Adrien Marchal */ @@ -101,28 +108,22 @@ public long countInterrogationIdsByQuestionnaireId(String questionnaireId) { * @author Adrien Marchal */ public List findPageableInterrogationIdsByQuestionnaireId(String questionnaireId, Long skip, Long limit) { - return List.of(); - } - - - @Override - public List findModesByCampaignIdV2(String campaignId) { List surveyUnitModelList = new ArrayList<>(); for(SurveyUnitModel SurveyUnitModel : mongoStub){ - if(SurveyUnitModel.getCampaignId().equals(campaignId)) + if(SurveyUnitModel.getQuestionnaireId().equals(questionnaireId)) surveyUnitModelList.add( new SurveyUnitModel(SurveyUnitModel.getInterrogationId(), SurveyUnitModel.getMode()) ); } - return surveyUnitModelList; } + @Override - public List findModesByQuestionnaireIdV2(String questionnaireId) { + public List findModesByCampaignId(String campaignId) { List surveyUnitModelList = new ArrayList<>(); for(SurveyUnitModel SurveyUnitModel : mongoStub){ - if(SurveyUnitModel.getQuestionnaireId().equals(questionnaireId)) + if(SurveyUnitModel.getCampaignId().equals(campaignId)) surveyUnitModelList.add( new SurveyUnitModel(SurveyUnitModel.getInterrogationId(), SurveyUnitModel.getMode()) ); @@ -130,14 +131,12 @@ public List findModesByQuestionnaireIdV2(String questionnaireId return surveyUnitModelList; } - //======= OPTIMISATIONS PERFS (END) ========= - @Override - public List findInterrogationIdsByCampaignId(String campaignId) { + public List findModesByQuestionnaireId(String questionnaireId) { List surveyUnitModelList = new ArrayList<>(); for(SurveyUnitModel SurveyUnitModel : mongoStub){ - if(SurveyUnitModel.getCampaignId().equals(campaignId)) + if(SurveyUnitModel.getQuestionnaireId().equals(questionnaireId)) surveyUnitModelList.add( new SurveyUnitModel(SurveyUnitModel.getInterrogationId(), SurveyUnitModel.getMode()) ); @@ -146,6 +145,7 @@ public List findInterrogationIdsByCampaignId(String campaignId) return surveyUnitModelList; } + @Override public Long deleteByQuestionnaireId(String questionnaireId) { return null; @@ -156,6 +156,7 @@ public long count() { return mongoStub.size(); } + @Override public Set findQuestionnaireIdsByCampaignId(String campaignId) { Set questionnaireIdSet = new HashSet<>(); @@ -167,13 +168,6 @@ public Set findQuestionnaireIdsByCampaignId(String campaignId) { return questionnaireIdSet; } - //========= OPTIMISATIONS PERFS (START) ========== - @Override - public Set findQuestionnaireIdsByCampaignIdV2(String campaignId) { - //This stub is explicitally the same as method "findQuestionnaireIdsByCampaignId()" - return findQuestionnaireIdsByCampaignId(campaignId); - } - //========= OPTIMISATIONS PERFS (END) ========== @Override public Set findDistinctCampaignIds() {