From b9650f29559b18670a8ec2f5416cb04bafadd5e0 Mon Sep 17 00:00:00 2001 From: Nicolas Senave Date: Mon, 24 Apr 2023 17:46:32 +0200 Subject: [PATCH 01/12] refactor(composition): one class per step (wip) --- .../exception/DeReferencingException.java | 12 ++++ .../composition/CompositionStep.java | 18 ++++++ .../composition/InsertCodeLists.java | 16 ++++++ .../composition/InsertFlowControls.java | 14 +++++ .../composition/InsertIterations.java | 15 +++++ ...eComposition.java => InsertSequences.java} | 9 +-- .../composition/InsertVariables.java | 14 +++++ .../composition/QuestionnaireComposition.java | 37 ++++--------- ...tion.java => UpdateFlowControlBounds.java} | 21 ++++++- .../composition/UpdateIterationBounds.java | 55 +++++++++++++++++++ ...va => UpdateReferencedVariablesScope.java} | 39 ++++--------- 11 files changed, 190 insertions(+), 60 deletions(-) create mode 100644 src/main/java/fr/insee/pogues/exception/DeReferencingException.java create mode 100644 src/main/java/fr/insee/pogues/transforms/visualize/composition/CompositionStep.java create mode 100644 src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertCodeLists.java create mode 100644 src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertFlowControls.java create mode 100644 src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertIterations.java rename src/main/java/fr/insee/pogues/transforms/visualize/composition/{SequenceComposition.java => InsertSequences.java} (83%) create mode 100644 src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertVariables.java rename src/main/java/fr/insee/pogues/transforms/visualize/composition/{FilterComposition.java => UpdateFlowControlBounds.java} (64%) create mode 100644 src/main/java/fr/insee/pogues/transforms/visualize/composition/UpdateIterationBounds.java rename src/main/java/fr/insee/pogues/transforms/visualize/composition/{LoopComposition.java => UpdateReferencedVariablesScope.java} (78%) diff --git a/src/main/java/fr/insee/pogues/exception/DeReferencingException.java b/src/main/java/fr/insee/pogues/exception/DeReferencingException.java new file mode 100644 index 00000000..2d291a66 --- /dev/null +++ b/src/main/java/fr/insee/pogues/exception/DeReferencingException.java @@ -0,0 +1,12 @@ +package fr.insee.pogues.exception; + +/** + * Exception thrown if an error occurs during questionnaire de-referencing (composition feature). + */ +public class DeReferencingException extends RuntimeException { + + public DeReferencingException(String message, Exception e) { + super(message, e); + } + +} diff --git a/src/main/java/fr/insee/pogues/transforms/visualize/composition/CompositionStep.java b/src/main/java/fr/insee/pogues/transforms/visualize/composition/CompositionStep.java new file mode 100644 index 00000000..0117fb19 --- /dev/null +++ b/src/main/java/fr/insee/pogues/transforms/visualize/composition/CompositionStep.java @@ -0,0 +1,18 @@ +package fr.insee.pogues.transforms.visualize.composition; + +import fr.insee.pogues.exception.DeReferencingException; +import fr.insee.pogues.model.Questionnaire; + +/** + * Interface for processing step when de-referencing a questionnaire. + */ +public interface CompositionStep { + + /** + * Update questionnaire content with referenced questionnaire given. + * @param questionnaire Referencing questionnaire. + * @param referencedQuestionnaire Referenced questionnaire. + */ + void apply(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) throws DeReferencingException; + +} diff --git a/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertCodeLists.java b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertCodeLists.java new file mode 100644 index 00000000..2a8a36b6 --- /dev/null +++ b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertCodeLists.java @@ -0,0 +1,16 @@ +package fr.insee.pogues.transforms.visualize.composition; + +import fr.insee.pogues.exception.DeReferencingException; +import fr.insee.pogues.model.CodeLists; +import fr.insee.pogues.model.Questionnaire; + +public class InsertCodeLists implements CompositionStep { + + @Override + public void apply(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) + throws DeReferencingException { + questionnaire.setCodeLists(new CodeLists()); + questionnaire.getCodeLists().getCodeList().addAll(referencedQuestionnaire.getCodeLists().getCodeList()); + } + +} diff --git a/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertFlowControls.java b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertFlowControls.java new file mode 100644 index 00000000..64d1b4b2 --- /dev/null +++ b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertFlowControls.java @@ -0,0 +1,14 @@ +package fr.insee.pogues.transforms.visualize.composition; + +import fr.insee.pogues.exception.DeReferencingException; +import fr.insee.pogues.model.Questionnaire; + +public class InsertFlowControls implements CompositionStep { + + @Override + public void apply(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) + throws DeReferencingException { + questionnaire.getFlowControl().addAll(referencedQuestionnaire.getFlowControl()); + } + +} diff --git a/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertIterations.java b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertIterations.java new file mode 100644 index 00000000..af7b61b1 --- /dev/null +++ b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertIterations.java @@ -0,0 +1,15 @@ +package fr.insee.pogues.transforms.visualize.composition; + +import fr.insee.pogues.exception.DeReferencingException; +import fr.insee.pogues.model.Questionnaire; + +public class InsertIterations implements CompositionStep { + + @Override + public void apply(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) + throws DeReferencingException { + questionnaire.setIterations(new Questionnaire.Iterations()); + questionnaire.getIterations().getIteration().addAll(referencedQuestionnaire.getIterations().getIteration()); + } + +} diff --git a/src/main/java/fr/insee/pogues/transforms/visualize/composition/SequenceComposition.java b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertSequences.java similarity index 83% rename from src/main/java/fr/insee/pogues/transforms/visualize/composition/SequenceComposition.java rename to src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertSequences.java index 46af2bc9..508adb2b 100644 --- a/src/main/java/fr/insee/pogues/transforms/visualize/composition/SequenceComposition.java +++ b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertSequences.java @@ -1,5 +1,6 @@ package fr.insee.pogues.transforms.visualize.composition; +import fr.insee.pogues.exception.DeReferencingException; import fr.insee.pogues.model.ComponentType; import fr.insee.pogues.model.Questionnaire; import lombok.extern.slf4j.Slf4j; @@ -12,16 +13,16 @@ * Methods to insert and update sequence objects when de-referencing a questionnaire. */ @Slf4j -class SequenceComposition { - - private SequenceComposition() {} +class InsertSequences implements CompositionStep { /** * Replace questionnaire reference by its sequences. * @param questionnaire Referencing questionnaire. * @param referencedQuestionnaire Referenced questionnaire. */ - static void insertSequences(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) { + @Override + public void apply(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) + throws DeReferencingException { // List refSequences = getSequences(referencedQuestionnaire); int indexOfModification = 0; diff --git a/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertVariables.java b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertVariables.java new file mode 100644 index 00000000..14a677ad --- /dev/null +++ b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertVariables.java @@ -0,0 +1,14 @@ +package fr.insee.pogues.transforms.visualize.composition; + +import fr.insee.pogues.exception.DeReferencingException; +import fr.insee.pogues.model.Questionnaire; + +class InsertVariables implements CompositionStep { + + @Override + public void apply(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) + throws DeReferencingException { + questionnaire.getVariables().getVariable().addAll(referencedQuestionnaire.getVariables().getVariable()); + } + +} diff --git a/src/main/java/fr/insee/pogues/transforms/visualize/composition/QuestionnaireComposition.java b/src/main/java/fr/insee/pogues/transforms/visualize/composition/QuestionnaireComposition.java index 14627ecf..c80fc858 100644 --- a/src/main/java/fr/insee/pogues/transforms/visualize/composition/QuestionnaireComposition.java +++ b/src/main/java/fr/insee/pogues/transforms/visualize/composition/QuestionnaireComposition.java @@ -1,18 +1,10 @@ package fr.insee.pogues.transforms.visualize.composition; -import fr.insee.pogues.exception.IllegalFlowControlException; -import fr.insee.pogues.exception.IllegalIterationException; +import fr.insee.pogues.exception.DeReferencingException; import fr.insee.pogues.model.CodeLists; -import fr.insee.pogues.model.FlowControlType; -import fr.insee.pogues.model.IterationType; import fr.insee.pogues.model.Questionnaire; import lombok.extern.slf4j.Slf4j; -import static fr.insee.pogues.transforms.visualize.composition.FilterComposition.updateFlowControlBounds; -import static fr.insee.pogues.transforms.visualize.composition.LoopComposition.updateIterationBounds; -import static fr.insee.pogues.transforms.visualize.composition.LoopComposition.updateReferencedVariablesScope; -import static fr.insee.pogues.transforms.visualize.composition.SequenceComposition.insertSequences; - @Slf4j public class QuestionnaireComposition { @@ -22,11 +14,10 @@ private QuestionnaireComposition() {} * Replace referenced questionnaire by its component. Update elements that are impacted. * @param questionnaire Referencing questionnaire. * @param referencedQuestionnaire Referenced questionnaire. - * @throws IllegalFlowControlException if one of the FlowControl object involved is invalid. - * @throws IllegalIterationException if one of the Iteration object involved is invalid. + * @throws DeReferencingException if an error occurs during de-referencing. */ public static void insertReference(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) - throws IllegalFlowControlException, IllegalIterationException { + throws DeReferencingException { // String id = questionnaire.getId(); String reference = referencedQuestionnaire.getId(); @@ -34,49 +25,43 @@ public static void insertReference(Questionnaire questionnaire, Questionnaire re // Update the scope of the referenced questionnaire variables if (questionnaire.getIterations() != null) - updateReferencedVariablesScope(questionnaire, referencedQuestionnaire); + new UpdateReferencedVariablesScope().apply(questionnaire, referencedQuestionnaire); // Add sequences - insertSequences(questionnaire, referencedQuestionnaire); + new InsertSequences().apply(questionnaire, referencedQuestionnaire); log.info("Sequences from '{}' inserted in '{}'", reference, id); // Add variables - questionnaire.getVariables().getVariable().addAll(referencedQuestionnaire.getVariables().getVariable()); + new InsertVariables().apply(questionnaire, referencedQuestionnaire); log.info("Variables from '{}' inserted in '{}'", reference, id); // Add code lists CodeLists refCodeLists = referencedQuestionnaire.getCodeLists(); if (refCodeLists != null) { - questionnaire.setCodeLists(new CodeLists()); - questionnaire.getCodeLists().getCodeList().addAll(refCodeLists.getCodeList()); + new InsertCodeLists().apply(questionnaire, referencedQuestionnaire); log.info("Code lists from '{}' inserted in '{}'", reference, id); } else { log.info("No code lists in referenced questionnaire '{}'", reference); } // Update filters in referencing questionnaire - for (FlowControlType flowControlType : questionnaire.getFlowControl()) { - updateFlowControlBounds(referencedQuestionnaire, flowControlType); - } + new UpdateFlowControlBounds().apply(questionnaire, referencedQuestionnaire); log.info("Flow controls' bounds updated in '{}' when de-referencing '{}'", id, reference); // Add flow controls (filters) - questionnaire.getFlowControl().addAll(referencedQuestionnaire.getFlowControl()); + new InsertFlowControls().apply(questionnaire, referencedQuestionnaire); log.info("FlowControl from '{}' inserted in '{}'", reference, id); // Update loops in referencing questionnaire if (questionnaire.getIterations() != null) { - for (IterationType iterationType : questionnaire.getIterations().getIteration()) { - updateIterationBounds(referencedQuestionnaire, iterationType); - } + new UpdateIterationBounds().apply(questionnaire, referencedQuestionnaire); log.info("Iterations' bounds updated in '{}' when de-referencing '{}'", id, reference); } // Add iterations (loops) Questionnaire.Iterations refIterations = referencedQuestionnaire.getIterations(); if (refIterations != null) { - questionnaire.setIterations(new Questionnaire.Iterations()); - questionnaire.getIterations().getIteration().addAll(refIterations.getIteration()); + new InsertIterations().apply(questionnaire, referencedQuestionnaire); log.info("Iterations from '{}' inserted in '{}'", reference, id); } else { log.info("No iterations in referenced questionnaire '{}'", reference); diff --git a/src/main/java/fr/insee/pogues/transforms/visualize/composition/FilterComposition.java b/src/main/java/fr/insee/pogues/transforms/visualize/composition/UpdateFlowControlBounds.java similarity index 64% rename from src/main/java/fr/insee/pogues/transforms/visualize/composition/FilterComposition.java rename to src/main/java/fr/insee/pogues/transforms/visualize/composition/UpdateFlowControlBounds.java index eeb59be1..34a3c495 100644 --- a/src/main/java/fr/insee/pogues/transforms/visualize/composition/FilterComposition.java +++ b/src/main/java/fr/insee/pogues/transforms/visualize/composition/UpdateFlowControlBounds.java @@ -1,5 +1,6 @@ package fr.insee.pogues.transforms.visualize.composition; +import fr.insee.pogues.exception.DeReferencingException; import fr.insee.pogues.exception.IllegalFlowControlException; import fr.insee.pogues.model.ComponentType; import fr.insee.pogues.model.FlowControlType; @@ -13,16 +14,30 @@ /** * Methods to insert and update FlowControl (filters) objects when de-referencing a questionnaire. */ -class FilterComposition { +class UpdateFlowControlBounds implements CompositionStep { - private FilterComposition() {} + @Override + public void apply(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) + throws DeReferencingException { + try { + for (FlowControlType flowControlType : questionnaire.getFlowControl()) { + updateFlowControlBounds(referencedQuestionnaire, flowControlType); + } + } catch (IllegalFlowControlException e) { + String message = String.format( + "Error when updating flow control bounds in questionnaire '%s' with reference '%s'", + questionnaire.getId(), referencedQuestionnaire.getId()); + throw new DeReferencingException(message, e); + } + + } /** Replace filter bounds that are reference a questionnaire by its first or last sequence. * @param referencedQuestionnaire Referenced questionnaire. * @param flowControlType The FlowControl object to be updated. * @throws IllegalFlowControlException If the FlowControl 'IfTrue' property doesn't match the format "id-id". */ - static void updateFlowControlBounds(Questionnaire referencedQuestionnaire, FlowControlType flowControlType) + private static void updateFlowControlBounds(Questionnaire referencedQuestionnaire, FlowControlType flowControlType) throws IllegalFlowControlException { // String reference = referencedQuestionnaire.getId(); diff --git a/src/main/java/fr/insee/pogues/transforms/visualize/composition/UpdateIterationBounds.java b/src/main/java/fr/insee/pogues/transforms/visualize/composition/UpdateIterationBounds.java new file mode 100644 index 00000000..2cd3504d --- /dev/null +++ b/src/main/java/fr/insee/pogues/transforms/visualize/composition/UpdateIterationBounds.java @@ -0,0 +1,55 @@ +package fr.insee.pogues.transforms.visualize.composition; + +import fr.insee.pogues.exception.DeReferencingException; +import fr.insee.pogues.exception.IllegalIterationException; +import fr.insee.pogues.model.ComponentType; +import fr.insee.pogues.model.IterationType; +import fr.insee.pogues.model.Questionnaire; + +import java.util.List; + +import static fr.insee.pogues.utils.PoguesModelUtils.getIterationBounds; +import static fr.insee.pogues.utils.PoguesModelUtils.getSequences; + +public class UpdateIterationBounds implements CompositionStep { + + @Override + public void apply(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) + throws DeReferencingException { + try { + for (IterationType iterationType : questionnaire.getIterations().getIteration()) { + updateIterationBounds(referencedQuestionnaire, iterationType); + } + } catch (IllegalIterationException e) { + String message = String.format( + "Error when updating iteration bounds in questionnaire '%s' with reference '%s'", + questionnaire.getId(), referencedQuestionnaire.getId()); + throw new DeReferencingException(message, e); + } + + } + + /** Replace loop bounds that reference a questionnaire by its first or last sequence. + * @param referencedQuestionnaire Referenced questionnaire. + * @param iterationType The Iteration object to be updated. + * @throws IllegalIterationException if the 'MemberReference' property in the iteration is invalid. + */ + static void updateIterationBounds(Questionnaire referencedQuestionnaire, IterationType iterationType) + throws IllegalIterationException { + // + String reference = referencedQuestionnaire.getId(); + // + List iterationBounds = getIterationBounds(iterationType); + // Replace questionnaire reference by its first/last sequence + String beginMember = iterationBounds.get(0); + String endMember = iterationBounds.get(1); + if (beginMember.equals(reference)) { + iterationBounds.set(0, referencedQuestionnaire.getChild().get(0).getId()); + } + if (endMember.equals(reference)) { + List referenceSequences = getSequences(referencedQuestionnaire); + iterationBounds.set(1, referenceSequences.get(referenceSequences.size() - 1).getId()); + } + } + +} diff --git a/src/main/java/fr/insee/pogues/transforms/visualize/composition/LoopComposition.java b/src/main/java/fr/insee/pogues/transforms/visualize/composition/UpdateReferencedVariablesScope.java similarity index 78% rename from src/main/java/fr/insee/pogues/transforms/visualize/composition/LoopComposition.java rename to src/main/java/fr/insee/pogues/transforms/visualize/composition/UpdateReferencedVariablesScope.java index f7c244ae..c8aff173 100644 --- a/src/main/java/fr/insee/pogues/transforms/visualize/composition/LoopComposition.java +++ b/src/main/java/fr/insee/pogues/transforms/visualize/composition/UpdateReferencedVariablesScope.java @@ -1,5 +1,6 @@ package fr.insee.pogues.transforms.visualize.composition; +import fr.insee.pogues.exception.DeReferencingException; import fr.insee.pogues.exception.IllegalIterationException; import fr.insee.pogues.model.*; import lombok.extern.slf4j.Slf4j; @@ -7,36 +8,20 @@ import java.util.List; import static fr.insee.pogues.utils.PoguesModelUtils.getIterationBounds; -import static fr.insee.pogues.utils.PoguesModelUtils.getSequences; -/** - * Methods to insert and update Iteration (loop) objects when de-referencing a questionnaire. - */ @Slf4j -class LoopComposition { +class UpdateReferencedVariablesScope implements CompositionStep { - private LoopComposition() {} - - /** Replace loop bounds that reference a questionnaire by its first or last sequence. - * @param referencedQuestionnaire Referenced questionnaire. - * @param iterationType The Iteration object to be updated. - * @throws IllegalIterationException if the 'MemberReference' property in the iteration is invalid. - */ - static void updateIterationBounds(Questionnaire referencedQuestionnaire, IterationType iterationType) - throws IllegalIterationException { - // - String reference = referencedQuestionnaire.getId(); - // - List iterationBounds = getIterationBounds(iterationType); - // Replace questionnaire reference by its first/last sequence - String beginMember = iterationBounds.get(0); - String endMember = iterationBounds.get(1); - if (beginMember.equals(reference)) { - iterationBounds.set(0, referencedQuestionnaire.getChild().get(0).getId()); - } - if (endMember.equals(reference)) { - List referenceSequences = getSequences(referencedQuestionnaire); - iterationBounds.set(1, referenceSequences.get(referenceSequences.size() - 1).getId()); + @Override + public void apply(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) + throws DeReferencingException { + try { + updateReferencedVariablesScope(questionnaire, referencedQuestionnaire); + } catch (IllegalIterationException e) { + String message = String.format( + "Error when updating referenced variables scope in questionnaire '%s' with reference '%s'", + questionnaire.getId(), referencedQuestionnaire.getId()); + throw new DeReferencingException(message, e); } } From 9bcb94614df354d30d55d2b6896e03a6843428d3 Mon Sep 17 00:00:00 2001 From: Nicolas Senave Date: Mon, 24 Apr 2023 18:42:36 +0200 Subject: [PATCH 02/12] refactor(composition): encapsulate steps further --- .../composition/InsertCodeLists.java | 13 +++++-- .../composition/InsertFlowControls.java | 3 ++ .../composition/InsertIterations.java | 12 +++++-- .../composition/InsertSequences.java | 2 ++ .../composition/InsertVariables.java | 3 ++ .../composition/QuestionnaireComposition.java | 34 ++++--------------- .../composition/UpdateFlowControlBounds.java | 4 +++ .../composition/UpdateIterationBounds.java | 23 ++++++++----- .../UpdateReferencedVariablesScope.java | 3 +- 9 files changed, 55 insertions(+), 42 deletions(-) diff --git a/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertCodeLists.java b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertCodeLists.java index 2a8a36b6..7e6e9f2e 100644 --- a/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertCodeLists.java +++ b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertCodeLists.java @@ -3,14 +3,23 @@ import fr.insee.pogues.exception.DeReferencingException; import fr.insee.pogues.model.CodeLists; import fr.insee.pogues.model.Questionnaire; +import lombok.extern.slf4j.Slf4j; +@Slf4j public class InsertCodeLists implements CompositionStep { @Override public void apply(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) throws DeReferencingException { - questionnaire.setCodeLists(new CodeLists()); - questionnaire.getCodeLists().getCodeList().addAll(referencedQuestionnaire.getCodeLists().getCodeList()); + CodeLists refCodeLists = referencedQuestionnaire.getCodeLists(); + if (refCodeLists != null) { + questionnaire.setCodeLists(new CodeLists()); + questionnaire.getCodeLists().getCodeList().addAll(refCodeLists.getCodeList()); + log.info("Code lists from '{}' inserted in '{}'", referencedQuestionnaire.getId(), questionnaire.getId()); + } else { + log.info("No code lists in referenced questionnaire '{}'", referencedQuestionnaire.getId()); + } + } } diff --git a/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertFlowControls.java b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertFlowControls.java index 64d1b4b2..f42204ad 100644 --- a/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertFlowControls.java +++ b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertFlowControls.java @@ -2,13 +2,16 @@ import fr.insee.pogues.exception.DeReferencingException; import fr.insee.pogues.model.Questionnaire; +import lombok.extern.slf4j.Slf4j; +@Slf4j public class InsertFlowControls implements CompositionStep { @Override public void apply(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) throws DeReferencingException { questionnaire.getFlowControl().addAll(referencedQuestionnaire.getFlowControl()); + log.info("FlowControl from '{}' inserted in '{}'", referencedQuestionnaire.getId(), questionnaire.getId()); } } diff --git a/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertIterations.java b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertIterations.java index af7b61b1..77af88a0 100644 --- a/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertIterations.java +++ b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertIterations.java @@ -2,14 +2,22 @@ import fr.insee.pogues.exception.DeReferencingException; import fr.insee.pogues.model.Questionnaire; +import lombok.extern.slf4j.Slf4j; +@Slf4j public class InsertIterations implements CompositionStep { @Override public void apply(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) throws DeReferencingException { - questionnaire.setIterations(new Questionnaire.Iterations()); - questionnaire.getIterations().getIteration().addAll(referencedQuestionnaire.getIterations().getIteration()); + Questionnaire.Iterations refIterations = referencedQuestionnaire.getIterations(); + if (refIterations != null) { + questionnaire.setIterations(new Questionnaire.Iterations()); + questionnaire.getIterations().getIteration().addAll(refIterations.getIteration()); + log.info("Iterations from '{}' inserted in '{}'", referencedQuestionnaire.getId(), questionnaire.getId()); + } else { + log.info("No iterations in referenced questionnaire '{}'", referencedQuestionnaire.getId()); + } } } diff --git a/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertSequences.java b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertSequences.java index 508adb2b..a99a7940 100644 --- a/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertSequences.java +++ b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertSequences.java @@ -39,6 +39,8 @@ public void apply(Questionnaire questionnaire, Questionnaire referencedQuestionn for (int i=0; i Date: Mon, 24 Apr 2023 18:54:49 +0200 Subject: [PATCH 03/12] refactor(composition): chained steps class --- .../composition/QuestionnaireComposition.java | 57 ++++++++++--------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/src/main/java/fr/insee/pogues/transforms/visualize/composition/QuestionnaireComposition.java b/src/main/java/fr/insee/pogues/transforms/visualize/composition/QuestionnaireComposition.java index 43532b1a..135d4ec5 100644 --- a/src/main/java/fr/insee/pogues/transforms/visualize/composition/QuestionnaireComposition.java +++ b/src/main/java/fr/insee/pogues/transforms/visualize/composition/QuestionnaireComposition.java @@ -9,8 +9,27 @@ public class QuestionnaireComposition { private QuestionnaireComposition() {} + static class DeReferencingPipeline { + Questionnaire questionnaire; + Questionnaire referencedQuestionnaire; + private DeReferencingPipeline(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) { + this.questionnaire = questionnaire; + this.referencedQuestionnaire = referencedQuestionnaire; + } + static DeReferencingPipeline start(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) { + log.info("Starting de-referencing of questionnaire '{}' in questionnaire '{}'", + referencedQuestionnaire.getId(), questionnaire.getId()); + return new DeReferencingPipeline(questionnaire, referencedQuestionnaire); + } + DeReferencingPipeline then(CompositionStep compositionStep) { + compositionStep.apply(questionnaire, referencedQuestionnaire); + return this; + } + } + /** * Replace referenced questionnaire by its component. Update elements that are impacted. + * Note: Component group is not updated since it is not used by eno generation. * @param questionnaire Referencing questionnaire. * @param referencedQuestionnaire Referenced questionnaire. * @throws DeReferencingException if an error occurs during de-referencing. @@ -18,34 +37,18 @@ private QuestionnaireComposition() {} public static void insertReference(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) throws DeReferencingException { // - log.info("Starting de-referencing of questionnaire '{}' in questionnaire '{}'", + DeReferencingPipeline.start(questionnaire, referencedQuestionnaire) + .then(new UpdateReferencedVariablesScope()) + .then(new InsertSequences()) + .then(new InsertVariables()) + .then(new InsertCodeLists()) + .then(new UpdateFlowControlBounds()) + .then(new InsertFlowControls()) + .then(new UpdateIterationBounds()) + .then(new InsertIterations()); + // + log.info("Finished de-referencing of questionnaire '{}' in questionnaire '{}'", referencedQuestionnaire.getId(), questionnaire.getId()); - - // Update the scope of the referenced questionnaire variables - new UpdateReferencedVariablesScope().apply(questionnaire, referencedQuestionnaire); - - // Add sequences - new InsertSequences().apply(questionnaire, referencedQuestionnaire); - - // Add variables - new InsertVariables().apply(questionnaire, referencedQuestionnaire); - - // Add code lists - new InsertCodeLists().apply(questionnaire, referencedQuestionnaire); - - // Update filters in referencing questionnaire - new UpdateFlowControlBounds().apply(questionnaire, referencedQuestionnaire); - - // Add flow controls (filters) - new InsertFlowControls().apply(questionnaire, referencedQuestionnaire); - - // Update loops in referencing questionnaire - new UpdateIterationBounds().apply(questionnaire, referencedQuestionnaire); - - // Add iterations (loops) - new InsertIterations().apply(questionnaire, referencedQuestionnaire); - - // Component group is not updated since it is not used by eno generation } } From 908e9698212de99a076b7ba64e9c11fb2cac8f77 Mon Sep 17 00:00:00 2001 From: Nicolas Senave Date: Tue, 25 Apr 2023 10:59:10 +0200 Subject: [PATCH 04/12] docs(composition): documentation for each step --- .../composition/CompositionStep.java | 1 + .../composition/InsertCodeLists.java | 14 +++++++---- .../composition/InsertFlowControls.java | 14 +++++++---- .../composition/InsertIterations.java | 14 +++++++---- .../composition/InsertSequences.java | 2 +- .../composition/InsertVariables.java | 8 +++++++ .../composition/QuestionnaireComposition.java | 23 ++++++++++++++++++- .../composition/UpdateFlowControlBounds.java | 9 +++++++- .../composition/UpdateIterationBounds.java | 12 +++++++++- .../UpdateReferencedVariablesScope.java | 20 ++++++++++++---- 10 files changed, 96 insertions(+), 21 deletions(-) diff --git a/src/main/java/fr/insee/pogues/transforms/visualize/composition/CompositionStep.java b/src/main/java/fr/insee/pogues/transforms/visualize/composition/CompositionStep.java index 0117fb19..8be1f25c 100644 --- a/src/main/java/fr/insee/pogues/transforms/visualize/composition/CompositionStep.java +++ b/src/main/java/fr/insee/pogues/transforms/visualize/composition/CompositionStep.java @@ -12,6 +12,7 @@ public interface CompositionStep { * Update questionnaire content with referenced questionnaire given. * @param questionnaire Referencing questionnaire. * @param referencedQuestionnaire Referenced questionnaire. + * @throws DeReferencingException if an error occurs during the de-referencing step. */ void apply(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) throws DeReferencingException; diff --git a/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertCodeLists.java b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertCodeLists.java index 7e6e9f2e..f6d6b370 100644 --- a/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertCodeLists.java +++ b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertCodeLists.java @@ -1,16 +1,22 @@ package fr.insee.pogues.transforms.visualize.composition; -import fr.insee.pogues.exception.DeReferencingException; import fr.insee.pogues.model.CodeLists; import fr.insee.pogues.model.Questionnaire; import lombok.extern.slf4j.Slf4j; +/** + * Implementation of CompositionStep to insert code lists of a referenced questionnaire. + */ @Slf4j -public class InsertCodeLists implements CompositionStep { +class InsertCodeLists implements CompositionStep { + /** + * Insert code lists of the referenced questionnaire in the referencing questionnaire. + * @param questionnaire Referencing questionnaire. + * @param referencedQuestionnaire Referenced questionnaire. + */ @Override - public void apply(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) - throws DeReferencingException { + public void apply(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) { CodeLists refCodeLists = referencedQuestionnaire.getCodeLists(); if (refCodeLists != null) { questionnaire.setCodeLists(new CodeLists()); diff --git a/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertFlowControls.java b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertFlowControls.java index f42204ad..bb57622e 100644 --- a/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertFlowControls.java +++ b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertFlowControls.java @@ -1,15 +1,21 @@ package fr.insee.pogues.transforms.visualize.composition; -import fr.insee.pogues.exception.DeReferencingException; import fr.insee.pogues.model.Questionnaire; import lombok.extern.slf4j.Slf4j; +/** + * Implementation of CompositionStep to insert flow controls of a referenced questionnaire. + */ @Slf4j -public class InsertFlowControls implements CompositionStep { +class InsertFlowControls implements CompositionStep { + /** + * Insert flow controls of the referenced questionnaire in the referencing questionnaire. + * @param questionnaire Referencing questionnaire. + * @param referencedQuestionnaire Referenced questionnaire. + */ @Override - public void apply(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) - throws DeReferencingException { + public void apply(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) { questionnaire.getFlowControl().addAll(referencedQuestionnaire.getFlowControl()); log.info("FlowControl from '{}' inserted in '{}'", referencedQuestionnaire.getId(), questionnaire.getId()); } diff --git a/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertIterations.java b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertIterations.java index 77af88a0..601f891e 100644 --- a/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertIterations.java +++ b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertIterations.java @@ -1,15 +1,21 @@ package fr.insee.pogues.transforms.visualize.composition; -import fr.insee.pogues.exception.DeReferencingException; import fr.insee.pogues.model.Questionnaire; import lombok.extern.slf4j.Slf4j; +/** + * Implementation of CompositionStep to insert iterations of a referenced questionnaire. + */ @Slf4j -public class InsertIterations implements CompositionStep { +class InsertIterations implements CompositionStep { + /** + * Insert iterations of the referenced questionnaire in the referencing questionnaire. + * @param questionnaire Referencing questionnaire. + * @param referencedQuestionnaire Referenced questionnaire. + */ @Override - public void apply(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) - throws DeReferencingException { + public void apply(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) { Questionnaire.Iterations refIterations = referencedQuestionnaire.getIterations(); if (refIterations != null) { questionnaire.setIterations(new Questionnaire.Iterations()); diff --git a/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertSequences.java b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertSequences.java index a99a7940..7183e39e 100644 --- a/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertSequences.java +++ b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertSequences.java @@ -10,7 +10,7 @@ import static fr.insee.pogues.utils.PoguesModelUtils.getSequences; /** - * Methods to insert and update sequence objects when de-referencing a questionnaire. + * Implementation of CompositionStep to replace questionnaire reference by its sequences. */ @Slf4j class InsertSequences implements CompositionStep { diff --git a/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertVariables.java b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertVariables.java index f20db9ee..6dc87f61 100644 --- a/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertVariables.java +++ b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertVariables.java @@ -4,9 +4,17 @@ import fr.insee.pogues.model.Questionnaire; import lombok.extern.slf4j.Slf4j; +/** + * Implementation of CompositionStep to insert variables of a referenced questionnaire. + */ @Slf4j class InsertVariables implements CompositionStep { + /** + * Insert variables of the referenced questionnaire in the referencing questionnaire. + * @param questionnaire Referencing questionnaire. + * @param referencedQuestionnaire Referenced questionnaire. + */ @Override public void apply(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) throws DeReferencingException { diff --git a/src/main/java/fr/insee/pogues/transforms/visualize/composition/QuestionnaireComposition.java b/src/main/java/fr/insee/pogues/transforms/visualize/composition/QuestionnaireComposition.java index 135d4ec5..9b644e37 100644 --- a/src/main/java/fr/insee/pogues/transforms/visualize/composition/QuestionnaireComposition.java +++ b/src/main/java/fr/insee/pogues/transforms/visualize/composition/QuestionnaireComposition.java @@ -4,11 +4,20 @@ import fr.insee.pogues.model.Questionnaire; import lombok.extern.slf4j.Slf4j; +/** + * Class for the composition feature. + * Contains the logic to de-reference a questionnaire that contains references. + * De-referencing consists in replacing questionnaire references by their content. + * Note: 'composition' and 'de-referencing' words are used interchangeably. + */ @Slf4j public class QuestionnaireComposition { private QuestionnaireComposition() {} + /** + * Inner class of the composition class designed to chain de-referencing steps. + */ static class DeReferencingPipeline { Questionnaire questionnaire; Questionnaire referencedQuestionnaire; @@ -16,12 +25,24 @@ private DeReferencingPipeline(Questionnaire questionnaire, Questionnaire referen this.questionnaire = questionnaire; this.referencedQuestionnaire = referencedQuestionnaire; } + + /** + * Return an instance of de-referencing pipeline. + * @param questionnaire Referencing questionnaire. + * @param referencedQuestionnaire Referenced questionnaire. + * @return A DeReferencingPipeline instance. + */ static DeReferencingPipeline start(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) { log.info("Starting de-referencing of questionnaire '{}' in questionnaire '{}'", referencedQuestionnaire.getId(), questionnaire.getId()); return new DeReferencingPipeline(questionnaire, referencedQuestionnaire); } - DeReferencingPipeline then(CompositionStep compositionStep) { + /** + * Applies the composition step processing given. This method can be chained. + * @param compositionStep An implementation of the CompositionStep interface. + * @return The DeReferencingPipeline instance. + */ + DeReferencingPipeline then(CompositionStep compositionStep) throws DeReferencingException { compositionStep.apply(questionnaire, referencedQuestionnaire); return this; } diff --git a/src/main/java/fr/insee/pogues/transforms/visualize/composition/UpdateFlowControlBounds.java b/src/main/java/fr/insee/pogues/transforms/visualize/composition/UpdateFlowControlBounds.java index dd532527..2bd2c7d4 100644 --- a/src/main/java/fr/insee/pogues/transforms/visualize/composition/UpdateFlowControlBounds.java +++ b/src/main/java/fr/insee/pogues/transforms/visualize/composition/UpdateFlowControlBounds.java @@ -13,11 +13,18 @@ import static fr.insee.pogues.utils.PoguesModelUtils.getSequences; /** - * Methods to insert and update FlowControl (filters) objects when de-referencing a questionnaire. + * Implementation of CompositionStep to update FlowControl (filters) objects when de-referencing a questionnaire. */ @Slf4j class UpdateFlowControlBounds implements CompositionStep { + /** + * Update flow controls of the referencing questionnaire: if a start/end member of a flow control is a referenced + * questionnaire, replace the reference id by the right element's id from the referenced questionnaire. + * @param questionnaire Referencing questionnaire. + * @param referencedQuestionnaire Referenced questionnaire. + * @throws DeReferencingException if an error occurs during flow controls update. + */ @Override public void apply(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) throws DeReferencingException { diff --git a/src/main/java/fr/insee/pogues/transforms/visualize/composition/UpdateIterationBounds.java b/src/main/java/fr/insee/pogues/transforms/visualize/composition/UpdateIterationBounds.java index 17197a43..b9f2f4d3 100644 --- a/src/main/java/fr/insee/pogues/transforms/visualize/composition/UpdateIterationBounds.java +++ b/src/main/java/fr/insee/pogues/transforms/visualize/composition/UpdateIterationBounds.java @@ -12,9 +12,19 @@ import static fr.insee.pogues.utils.PoguesModelUtils.getIterationBounds; import static fr.insee.pogues.utils.PoguesModelUtils.getSequences; +/** + * Implementation of CompositionStep to update Iteration (loops) objects when de-referencing a questionnaire. + */ @Slf4j -public class UpdateIterationBounds implements CompositionStep { +class UpdateIterationBounds implements CompositionStep { + /** + * Update iterations of the referencing questionnaire: if a start/end member of an iteration is a referenced + * questionnaire, replace the reference id by the right element's id from the referenced questionnaire. + * @param questionnaire Referencing questionnaire. + * @param referencedQuestionnaire Referenced questionnaire. + * @throws DeReferencingException if an error occurs during iterations update. + */ @Override public void apply(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) throws DeReferencingException { diff --git a/src/main/java/fr/insee/pogues/transforms/visualize/composition/UpdateReferencedVariablesScope.java b/src/main/java/fr/insee/pogues/transforms/visualize/composition/UpdateReferencedVariablesScope.java index de1e1fb0..9dc434d0 100644 --- a/src/main/java/fr/insee/pogues/transforms/visualize/composition/UpdateReferencedVariablesScope.java +++ b/src/main/java/fr/insee/pogues/transforms/visualize/composition/UpdateReferencedVariablesScope.java @@ -9,9 +9,22 @@ import static fr.insee.pogues.utils.PoguesModelUtils.getIterationBounds; +/** + * Implementation of CompositionStep to update variable scopes when de-referencing a questionnaire. + */ @Slf4j class UpdateReferencedVariablesScope implements CompositionStep { + /** + * If the referenced questionnaire is in an iteration (loop) in referencing questionnaire, + * variables in referenced questionnaire that have null scope have to be updated. + * Warning: This must be done BEFORE replacing referenced questionnaire by its content. + * (Otherwise, we would have to scan every iteration and determine the variables in their scope, + * which would be much more complex.) + * @param questionnaire Referencing questionnaire. + * @param referencedQuestionnaire Referenced questionnaire. + * @throws DeReferencingException if an error occurs during variable scopes update. + */ @Override public void apply(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) throws DeReferencingException { @@ -27,11 +40,8 @@ public void apply(Questionnaire questionnaire, Questionnaire referencedQuestionn } /** - * If referenced questionnaire is in a loop in referencing questionnaire, - * variables in referenced questionnaire that have null scope have to be updated. - * Warning: This must be done BEFORE replacing referenced questionnaire by its content. - * Otherwise, we would have to scan every iteration and determine the variables in their scope, - * which would be much more complex. + * Iterate on iterations of the referencing questionnaire. + * For each iteration: update variables scope if the referenced questionnaire is in the scope of the iteration. * @param questionnaire Referencing questionnaire. * @param referencedQuestionnaire Referenced questionnaire. * @throws IllegalIterationException If the 'MemberReference' property is not of size 2 From 7d377b4384f968dd38b018152251756db1104da9 Mon Sep 17 00:00:00 2001 From: Nicolas Senave Date: Tue, 25 Apr 2023 12:00:49 +0200 Subject: [PATCH 05/12] refactor(composition): refactor unit tests --- .../exception/DeReferencingException.java | 2 +- .../composition/InsertSequences.java | 3 +- .../composition/InsertVariables.java | 3 +- .../composition/InsertIterationsTest.java | 44 +++++++++++ .../composition/InsertSequencesTest.java | 34 +++++++++ .../composition/InsertVariablesTest.java | 36 +++++++++ .../QuestionnaireCompositionTest.java | 73 ++++--------------- 7 files changed, 130 insertions(+), 65 deletions(-) create mode 100644 src/test/java/fr/insee/pogues/transforms/visualize/composition/InsertIterationsTest.java create mode 100644 src/test/java/fr/insee/pogues/transforms/visualize/composition/InsertSequencesTest.java create mode 100644 src/test/java/fr/insee/pogues/transforms/visualize/composition/InsertVariablesTest.java diff --git a/src/main/java/fr/insee/pogues/exception/DeReferencingException.java b/src/main/java/fr/insee/pogues/exception/DeReferencingException.java index 2d291a66..b109d3bb 100644 --- a/src/main/java/fr/insee/pogues/exception/DeReferencingException.java +++ b/src/main/java/fr/insee/pogues/exception/DeReferencingException.java @@ -3,7 +3,7 @@ /** * Exception thrown if an error occurs during questionnaire de-referencing (composition feature). */ -public class DeReferencingException extends RuntimeException { +public class DeReferencingException extends Exception { public DeReferencingException(String message, Exception e) { super(message, e); diff --git a/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertSequences.java b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertSequences.java index 7183e39e..ab68176e 100644 --- a/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertSequences.java +++ b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertSequences.java @@ -21,8 +21,7 @@ class InsertSequences implements CompositionStep { * @param referencedQuestionnaire Referenced questionnaire. */ @Override - public void apply(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) - throws DeReferencingException { + public void apply(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) { // List refSequences = getSequences(referencedQuestionnaire); int indexOfModification = 0; diff --git a/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertVariables.java b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertVariables.java index 6dc87f61..c2ec7687 100644 --- a/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertVariables.java +++ b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertVariables.java @@ -16,8 +16,7 @@ class InsertVariables implements CompositionStep { * @param referencedQuestionnaire Referenced questionnaire. */ @Override - public void apply(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) - throws DeReferencingException { + public void apply(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) { questionnaire.getVariables().getVariable().addAll(referencedQuestionnaire.getVariables().getVariable()); log.info("Variables from '{}' inserted in '{}'", referencedQuestionnaire.getId(), questionnaire.getId()); } diff --git a/src/test/java/fr/insee/pogues/transforms/visualize/composition/InsertIterationsTest.java b/src/test/java/fr/insee/pogues/transforms/visualize/composition/InsertIterationsTest.java new file mode 100644 index 00000000..a6c24e02 --- /dev/null +++ b/src/test/java/fr/insee/pogues/transforms/visualize/composition/InsertIterationsTest.java @@ -0,0 +1,44 @@ +package fr.insee.pogues.transforms.visualize.composition; + +import fr.insee.pogues.model.DynamicIterationType; +import fr.insee.pogues.model.IterationType; +import fr.insee.pogues.model.Questionnaire; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class InsertIterationsTest { + + private final Questionnaire questionnaire = new Questionnaire(); + private final Questionnaire referenced1 = new Questionnaire(); + private final Questionnaire referenced2 = new Questionnaire(); + + @BeforeEach + public void createQuestionnaires() { + QuestionnaireCompositionTest.questionnairesContent(questionnaire, referenced1, referenced2); + } + + @Test + void insertReference_loopInReferenced() { + // + IterationType iteration = new DynamicIterationType(); + iteration.setId("loop11"); + iteration.getMemberReference().add("seq11"); // begin member + iteration.getMemberReference().add("seq11"); // end member + referenced1.setIterations(new Questionnaire.Iterations()); + referenced1.getIterations().getIteration().add(iteration); + // + assertNull(questionnaire.getIterations()); + // + InsertIterations insertIterations = new InsertIterations(); + insertIterations.apply(questionnaire, referenced1); + // + assertNotNull(questionnaire.getIterations()); + assertFalse(questionnaire.getIterations().getIteration().isEmpty()); + assertEquals("loop11", questionnaire.getIterations().getIteration().get(0).getId()); + assertEquals("seq11", questionnaire.getIterations().getIteration().get(0).getMemberReference().get(0)); + assertEquals("seq11", questionnaire.getIterations().getIteration().get(0).getMemberReference().get(1)); + } + +} diff --git a/src/test/java/fr/insee/pogues/transforms/visualize/composition/InsertSequencesTest.java b/src/test/java/fr/insee/pogues/transforms/visualize/composition/InsertSequencesTest.java new file mode 100644 index 00000000..8d635192 --- /dev/null +++ b/src/test/java/fr/insee/pogues/transforms/visualize/composition/InsertSequencesTest.java @@ -0,0 +1,34 @@ +package fr.insee.pogues.transforms.visualize.composition; + +import fr.insee.pogues.model.Questionnaire; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class InsertSequencesTest { + + private final Questionnaire questionnaire = new Questionnaire(); + private final Questionnaire referenced1 = new Questionnaire(); + private final Questionnaire referenced2 = new Questionnaire(); + + @BeforeEach + public void createQuestionnaires() { + QuestionnaireCompositionTest.questionnairesContent(questionnaire, referenced1, referenced2); + } + + @Test + void insertReference_sequences() { + assertEquals("ref1", questionnaire.getChild().get(1).getId()); + assertEquals("ref2", questionnaire.getChild().get(2).getId()); + // + InsertSequences insertSequences = new InsertSequences(); + insertSequences.apply(questionnaire, referenced1); + insertSequences.apply(questionnaire, referenced2); + // + assertEquals("seq1", questionnaire.getChild().get(0).getId()); + assertEquals("seq11", questionnaire.getChild().get(1).getId()); + assertEquals("seq21", questionnaire.getChild().get(2).getId()); + } + +} diff --git a/src/test/java/fr/insee/pogues/transforms/visualize/composition/InsertVariablesTest.java b/src/test/java/fr/insee/pogues/transforms/visualize/composition/InsertVariablesTest.java new file mode 100644 index 00000000..3209ed0c --- /dev/null +++ b/src/test/java/fr/insee/pogues/transforms/visualize/composition/InsertVariablesTest.java @@ -0,0 +1,36 @@ +package fr.insee.pogues.transforms.visualize.composition; + +import fr.insee.pogues.model.ExternalVariableType; +import fr.insee.pogues.model.Questionnaire; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class InsertVariablesTest { + + private final Questionnaire questionnaire = new Questionnaire(); + private final Questionnaire referenced1 = new Questionnaire(); + private final Questionnaire referenced2 = new Questionnaire(); + + @BeforeEach + public void createQuestionnaires() { + QuestionnaireCompositionTest.questionnairesContent(questionnaire, referenced1, referenced2); + } + + @Test + void insertReference_variables() { + // + referenced1.getVariables().getVariable().add(new ExternalVariableType()); + referenced2.getVariables().getVariable().add(new ExternalVariableType()); + // + assertEquals(0, questionnaire.getVariables().getVariable().size()); + // + InsertVariables insertVariables = new InsertVariables(); + insertVariables.apply(questionnaire, referenced1); + insertVariables.apply(questionnaire, referenced2); + // + assertEquals(2, questionnaire.getVariables().getVariable().size()); + } + +} diff --git a/src/test/java/fr/insee/pogues/transforms/visualize/composition/QuestionnaireCompositionTest.java b/src/test/java/fr/insee/pogues/transforms/visualize/composition/QuestionnaireCompositionTest.java index 96eedb6c..d10ffad1 100644 --- a/src/test/java/fr/insee/pogues/transforms/visualize/composition/QuestionnaireCompositionTest.java +++ b/src/test/java/fr/insee/pogues/transforms/visualize/composition/QuestionnaireCompositionTest.java @@ -1,7 +1,6 @@ package fr.insee.pogues.transforms.visualize.composition; -import fr.insee.pogues.exception.IllegalFlowControlException; -import fr.insee.pogues.exception.IllegalIterationException; +import fr.insee.pogues.exception.DeReferencingException; import fr.insee.pogues.model.*; import fr.insee.pogues.utils.PoguesModelUtils; import org.junit.jupiter.api.BeforeEach; @@ -13,14 +12,9 @@ class QuestionnaireCompositionTest { - private Questionnaire questionnaire; - private Questionnaire referenced1; - private Questionnaire referenced2; - - @BeforeEach - public void createQuestionnaires() { + static void questionnairesContent( + Questionnaire questionnaire, Questionnaire referenced1, Questionnaire referenced2) { // - referenced1 = new Questionnaire(); referenced1.setId("ref1"); SequenceType sequence11 = new SequenceType(); sequence11.setId("seq11"); @@ -28,7 +22,6 @@ public void createQuestionnaires() { referenced1.getChild().add(sequence11); referenced1.setVariables(new Questionnaire.Variables()); // - referenced2 = new Questionnaire(); referenced2.setId("ref2"); SequenceType sequence21 = new SequenceType(); sequence21.setId("seq21"); @@ -36,7 +29,6 @@ public void createQuestionnaires() { referenced2.getChild().add(sequence21); referenced2.setVariables(new Questionnaire.Variables()); // - questionnaire = new Questionnaire(); questionnaire.setId("id"); SequenceType sequence1 = new SequenceType(); sequence1.setId("seq1"); @@ -54,56 +46,17 @@ public void createQuestionnaires() { questionnaire.setVariables(new Questionnaire.Variables()); } - @Test - void insertReference_sequences() throws IllegalIterationException, IllegalFlowControlException { - assertEquals("ref1", questionnaire.getChild().get(1).getId()); - assertEquals("ref2", questionnaire.getChild().get(2).getId()); - // - QuestionnaireComposition.insertReference(questionnaire, referenced1); - QuestionnaireComposition.insertReference(questionnaire, referenced2); - // - assertEquals("seq1", questionnaire.getChild().get(0).getId()); - assertEquals("seq11", questionnaire.getChild().get(1).getId()); - assertEquals("seq21", questionnaire.getChild().get(2).getId()); - } + private final Questionnaire questionnaire = new Questionnaire(); + private final Questionnaire referenced1 = new Questionnaire(); + private final Questionnaire referenced2 = new Questionnaire(); - @Test - void insertReference_variables() throws IllegalIterationException, IllegalFlowControlException { - // - referenced1.getVariables().getVariable().add(new ExternalVariableType()); - referenced2.getVariables().getVariable().add(new ExternalVariableType()); - // - assertEquals(0, questionnaire.getVariables().getVariable().size()); - // - QuestionnaireComposition.insertReference(questionnaire, referenced1); - QuestionnaireComposition.insertReference(questionnaire, referenced2); - // - assertEquals(2, questionnaire.getVariables().getVariable().size()); - } - - @Test - void insertReference_loopInReferenced() throws IllegalIterationException, IllegalFlowControlException { - // - IterationType iteration = new DynamicIterationType(); - iteration.setId("loop11"); - iteration.getMemberReference().add("seq11"); // begin member - iteration.getMemberReference().add("seq11"); // end member - referenced1.setIterations(new Questionnaire.Iterations()); - referenced1.getIterations().getIteration().add(iteration); - // - assertNull(questionnaire.getIterations()); - // - QuestionnaireComposition.insertReference(questionnaire, referenced1); - // - assertNotNull(questionnaire.getIterations()); - assertFalse(questionnaire.getIterations().getIteration().isEmpty()); - assertEquals("loop11", questionnaire.getIterations().getIteration().get(0).getId()); - assertEquals("seq11", questionnaire.getIterations().getIteration().get(0).getMemberReference().get(0)); - assertEquals("seq11", questionnaire.getIterations().getIteration().get(0).getMemberReference().get(1)); + @BeforeEach + public void createQuestionnaires() { + questionnairesContent(questionnaire, referenced1, referenced2); } @Test - void insertReference_loopOnReference() throws IllegalIterationException, IllegalFlowControlException { + void insertReference_loopOnReference() throws DeReferencingException { // IterationType iteration = new DynamicIterationType(); iteration.setId("loop1"); @@ -119,7 +72,7 @@ void insertReference_loopOnReference() throws IllegalIterationException, Illegal } @Test - void insertReference_referencedWithinLoop() throws IllegalIterationException, IllegalFlowControlException { + void insertReference_referencedWithinLoop() throws DeReferencingException { // Add second sequence in referenced SequenceType sequence12 = new SequenceType(); sequence12.setId("seq12"); @@ -141,7 +94,7 @@ void insertReference_referencedWithinLoop() throws IllegalIterationException, Il /** To make sure de-referencing doesn't affect loops that shouldn't be affected. */ @Test - void insertReference_referenceOutsideLoop() throws IllegalIterationException, IllegalFlowControlException { + void insertReference_referenceOutsideLoop() throws DeReferencingException { // questionnaire.setIterations(new Questionnaire.Iterations()); IterationType iteration1 = new DynamicIterationType(); @@ -164,7 +117,7 @@ void insertReference_referenceOutsideLoop() throws IllegalIterationException, Il } @Test - void insertReference_updateVariableScopes() throws IllegalIterationException, IllegalFlowControlException { + void insertReference_updateVariableScopes() throws DeReferencingException { // Add iteration on referenced 1 in referencing questionnaire IterationType iteration = new DynamicIterationType(); iteration.setId("loop1"); From b99eb84baae85f9bdc8f6d0f8e478b33e00da038 Mon Sep 17 00:00:00 2001 From: Nicolas Senave Date: Tue, 25 Apr 2023 14:38:42 +0200 Subject: [PATCH 06/12] test: typo --- .../visualize/composition/QuestionnaireCompositionTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/fr/insee/pogues/transforms/visualize/composition/QuestionnaireCompositionTest.java b/src/test/java/fr/insee/pogues/transforms/visualize/composition/QuestionnaireCompositionTest.java index d10ffad1..7835dab2 100644 --- a/src/test/java/fr/insee/pogues/transforms/visualize/composition/QuestionnaireCompositionTest.java +++ b/src/test/java/fr/insee/pogues/transforms/visualize/composition/QuestionnaireCompositionTest.java @@ -37,7 +37,7 @@ static void questionnairesContent( questionnaire.getChild().add(referenced1); questionnaire.getChild().add(referenced2); SequenceType sequence2 = new SequenceType(); - sequence2.setId("seq1"); + sequence2.setId("seq2"); sequence2.getChild().add(new QuestionType()); questionnaire.getChild().add(sequence2); SequenceType fakeEndSequence = new SequenceType(); From 969840f5b1b9a814a6e0095a0f95a6c46853beb4 Mon Sep 17 00:00:00 2001 From: Nicolas Senave Date: Tue, 25 Apr 2023 14:39:05 +0200 Subject: [PATCH 07/12] test(composition): add some unit tests --- .../composition/InsertFlowControlsTest.java | 39 ++++++++++++++++++ .../UpdateFlowControlBoundsTest.java | 41 +++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 src/test/java/fr/insee/pogues/transforms/visualize/composition/InsertFlowControlsTest.java create mode 100644 src/test/java/fr/insee/pogues/transforms/visualize/composition/UpdateFlowControlBoundsTest.java diff --git a/src/test/java/fr/insee/pogues/transforms/visualize/composition/InsertFlowControlsTest.java b/src/test/java/fr/insee/pogues/transforms/visualize/composition/InsertFlowControlsTest.java new file mode 100644 index 00000000..761d2b2d --- /dev/null +++ b/src/test/java/fr/insee/pogues/transforms/visualize/composition/InsertFlowControlsTest.java @@ -0,0 +1,39 @@ +package fr.insee.pogues.transforms.visualize.composition; + +import fr.insee.pogues.model.FlowControlType; +import fr.insee.pogues.model.Questionnaire; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class InsertFlowControlsTest { + + private final Questionnaire questionnaire = new Questionnaire(); + private final Questionnaire referenced1 = new Questionnaire(); + private final Questionnaire referenced2 = new Questionnaire(); + + @BeforeEach + public void createQuestionnaires() { + QuestionnaireCompositionTest.questionnairesContent(questionnaire, referenced1, referenced2); + } + + @Test + void insertReference_loopInReferenced() { + // + FlowControlType flowControlType = new FlowControlType(); + flowControlType.setId("filter11"); + flowControlType.setIfTrue("seq11-seq11"); // begin-end member + referenced1.getFlowControl().add(flowControlType); + // + assertTrue(questionnaire.getFlowControl().isEmpty()); + // + InsertFlowControls insertFlowControls = new InsertFlowControls(); + insertFlowControls.apply(questionnaire, referenced1); + // + assertFalse(questionnaire.getFlowControl().isEmpty()); + assertEquals("filter11", questionnaire.getFlowControl().get(0).getId()); + assertEquals("seq11-seq11", questionnaire.getFlowControl().get(0).getIfTrue()); + } + +} diff --git a/src/test/java/fr/insee/pogues/transforms/visualize/composition/UpdateFlowControlBoundsTest.java b/src/test/java/fr/insee/pogues/transforms/visualize/composition/UpdateFlowControlBoundsTest.java new file mode 100644 index 00000000..1b1282c1 --- /dev/null +++ b/src/test/java/fr/insee/pogues/transforms/visualize/composition/UpdateFlowControlBoundsTest.java @@ -0,0 +1,41 @@ +package fr.insee.pogues.transforms.visualize.composition; + +import fr.insee.pogues.exception.DeReferencingException; +import fr.insee.pogues.model.FlowControlType; +import fr.insee.pogues.model.Questionnaire; +import fr.insee.pogues.model.SequenceType; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class UpdateFlowControlBoundsTest { + + private final Questionnaire questionnaire = new Questionnaire(); + private final Questionnaire referenced1 = new Questionnaire(); + private final Questionnaire referenced2 = new Questionnaire(); + + @BeforeEach + public void createQuestionnaires() { + QuestionnaireCompositionTest.questionnairesContent(questionnaire, referenced1, referenced2); + } + + @Test + void endMemberIsReferencedQuestionnaire() throws DeReferencingException { + // + FlowControlType flowControlType = new FlowControlType(); + flowControlType.setId("filter1"); + flowControlType.setIfTrue("seq1-ref1"); + questionnaire.getFlowControl().add(flowControlType); + // + SequenceType sequence12 = new SequenceType(); + sequence12.setId("seq12"); + referenced1.getChild().add(sequence12); + // + UpdateFlowControlBounds updateFlowControlBounds = new UpdateFlowControlBounds(); + updateFlowControlBounds.apply(questionnaire, referenced1); + // + assertEquals("seq1-seq12", questionnaire.getFlowControl().get(0).getIfTrue()); + } + +} From 2fa499c5114576701eafa82fb810350c3005caf8 Mon Sep 17 00:00:00 2001 From: Nicolas Senave Date: Tue, 25 Apr 2023 16:30:34 +0200 Subject: [PATCH 08/12] test(variable service): to make sonar happier --- .../service/VariablesServiceImpl.java | 6 + .../service/VariablesServiceImplTest.java | 106 +++++ .../VariablesService/l4i3m6qa.json | 374 ++++++++++++++++++ 3 files changed, 486 insertions(+) create mode 100644 src/test/java/fr/insee/pogues/persistence/service/VariablesServiceImplTest.java create mode 100644 src/test/resources/persistence/VariablesService/l4i3m6qa.json diff --git a/src/main/java/fr/insee/pogues/persistence/service/VariablesServiceImpl.java b/src/main/java/fr/insee/pogues/persistence/service/VariablesServiceImpl.java index cdfeb264..7c182295 100644 --- a/src/main/java/fr/insee/pogues/persistence/service/VariablesServiceImpl.java +++ b/src/main/java/fr/insee/pogues/persistence/service/VariablesServiceImpl.java @@ -37,6 +37,12 @@ public class VariablesServiceImpl implements VariablesService { @Autowired private QuestionnairesServiceQuery questionnaireServiceQuery; + public VariablesServiceImpl() {} + + public VariablesServiceImpl(QuestionnairesServiceQuery questionnairesServiceQuery) { + this.questionnaireServiceQuery = questionnairesServiceQuery; + } + public JSONArray getVariablesByQuestionnaireForPublicEnemy(String id){ try { JSONObject questionnaire = questionnaireServiceQuery.getQuestionnaireByID(id); diff --git a/src/test/java/fr/insee/pogues/persistence/service/VariablesServiceImplTest.java b/src/test/java/fr/insee/pogues/persistence/service/VariablesServiceImplTest.java new file mode 100644 index 00000000..9347f3a1 --- /dev/null +++ b/src/test/java/fr/insee/pogues/persistence/service/VariablesServiceImplTest.java @@ -0,0 +1,106 @@ +package fr.insee.pogues.persistence.service; + +import fr.insee.pogues.persistence.query.QuestionnairesServiceQuery; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +class VariablesServiceImplTest { + + @Test + void getVariables() throws Exception { + // Given + // Read tested questionnaire + URL url = this.getClass().getClassLoader().getResource( + "persistence/VariablesService/l4i3m6qa.json"); + assert url != null; + String stringQuestionnaire = Files.readString(Path.of(url.toURI())); + JSONObject jsonQuestionnaire = (JSONObject) new JSONParser().parse(stringQuestionnaire); + // Mock questionnaire service + QuestionnairesServiceQuery questionnairesServiceQuery = Mockito.mock(QuestionnairesServiceQuery.class); + Mockito.when(questionnairesServiceQuery.getQuestionnaireByID("l4i3m6qa")).thenReturn(jsonQuestionnaire); + + // When + VariablesServiceImpl variablesService = new VariablesServiceImpl(questionnairesServiceQuery); + String result = variablesService.getVariablesByQuestionnaire("l4i3m6qa"); + + // Then + // (quick and dirty tests, the implementation could be refactored to make it more easily testable) + assertNotNull(result); + assertNotEquals("", result); + // Input questionnaire contains all three types of variables, these should be in output + assertTrue(result.contains("CollectedVariableType")); + assertTrue(result.contains("CalculatedVariableType")); + assertTrue(result.contains("ExternalVariableType")); + // Variable names present in input questionnaire, these should be in output + List.of("CAT_VAR_COMP_1", "CAT_VAR_EXT_1", "CAT_Q1", "CAT_Q2", "CAT_Q21", "CAT_Q22", "CAT_Q23") + .forEach(variableName -> assertTrue(result.contains(variableName))); + } + + @Test + void getVariablesForPublicEnemy() throws Exception { + // Given + // Read tested questionnaire + URL url = this.getClass().getClassLoader().getResource( + "persistence/VariablesService/l4i3m6qa.json"); + assert url != null; + String stringQuestionnaire = Files.readString(Path.of(url.toURI())); + JSONObject jsonQuestionnaire = (JSONObject) new JSONParser().parse(stringQuestionnaire); + // Mock questionnaire service + QuestionnairesServiceQuery questionnairesServiceQuery = Mockito.mock(QuestionnairesServiceQuery.class); + Mockito.when(questionnairesServiceQuery.getQuestionnaireByID("l4i3m6qa")).thenReturn(jsonQuestionnaire); + + // When + VariablesServiceImpl variablesService = new VariablesServiceImpl(questionnairesServiceQuery); + JSONArray result = variablesService.getVariablesByQuestionnaireForPublicEnemy("l4i3m6qa"); + + // Then + assertNotNull(result); + assertEquals(7, result.size()); + } + + /** Custom exception with no stack trace (to not pollute log when running tests) to be used in mocking. */ + static class MockedException extends Exception { + public MockedException() { + super("Mocked exception.", null, true, false); + } + } + + @Test + void getVariables_exceptionDuringQuestionnaireQuery_shouldReturnNull() throws Exception { + // Given + QuestionnairesServiceQuery questionnairesServiceQuery = Mockito.mock(QuestionnairesServiceQuery.class); + Mockito.when(questionnairesServiceQuery.getQuestionnaireByID("foo-id")).thenThrow(new MockedException()); + + // When + VariablesServiceImpl variablesService = new VariablesServiceImpl(questionnairesServiceQuery); + String result = variablesService.getVariablesByQuestionnaire("foo-id"); + + // Then + assertNull(result); + } + + @Test + void getVariablesForPublicEnemy_exceptionDuringQuestionnaireQuery_shouldReturnNull() throws Exception { + // Given + QuestionnairesServiceQuery questionnairesServiceQuery = Mockito.mock(QuestionnairesServiceQuery.class); + Mockito.when(questionnairesServiceQuery.getQuestionnaireByID("foo-id")).thenThrow(new MockedException()); + + // When + VariablesServiceImpl variablesService = new VariablesServiceImpl(questionnairesServiceQuery); + JSONArray result = variablesService.getVariablesByQuestionnaireForPublicEnemy("foo-id"); + + // Then + assertNull(result); + } + +} diff --git a/src/test/resources/persistence/VariablesService/l4i3m6qa.json b/src/test/resources/persistence/VariablesService/l4i3m6qa.json new file mode 100644 index 00000000..e6e4bbda --- /dev/null +++ b/src/test/resources/persistence/VariablesService/l4i3m6qa.json @@ -0,0 +1,374 @@ +{ + "owner": "FAKEPERMISSION", + "FlowControl": [], + "ComponentGroup": [ + { + "MemberReference": [ + "l4i3a6ii", + "l4i3it38", + "l4i3b1na", + "l4i3w0p1", + "idendquest" + ], + "Label": [ + "Components for page 1" + ], + "id": "l4i3je0b", + "Name": "PAGE_1" + } + ], + "agency": "fr.insee", + "genericName": "QUESTIONNAIRE", + "Label": [ + "Catalogue" + ], + "childQuestionnaireRef": [], + "Name": "CATALOGUE", + "Variables": { + "Variable": [ + { + "Formula": "41 + 1", + "Label": "CAT_VAR_COMP_1", + "id": "l50tn9cp", + "type": "CalculatedVariableType", + "Name": "CAT_VAR_COMP_1", + "Datatype": { + "Maximum": "100", + "Minimum": "0", + "typeName": "NUMERIC", + "Unit": "", + "type": "NumericDatatypeType", + "Decimals": "" + } + }, + { + "Label": "CAT_VAR_EXT_1", + "id": "l7hn33xv", + "type": "ExternalVariableType", + "Name": "CAT_VAR_EXT_1", + "Datatype": { + "Maximum": "100", + "Minimum": "0", + "typeName": "NUMERIC", + "Unit": "", + "type": "NumericDatatypeType", + "Decimals": "" + } + }, + { + "Label": "CAT_Q1 label", + "id": "l4i3ae42", + "type": "CollectedVariableType", + "Name": "CAT_Q1", + "Datatype": { + "Pattern": "", + "typeName": "TEXT", + "type": "TextDatatypeType", + "MaxLength": 249 + } + }, + { + "Scope": "ldx9s262", + "Label": "1 - Netflix", + "id": "l4i3j8e1", + "type": "CollectedVariableType", + "Name": "CAT_Q21", + "Datatype": { + "typeName": "BOOLEAN", + "type": "BooleanDatatypeType" + } + }, + { + "Scope": "ldx9s262", + "Label": "2 - Canal+", + "id": "l4i3dbok", + "type": "CollectedVariableType", + "Name": "CAT_Q22", + "Datatype": { + "typeName": "BOOLEAN", + "type": "BooleanDatatypeType" + } + }, + { + "Scope": "ldx9s262", + "Label": "3 - Disnex+", + "id": "l4i3gycc", + "type": "CollectedVariableType", + "Name": "CAT_Q23", + "Datatype": { + "typeName": "BOOLEAN", + "type": "BooleanDatatypeType" + } + }, + { + "Scope": "ldx9s262", + "Label": "4 - Prime", + "id": "l4i3ikfy", + "type": "CollectedVariableType", + "Name": "CAT_Q24", + "Datatype": { + "typeName": "BOOLEAN", + "type": "BooleanDatatypeType" + } + } + ] + }, + "lastUpdatedDate": "Mon Mar 27 2023 16:19:04 GMT+0200 (heure d’été d’Europe centrale)", + "DataCollection": [ + { + "id": "esa-dc-2018", + "uri": "http://ddi:fr.insee:DataCollection.esa-dc-2018" + } + ], + "final": false, + "flowLogic": "FILTER", + "id": "l4i3m6qa", + "TargetMode": [ + "CAWI", + "PAPI", + "CATI", + "CAPI" + ], + "CodeLists": { + "CodeList": [ + { + "Label": "ABONNEMENTS", + "id": "l4i3ehzf", + "Code": [ + { + "Parent": "", + "Label": "Netflix", + "Value": 1 + }, + { + "Parent": "", + "Label": "Canal+", + "Value": 2 + }, + { + "Parent": "", + "Label": "Disnex+", + "Value": 3 + }, + { + "Parent": "", + "Label": "Prime", + "Value": 4 + } + ], + "Name": "" + } + ] + }, + "Iterations": { + "Iteration": [ + { + "Maximum": "2", + "Minimum": "2", + "MemberReference": [ + "l4i3b1na" + ], + "id": "ldx9s262", + "Step": "1", + "type": "DynamicIterationType", + "Name": "BOUCLE_REF" + } + ] + }, + "formulasLanguage": "VTL", + "Child": [ + { + "Control": [], + "depth": 1, + "FlowControl": [], + "genericName": "MODULE", + "Label": [ + "CAT_S1" + ], + "id": "l4i3a6ii", + "TargetMode": [ + "CAWI", + "PAPI", + "CATI", + "CAPI" + ], + "Declaration": [], + "type": "SequenceType", + "Child": [ + { + "Response": [ + { + "CollectedVariableReference": "l4i3ae42", + "id": "l4i3k2ed", + "mandatory": false, + "Datatype": { + "Pattern": "", + "typeName": "TEXT", + "type": "TextDatatypeType", + "MaxLength": 249 + } + } + ], + "Control": [], + "depth": 2, + "FlowControl": [], + "Label": [ + "\"CAT_Q1\"" + ], + "id": "l4i3it38", + "TargetMode": [ + "CAWI", + "PAPI", + "CATI", + "CAPI" + ], + "Declaration": [ + { + "declarationType": "HELP", + "Text": "\"With a twist\"", + "id": "l7fzaq2p", + "position": "AFTER_QUESTION_TEXT", + "DeclarationMode": [ + "CAWI", + "PAPI", + "CATI", + "CAPI" + ] + } + ], + "type": "QuestionType", + "questionType": "SIMPLE", + "Name": "CAT_Q1" + } + ], + "Name": "CAT_S1" + }, + { + "Control": [], + "depth": 1, + "FlowControl": [], + "genericName": "MODULE", + "Label": [ + "CAT_S2" + ], + "id": "l4i3b1na", + "TargetMode": [ + "CAWI", + "PAPI", + "CATI", + "CAPI" + ], + "Declaration": [], + "type": "SequenceType", + "Child": [ + { + "FlowControl": [], + "Label": [ + "\"CAT_Q2\"" + ], + "ResponseStructure": { + "Attribute": [], + "Mapping": [ + { + "MappingSource": "l4i3rxxm", + "MappingTarget": "1" + }, + { + "MappingSource": "l4i3lzwf", + "MappingTarget": "2" + }, + { + "MappingSource": "l4i3d9if", + "MappingTarget": "3" + }, + { + "MappingSource": "l4i3t95q", + "MappingTarget": "4" + } + ], + "Dimension": [ + { + "dimensionType": "PRIMARY", + "dynamic": "0", + "CodeListReference": "l4i3ehzf" + }, + { + "dimensionType": "MEASURE", + "dynamic": "0" + } + ] + }, + "type": "QuestionType", + "Name": "CAT_Q2", + "Response": [ + { + "CollectedVariableReference": "l4i3j8e1", + "id": "l4i3rxxm", + "Datatype": { + "typeName": "BOOLEAN", + "type": "BooleanDatatypeType" + } + }, + { + "CollectedVariableReference": "l4i3dbok", + "id": "l4i3lzwf", + "Datatype": { + "typeName": "BOOLEAN", + "type": "BooleanDatatypeType" + } + }, + { + "CollectedVariableReference": "l4i3gycc", + "id": "l4i3d9if", + "Datatype": { + "typeName": "BOOLEAN", + "type": "BooleanDatatypeType" + } + }, + { + "CollectedVariableReference": "l4i3ikfy", + "id": "l4i3t95q", + "Datatype": { + "typeName": "BOOLEAN", + "type": "BooleanDatatypeType" + } + } + ], + "Control": [], + "depth": 2, + "ClarificationQuestion": [], + "id": "l4i3w0p1", + "TargetMode": [ + "CAWI", + "PAPI", + "CATI", + "CAPI" + ], + "Declaration": [], + "questionType": "MULTIPLE_CHOICE" + } + ], + "Name": "CAT_S2" + }, + { + "Control": [], + "depth": 1, + "FlowControl": [], + "genericName": "MODULE", + "Label": [ + "QUESTIONNAIRE_END" + ], + "id": "idendquest", + "TargetMode": [ + "CAWI", + "PAPI", + "CATI", + "CAPI" + ], + "Declaration": [], + "type": "SequenceType", + "Child": [], + "Name": "QUESTIONNAIRE_END" + } + ] +} \ No newline at end of file From 133958a71c71f63ea206999ac79c0259e84029d7 Mon Sep 17 00:00:00 2001 From: Nicolas Senave Date: Thu, 27 Apr 2023 08:05:26 +0200 Subject: [PATCH 09/12] test(composition): unit test on code lists --- .../composition/InsertCodeListsTest.java | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/test/java/fr/insee/pogues/transforms/visualize/composition/InsertCodeListsTest.java diff --git a/src/test/java/fr/insee/pogues/transforms/visualize/composition/InsertCodeListsTest.java b/src/test/java/fr/insee/pogues/transforms/visualize/composition/InsertCodeListsTest.java new file mode 100644 index 00000000..14cbd0d2 --- /dev/null +++ b/src/test/java/fr/insee/pogues/transforms/visualize/composition/InsertCodeListsTest.java @@ -0,0 +1,40 @@ +package fr.insee.pogues.transforms.visualize.composition; + +import fr.insee.pogues.model.CodeList; +import fr.insee.pogues.model.CodeLists; +import fr.insee.pogues.model.Questionnaire; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class InsertCodeListsTest { + + private final Questionnaire questionnaire = new Questionnaire(); + private final Questionnaire referenced1 = new Questionnaire(); + private final Questionnaire referenced2 = new Questionnaire(); + + @BeforeEach + public void createQuestionnaires() { + QuestionnaireCompositionTest.questionnairesContent(questionnaire, referenced1, referenced2); + } + + @Test + void insertReference_codeLists() { + // + CodeList codeList = new CodeList(); + codeList.setId("codes11"); + referenced1.setCodeLists(new CodeLists()); + referenced1.getCodeLists().getCodeList().add(codeList); + // + assertNull(questionnaire.getCodeLists()); + // + InsertCodeLists insertCodeLists = new InsertCodeLists(); + insertCodeLists.apply(questionnaire, referenced1); + // + assertNotNull(questionnaire.getCodeLists()); + assertFalse(questionnaire.getCodeLists().getCodeList().isEmpty()); + assertEquals("codes11", questionnaire.getCodeLists().getCodeList().get(0).getId()); + } + +} From e53686820b68a2f2c3fa412c5608afcb80954c2d Mon Sep 17 00:00:00 2001 From: Nicolas Senave Date: Thu, 27 Apr 2023 10:00:57 +0200 Subject: [PATCH 10/12] fix(composition): add test for linked loops --- .../PoguesJSONToPoguesJSONDerefImplTest.java | 27 ++ .../linked_loop/lgyr1y6x_host.json | 319 ++++++++++++++++++ .../linked_loop/lgyr3utb_referenced.json | 289 ++++++++++++++++ 3 files changed, 635 insertions(+) create mode 100644 src/test/resources/transforms/PoguesJSONToPoguesJSONDeref/linked_loop/lgyr1y6x_host.json create mode 100644 src/test/resources/transforms/PoguesJSONToPoguesJSONDeref/linked_loop/lgyr3utb_referenced.json diff --git a/src/test/java/fr/insee/pogues/transforms/visualize/PoguesJSONToPoguesJSONDerefImplTest.java b/src/test/java/fr/insee/pogues/transforms/visualize/PoguesJSONToPoguesJSONDerefImplTest.java index f3a613e5..f57f7c5a 100644 --- a/src/test/java/fr/insee/pogues/transforms/visualize/PoguesJSONToPoguesJSONDerefImplTest.java +++ b/src/test/java/fr/insee/pogues/transforms/visualize/PoguesJSONToPoguesJSONDerefImplTest.java @@ -9,6 +9,7 @@ import fr.insee.pogues.utils.PoguesSerializer; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.mockito.Mockito; @@ -346,4 +347,30 @@ void dereference_twoReferences() throws Exception { }); } + @Test + @Disabled("Work in progress") + void dereference_linkedLoopIssue() throws Exception { + // Given + String folderName = "linked_loop"; + QuestionnairesService questionnairesService = mockQuestionnaireService( + folderName, + List.of("lgyr3utb_referenced.json"), + List.of("lgyr3utb")); + String testedInput = readQuestionnaire(folderName, "lgyr1y6x_host.json"); + + // When + PoguesJSONToPoguesJSONDerefImpl deref = new PoguesJSONToPoguesJSONDerefImpl(questionnairesService); + Questionnaire outQuestionnaire = deref.transformAsQuestionnaire(testedInput); + + // Then + assertNotNull(outQuestionnaire); + assertDoesNotThrow(() -> PoguesSerializer.questionnaireJavaToString(outQuestionnaire)); + // + assertEquals(2, outQuestionnaire.getIterations().getIteration().size()); + assertTrue(outQuestionnaire.getIterations().getIteration().stream() + .anyMatch(iterationType -> "LOOP".equals(iterationType.getName()))); + assertTrue(outQuestionnaire.getIterations().getIteration().stream() + .anyMatch(iterationType -> "LINKED_LOOP".equals(iterationType.getName()))); + } + } diff --git a/src/test/resources/transforms/PoguesJSONToPoguesJSONDeref/linked_loop/lgyr1y6x_host.json b/src/test/resources/transforms/PoguesJSONToPoguesJSONDeref/linked_loop/lgyr1y6x_host.json new file mode 100644 index 00000000..bcfc5d4a --- /dev/null +++ b/src/test/resources/transforms/PoguesJSONToPoguesJSONDeref/linked_loop/lgyr1y6x_host.json @@ -0,0 +1,319 @@ +{ + "owner": "FAKEPERMISSION", + "FlowControl": [], + "ComponentGroup": [ + { + "MemberReference": [ + "lgyrchd9", + "lgyr1smj", + "idendquest", + "lgyr3utb", + "lgyrfr5p", + "lgyrlyis", + "lgyrg0s1", + "lgyrgrx9" + ], + "Label": [ + "Components for page 1" + ], + "id": "lgyrhhm7", + "Name": "PAGE_1" + } + ], + "agency": "fr.insee", + "genericName": "QUESTIONNAIRE", + "Label": [ + "Issue Referenced Loop" + ], + "childQuestionnaireRef": [ + "lgyr3utb" + ], + "Name": "ISSUE_REF_LOOP", + "Variables": { + "Variable": [ + { + "Label": "QUESTION1 label", + "id": "lgyrkfo0", + "type": "CollectedVariableType", + "Name": "QUESTION1", + "Datatype": { + "Pattern": "", + "typeName": "TEXT", + "type": "TextDatatypeType", + "MaxLength": 249 + } + }, + { + "Scope": "lgyriqvg", + "Label": "QUESTION2 label", + "id": "lgyrkt28", + "type": "CollectedVariableType", + "Name": "QUESTION2", + "Datatype": { + "Pattern": "", + "typeName": "TEXT", + "type": "TextDatatypeType", + "MaxLength": 249 + } + }, + { + "Label": "QUSETION_LAST label", + "id": "lgys0cp9", + "type": "CollectedVariableType", + "Name": "QUSETION_LAST", + "Datatype": { + "Pattern": "", + "typeName": "TEXT", + "type": "TextDatatypeType", + "MaxLength": 249 + } + } + ] + }, + "lastUpdatedDate": "Thu Apr 27 2023 08:45:31 GMT+0200 (heure d’été d’Europe centrale)", + "DataCollection": [ + { + "id": "esa-dc-2018", + "uri": "http://ddi:fr.insee:DataCollection.esa-dc-2018", + "Name": "Enquête sectorielle annuelle 2018" + } + ], + "final": false, + "flowLogic": "FILTER", + "id": "lgyr1y6x", + "TargetMode": [ + "CAPI", + "CATI", + "CAWI", + "PAPI" + ], + "CodeLists": { + "CodeList": [] + }, + "Iterations": { + "Iteration": [ + { + "MemberReference": [ + "lgyrfr5p", + "lgyrfr5p" + ], + "id": "lgyrtkh8", + "type": "DynamicIterationType", + "Name": "LINKED_LOOP", + "IterableReference": "lgyriqvg" + } + ] + }, + "formulasLanguage": "VTL", + "Child": [ + { + "Control": [], + "depth": 1, + "FlowControl": [], + "genericName": "MODULE", + "Label": [ + "\"Sequence 1\"" + ], + "id": "lgyrchd9", + "TargetMode": [ + "CAPI", + "CATI", + "CAWI", + "PAPI" + ], + "Declaration": [], + "type": "SequenceType", + "Child": [ + { + "Response": [ + { + "CollectedVariableReference": "lgyrkfo0", + "id": "lgyrh1ne", + "mandatory": false, + "Datatype": { + "Pattern": "", + "typeName": "TEXT", + "type": "TextDatatypeType", + "MaxLength": 249 + } + } + ], + "Control": [], + "depth": 2, + "FlowControl": [], + "Label": [ + "\"Question 1\"" + ], + "id": "lgyr1smj", + "TargetMode": [ + "CAPI", + "CATI", + "CAWI", + "PAPI" + ], + "Declaration": [], + "type": "QuestionType", + "questionType": "SIMPLE", + "Name": "QUESTION1" + } + ], + "Name": "SEQUENCE1" + }, + { + "Control": [], + "depth": 1, + "FlowControl": [], + "genericName": "EXTERNAL_ELEMENT", + "Label": [ + "Reference with loop" + ], + "id": "lgyr3utb", + "TargetMode": [ + "" + ], + "Declaration": [], + "type": "SequenceType", + "Child": [], + "Name": "REF_WITH_LOOP" + }, + { + "Control": [], + "depth": 1, + "FlowControl": [], + "genericName": "MODULE", + "Label": [ + "\"Sequence with linked loop\"" + ], + "id": "lgyrfr5p", + "TargetMode": [ + "CAPI", + "CATI", + "CAWI", + "PAPI" + ], + "Declaration": [ + { + "declarationType": "HELP", + "Text": "\"The loop on this sequence is based on a loop that comes from a referenced questionnaire.\"", + "id": "lgyrlt0g", + "position": "AFTER_QUESTION_TEXT", + "DeclarationMode": [ + "CAPI", + "CATI", + "CAWI", + "PAPI" + ] + } + ], + "type": "SequenceType", + "Child": [ + { + "Response": [ + { + "CollectedVariableReference": "lgyrkt28", + "id": "lgys1e5c", + "mandatory": false, + "Datatype": { + "Pattern": "", + "typeName": "TEXT", + "type": "TextDatatypeType", + "MaxLength": 249 + } + } + ], + "Control": [], + "depth": 2, + "FlowControl": [], + "Label": [ + "\"Question 2\"" + ], + "id": "lgyrlyis", + "TargetMode": [ + "CAPI", + "CATI", + "CAWI", + "PAPI" + ], + "Declaration": [], + "type": "QuestionType", + "questionType": "SIMPLE", + "Name": "QUESTION2" + } + ], + "Name": "SEQ_LINKED_LOOP" + }, + { + "Control": [], + "depth": 1, + "FlowControl": [], + "genericName": "MODULE", + "Label": [ + "\"End sequence\"" + ], + "id": "lgyrg0s1", + "TargetMode": [ + "CAPI", + "CATI", + "CAWI", + "PAPI" + ], + "Declaration": [], + "type": "SequenceType", + "Child": [ + { + "Response": [ + { + "CollectedVariableReference": "lgys0cp9", + "id": "lgyrrrww", + "mandatory": false, + "Datatype": { + "Pattern": "", + "typeName": "TEXT", + "type": "TextDatatypeType", + "MaxLength": 249 + } + } + ], + "Control": [], + "depth": 2, + "FlowControl": [], + "Label": [ + "\"Last question\"" + ], + "id": "lgyrgrx9", + "TargetMode": [ + "CAPI", + "CATI", + "CAWI", + "PAPI" + ], + "Declaration": [], + "type": "QuestionType", + "questionType": "SIMPLE", + "Name": "QUSETION_LAST" + } + ], + "Name": "SEQ_END" + }, + { + "Control": [], + "depth": 1, + "FlowControl": [], + "genericName": "MODULE", + "Label": [ + "QUESTIONNAIRE_END" + ], + "id": "idendquest", + "TargetMode": [ + "CAPI", + "CATI", + "CAWI", + "PAPI" + ], + "Declaration": [], + "type": "SequenceType", + "Child": [], + "Name": "QUESTIONNAIRE_END" + } + ] +} \ No newline at end of file diff --git a/src/test/resources/transforms/PoguesJSONToPoguesJSONDeref/linked_loop/lgyr3utb_referenced.json b/src/test/resources/transforms/PoguesJSONToPoguesJSONDeref/linked_loop/lgyr3utb_referenced.json new file mode 100644 index 00000000..e83b74b4 --- /dev/null +++ b/src/test/resources/transforms/PoguesJSONToPoguesJSONDeref/linked_loop/lgyr3utb_referenced.json @@ -0,0 +1,289 @@ +{ + "owner": "FAKEPERMISSION", + "FlowControl": [], + "ComponentGroup": [ + { + "MemberReference": [ + "idendquest", + "lgyrd62v", + "lgyrnlm3", + "lgyr87p3", + "lgyrpxzv", + "lgyrpiip", + "lgyrgkez" + ], + "Label": [ + "Components for page 1" + ], + "id": "lgyrq5it", + "Name": "PAGE_1" + } + ], + "agency": "fr.insee", + "genericName": "QUESTIONNAIRE", + "Label": [ + "Reference with loop" + ], + "childQuestionnaireRef": [], + "Name": "REF_WITH_LOOP", + "Variables": { + "Variable": [ + { + "Label": "REF_Q1 label", + "id": "lgyr6g6b", + "type": "CollectedVariableType", + "Name": "REF_Q1", + "Datatype": { + "Pattern": "", + "typeName": "TEXT", + "type": "TextDatatypeType", + "MaxLength": 249 + } + }, + { + "Scope": "lgyriqvg", + "Label": "REF_Q2 label", + "id": "lgyrbjh3", + "type": "CollectedVariableType", + "Name": "REF_Q2", + "Datatype": { + "Pattern": "", + "typeName": "TEXT", + "type": "TextDatatypeType", + "MaxLength": 249 + } + }, + { + "Label": "REF_Q_LAST label", + "id": "lgyrdql4", + "type": "CollectedVariableType", + "Name": "REF_Q_LAST", + "Datatype": { + "Pattern": "", + "typeName": "TEXT", + "type": "TextDatatypeType", + "MaxLength": 249 + } + } + ] + }, + "lastUpdatedDate": "Thu Apr 27 2023 08:41:41 GMT+0200 (heure d’été d’Europe centrale)", + "DataCollection": [ + { + "id": "fpe-dc-2019", + "uri": "http://ddi:fr.insee:DataCollection.fpe-dc-2019", + "Name": "Enquête auprès des salariés de l’État 2019" + } + ], + "final": false, + "flowLogic": "FILTER", + "id": "lgyr3utb", + "TargetMode": [ + "CAPI", + "CATI", + "CAWI", + "PAPI" + ], + "CodeLists": { + "CodeList": [] + }, + "Iterations": { + "Iteration": [ + { + "Maximum": "5", + "Minimum": "1", + "MemberReference": [ + "lgyr87p3", + "lgyr87p3" + ], + "Label": "\"Add answer\"", + "id": "lgyriqvg", + "Step": "1", + "type": "DynamicIterationType", + "Name": "LOOP" + } + ] + }, + "formulasLanguage": "VTL", + "Child": [ + { + "Control": [], + "depth": 1, + "FlowControl": [], + "genericName": "MODULE", + "Label": [ + "\"Reference sequence 1\"" + ], + "id": "lgyrd62v", + "TargetMode": [ + "CAPI", + "CATI", + "CAWI", + "PAPI" + ], + "Declaration": [], + "type": "SequenceType", + "Child": [ + { + "Response": [ + { + "CollectedVariableReference": "lgyr6g6b", + "id": "lgyrhnmj", + "mandatory": false, + "Datatype": { + "Pattern": "", + "typeName": "TEXT", + "type": "TextDatatypeType", + "MaxLength": 249 + } + } + ], + "Control": [], + "depth": 2, + "FlowControl": [], + "Label": [ + "\"Reference question 1\"" + ], + "id": "lgyrnlm3", + "TargetMode": [ + "CAPI", + "CATI", + "CAWI", + "PAPI" + ], + "Declaration": [], + "type": "QuestionType", + "questionType": "SIMPLE", + "Name": "REF_Q1" + } + ], + "Name": "REF_SEQ1" + }, + { + "Control": [], + "depth": 1, + "FlowControl": [], + "genericName": "MODULE", + "Label": [ + "\"Sequence with loop\"" + ], + "id": "lgyr87p3", + "TargetMode": [ + "CAPI", + "CATI", + "CAWI", + "PAPI" + ], + "Declaration": [], + "type": "SequenceType", + "Child": [ + { + "Response": [ + { + "CollectedVariableReference": "lgyrbjh3", + "id": "lgyrw53y", + "mandatory": false, + "Datatype": { + "Pattern": "", + "typeName": "TEXT", + "type": "TextDatatypeType", + "MaxLength": 249 + } + } + ], + "Control": [], + "depth": 2, + "FlowControl": [], + "Label": [ + "\"Reference question 2\"" + ], + "id": "lgyrpxzv", + "TargetMode": [ + "CAPI", + "CATI", + "CAWI", + "PAPI" + ], + "Declaration": [], + "type": "QuestionType", + "questionType": "SIMPLE", + "Name": "REF_Q2" + } + ], + "Name": "REF_SEQ_LOOP" + }, + { + "Control": [], + "depth": 1, + "FlowControl": [], + "genericName": "MODULE", + "Label": [ + "\"Reference end sequence\"" + ], + "id": "lgyrpiip", + "TargetMode": [ + "CAPI", + "CATI", + "CAWI", + "PAPI" + ], + "Declaration": [], + "type": "SequenceType", + "Child": [ + { + "Response": [ + { + "CollectedVariableReference": "lgyrdql4", + "id": "lgyrvbwb", + "mandatory": false, + "Datatype": { + "Pattern": "", + "typeName": "TEXT", + "type": "TextDatatypeType", + "MaxLength": 249 + } + } + ], + "Control": [], + "depth": 2, + "FlowControl": [], + "Label": [ + "\"Reference last question\"" + ], + "id": "lgyrgkez", + "TargetMode": [ + "CAPI", + "CATI", + "CAWI", + "PAPI" + ], + "Declaration": [], + "type": "QuestionType", + "questionType": "SIMPLE", + "Name": "REF_Q_LAST" + } + ], + "Name": "REF_SEQ_END" + }, + { + "Control": [], + "depth": 1, + "FlowControl": [], + "genericName": "MODULE", + "Label": [ + "QUESTIONNAIRE_END" + ], + "id": "idendquest", + "TargetMode": [ + "CAPI", + "CATI", + "CAWI", + "PAPI" + ], + "Declaration": [], + "type": "SequenceType", + "Child": [], + "Name": "QUESTIONNAIRE_END" + } + ] +} \ No newline at end of file From d6a974c0a23ab64e3865b59eb4b05351ef93f669 Mon Sep 17 00:00:00 2001 From: Nicolas Senave Date: Thu, 27 Apr 2023 10:15:11 +0200 Subject: [PATCH 11/12] fix (composition): no longer empty host loops if not necessary --- .../composition/InsertIterations.java | 3 ++- .../PoguesJSONToPoguesJSONDerefImplTest.java | 18 +++++++++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertIterations.java b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertIterations.java index 601f891e..2791fbec 100644 --- a/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertIterations.java +++ b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertIterations.java @@ -18,7 +18,8 @@ class InsertIterations implements CompositionStep { public void apply(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) { Questionnaire.Iterations refIterations = referencedQuestionnaire.getIterations(); if (refIterations != null) { - questionnaire.setIterations(new Questionnaire.Iterations()); + if (questionnaire.getIterations() == null) + questionnaire.setIterations(new Questionnaire.Iterations()); questionnaire.getIterations().getIteration().addAll(refIterations.getIteration()); log.info("Iterations from '{}' inserted in '{}'", referencedQuestionnaire.getId(), questionnaire.getId()); } else { diff --git a/src/test/java/fr/insee/pogues/transforms/visualize/PoguesJSONToPoguesJSONDerefImplTest.java b/src/test/java/fr/insee/pogues/transforms/visualize/PoguesJSONToPoguesJSONDerefImplTest.java index f57f7c5a..af5da4b6 100644 --- a/src/test/java/fr/insee/pogues/transforms/visualize/PoguesJSONToPoguesJSONDerefImplTest.java +++ b/src/test/java/fr/insee/pogues/transforms/visualize/PoguesJSONToPoguesJSONDerefImplTest.java @@ -9,7 +9,6 @@ import fr.insee.pogues.utils.PoguesSerializer; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.mockito.Mockito; @@ -247,7 +246,7 @@ void dereference_updatedScopes() throws Exception { // ----- Using factorized code for the last tests ----- // private final static String TEST_FOLDER = "transforms/PoguesJSONToPoguesJSONDeref/"; - private final ClassLoader classLoader = this.getClass().getClassLoader();; + private final ClassLoader classLoader = this.getClass().getClassLoader(); private QuestionnairesService mockQuestionnaireService( String folderName, List referencedFileNames, List referenceIds) throws Exception { @@ -348,7 +347,6 @@ void dereference_twoReferences() throws Exception { } @Test - @Disabled("Work in progress") void dereference_linkedLoopIssue() throws Exception { // Given String folderName = "linked_loop"; @@ -367,10 +365,16 @@ void dereference_linkedLoopIssue() throws Exception { assertDoesNotThrow(() -> PoguesSerializer.questionnaireJavaToString(outQuestionnaire)); // assertEquals(2, outQuestionnaire.getIterations().getIteration().size()); - assertTrue(outQuestionnaire.getIterations().getIteration().stream() - .anyMatch(iterationType -> "LOOP".equals(iterationType.getName()))); - assertTrue(outQuestionnaire.getIterations().getIteration().stream() - .anyMatch(iterationType -> "LINKED_LOOP".equals(iterationType.getName()))); + // + Optional loop = outQuestionnaire.getIterations().getIteration().stream() + .filter(iterationType -> "LOOP".equals(iterationType.getName())) + .findFirst(); + Optional linkedLoop = outQuestionnaire.getIterations().getIteration().stream() + .filter(iterationType -> "LINKED_LOOP".equals(iterationType.getName())) + .findFirst(); + assertTrue(loop.isPresent()); + assertTrue(linkedLoop.isPresent()); + assertEquals(loop.get().getId(), ((DynamicIterationType) linkedLoop.get()).getIterableReference()); } } From 152173797d6fd4442d932d6c285615727c751192 Mon Sep 17 00:00:00 2001 From: Nicolas Senave Date: Thu, 27 Apr 2023 11:28:49 +0200 Subject: [PATCH 12/12] feat(composition): code lists with same names --- .../composition/InsertCodeLists.java | 33 ++++++++++++- .../composition/InsertCodeListsTest.java | 48 +++++++++++++++++++ 2 files changed, 79 insertions(+), 2 deletions(-) diff --git a/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertCodeLists.java b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertCodeLists.java index f6d6b370..3c8d3f39 100644 --- a/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertCodeLists.java +++ b/src/main/java/fr/insee/pogues/transforms/visualize/composition/InsertCodeLists.java @@ -4,28 +4,57 @@ import fr.insee.pogues.model.Questionnaire; import lombok.extern.slf4j.Slf4j; +import java.util.HashSet; +import java.util.Set; + /** * Implementation of CompositionStep to insert code lists of a referenced questionnaire. */ @Slf4j class InsertCodeLists implements CompositionStep { + /** Host questionnaire. */ + private Questionnaire questionnaire; + /** Host questionnaire code list names. */ + private final Set codeListNames = new HashSet<>(); + /** * Insert code lists of the referenced questionnaire in the referencing questionnaire. + * If a code list of the referenced questionnaire has the same name asa list in the referencing questionnaire, + * the code list is not added. * @param questionnaire Referencing questionnaire. * @param referencedQuestionnaire Referenced questionnaire. */ @Override public void apply(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) { + // + this.questionnaire = questionnaire; + // CodeLists refCodeLists = referencedQuestionnaire.getCodeLists(); if (refCodeLists != null) { - questionnaire.setCodeLists(new CodeLists()); - questionnaire.getCodeLists().getCodeList().addAll(refCodeLists.getCodeList()); + // + hostCodeLists(); + // + if (questionnaire.getCodeLists() == null) + questionnaire.setCodeLists(new CodeLists()); + // + refCodeLists.getCodeList().forEach(codeList -> { + if (! codeListNames.contains(codeList.getName())) + questionnaire.getCodeLists().getCodeList().add(codeList); + else + log.info("Code list with name '{}' is already in host questionnaire '{}', " + + "so it has not been inserted from reference '{}'", + codeList.getName(), questionnaire.getId(), referencedQuestionnaire.getId()); + }); log.info("Code lists from '{}' inserted in '{}'", referencedQuestionnaire.getId(), questionnaire.getId()); } else { log.info("No code lists in referenced questionnaire '{}'", referencedQuestionnaire.getId()); } + } + private void hostCodeLists() { + if (questionnaire.getCodeLists() != null) + questionnaire.getCodeLists().getCodeList().forEach(codeList -> codeListNames.add(codeList.getName())); } } diff --git a/src/test/java/fr/insee/pogues/transforms/visualize/composition/InsertCodeListsTest.java b/src/test/java/fr/insee/pogues/transforms/visualize/composition/InsertCodeListsTest.java index 14cbd0d2..1241ddef 100644 --- a/src/test/java/fr/insee/pogues/transforms/visualize/composition/InsertCodeListsTest.java +++ b/src/test/java/fr/insee/pogues/transforms/visualize/composition/InsertCodeListsTest.java @@ -37,4 +37,52 @@ void insertReference_codeLists() { assertEquals("codes11", questionnaire.getCodeLists().getCodeList().get(0).getId()); } + @Test + void insertCodeList_differentName() { + // + CodeList codeList = new CodeList(); + codeList.setId("codes1"); + codeList.setName("CODE_LIST_A"); + questionnaire.setCodeLists(new CodeLists()); + questionnaire.getCodeLists().getCodeList().add(codeList); + // + CodeList codeListRef = new CodeList(); + codeListRef.setId("codes11"); + codeListRef.setName("CODE_LIST_B"); + referenced1.setCodeLists(new CodeLists()); + referenced1.getCodeLists().getCodeList().add(codeListRef); + // + InsertCodeLists insertCodeLists = new InsertCodeLists(); + insertCodeLists.apply(questionnaire, referenced1); + // + assertNotNull(questionnaire.getCodeLists()); + assertFalse(questionnaire.getCodeLists().getCodeList().isEmpty()); + assertEquals(2, questionnaire.getCodeLists().getCodeList().size()); + } + + @Test + void insertCodeList_sameName() { + // + CodeList codeList = new CodeList(); + codeList.setId("codes1"); + codeList.setName("CODE_LIST_A"); + questionnaire.setCodeLists(new CodeLists()); + questionnaire.getCodeLists().getCodeList().add(codeList); + // + CodeList codeListRef = new CodeList(); + codeListRef.setId("codes11"); + codeListRef.setName("CODE_LIST_A"); + referenced1.setCodeLists(new CodeLists()); + referenced1.getCodeLists().getCodeList().add(codeListRef); + // + InsertCodeLists insertCodeLists = new InsertCodeLists(); + insertCodeLists.apply(questionnaire, referenced1); + // + assertNotNull(questionnaire.getCodeLists()); + assertFalse(questionnaire.getCodeLists().getCodeList().isEmpty()); + assertEquals(1, questionnaire.getCodeLists().getCodeList().size()); + + assertEquals("codes1", questionnaire.getCodeLists().getCodeList().get(0).getId()); + } + }