diff --git a/build.gradle.kts b/build.gradle.kts
index aa34ebb11..b1009be5d 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -16,7 +16,7 @@ java {
allprojects {
group = "fr.insee.eno"
- version = "3.26.4"
+ version = "3.27.0"
}
subprojects {
diff --git a/eno-core/src/main/java/fr/insee/eno/core/exceptions/business/InvalidSuggesterExpression.java b/eno-core/src/main/java/fr/insee/eno/core/exceptions/business/InvalidSuggesterExpression.java
new file mode 100644
index 000000000..91d2da7c2
--- /dev/null
+++ b/eno-core/src/main/java/fr/insee/eno/core/exceptions/business/InvalidSuggesterExpression.java
@@ -0,0 +1,13 @@
+package fr.insee.eno.core.exceptions.business;
+
+/**
+ * Exception to be thrown if the magic VTL expression (that uses a left join) used for suggester option responses
+ * is invalid.
+ */
+public class InvalidSuggesterExpression extends RuntimeException {
+
+ public InvalidSuggesterExpression(String message) {
+ super(message);
+ }
+
+}
diff --git a/eno-core/src/main/java/fr/insee/eno/core/processing/out/LunaticProcessing.java b/eno-core/src/main/java/fr/insee/eno/core/processing/out/LunaticProcessing.java
index 03b860155..a6436f7dd 100644
--- a/eno-core/src/main/java/fr/insee/eno/core/processing/out/LunaticProcessing.java
+++ b/eno-core/src/main/java/fr/insee/eno/core/processing/out/LunaticProcessing.java
@@ -44,6 +44,7 @@ public void applyProcessing(Questionnaire lunaticQuestionnaire, EnoQuestionnaire
.then(new LunaticEditLabelTypes()) // this step should be temporary
.then(new LunaticSuggestersConfiguration(enoQuestionnaire))
.then(new LunaticVariablesDimension(enoQuestionnaire))
+ .then(new LunaticSuggesterOptionResponses())
.thenIf(lunaticParameters.isMissingVariables(),
new LunaticAddMissingVariables(enoCatalog, lunaticParameters.isMissingVariables()))
.then(new LunaticAddResizing(enoQuestionnaire))
diff --git a/eno-core/src/main/java/fr/insee/eno/core/processing/out/steps/lunatic/LunaticSuggesterOptionResponses.java b/eno-core/src/main/java/fr/insee/eno/core/processing/out/steps/lunatic/LunaticSuggesterOptionResponses.java
new file mode 100644
index 000000000..956714aca
--- /dev/null
+++ b/eno-core/src/main/java/fr/insee/eno/core/processing/out/steps/lunatic/LunaticSuggesterOptionResponses.java
@@ -0,0 +1,196 @@
+package fr.insee.eno.core.processing.out.steps.lunatic;
+
+import fr.insee.eno.core.exceptions.business.InvalidSuggesterExpression;
+import fr.insee.eno.core.exceptions.technical.MappingException;
+import fr.insee.eno.core.processing.ProcessingStep;
+import fr.insee.eno.core.utils.VtlSyntaxUtils;
+import fr.insee.lunatic.model.flat.*;
+import fr.insee.lunatic.model.flat.variable.CalculatedVariableType;
+import fr.insee.lunatic.model.flat.variable.CollectedVariableType;
+import fr.insee.lunatic.model.flat.variable.CollectedVariableValues;
+import fr.insee.lunatic.model.flat.variable.VariableType;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * In Lunatic, when a respondent chooses an entry in a suggester field, multiple variables can be filled.
+ * These variables correspond to the different columns of the nomenclature used in the suggester.
+ * In DDI, these variables are represented as calculated variables with a "magic" expression using a VTL
+ * left join operator.
+ * Format of the magic expression:
+ * left_join(RESPONSE_NAME, NOMENCLATURE_NAME using ID_FIELD, OTHER_FIELD)
+ */
+@Slf4j
+public class LunaticSuggesterOptionResponses implements ProcessingStep {
+
+ // Feature is not designed in Pogues yet.
+ // This processing will probably have to be refactored when proper Pogues modeling is done.
+
+ /** Identifier field that must always be present in nomenclature fields. */
+ private static final String NOMENCLATURE_ID_FIELD = "id";
+
+ /**
+ * Record to store information contained in the "magic" suggester response expressions.
+ * Note: made package-private to be unit tested.
+ * @param responseName Main response of the suggester component.
+ * @param storeName "name" in suggesters at questionnaire level. "storeName" in components.
+ * @param idField Identifier field of the nomenclature.
+ * @param fieldName Field name to be associated with the calculated variable that holds the expression.
+ */
+ record SuggesterResponseExpression(
+ String responseName,
+ String storeName,
+ String idField,
+ String fieldName
+ ){}
+
+ /**
+ * Unpacks the given expression to return its pieces of information.
+ * Note: made package-private to be unit-tested.
+ * @param expression Magic expression of a suggester option response (that contains a left join).
+ * @return A record with the information held by the expression.
+ * @throws InvalidSuggesterExpression If the expression does not match the format "left_join(A, B using C, D)".
+ */
+ static SuggesterResponseExpression unpackSuggesterResponseExpression(String expression)
+ throws InvalidSuggesterExpression {
+ String content = expression.replace(VtlSyntaxUtils.LEFT_JOIN_OPERATOR, "");
+ content = content.replace("(", "");
+ content = content.replace(")", "");
+ String[] splitContent = content.split(",");
+ if (3 != splitContent.length)
+ throw new InvalidSuggesterExpression("Invalid usage of the left join operator.");
+ String[] splitContent2 = splitContent[1].split(VtlSyntaxUtils.USING_KEYWORD);
+ if (2 != splitContent2.length)
+ throw new InvalidSuggesterExpression("The 'using' keyword is missing or misplaced.");
+ String responseName = splitContent[0].trim();
+ String nomenclatureName = splitContent2[0].trim();
+ String nomenclatureId = splitContent2[1].trim();
+ String fieldName = splitContent[2].trim();
+ if (!NOMENCLATURE_ID_FIELD.equals(nomenclatureId))
+ log.warn("Nomenclature identifier field " + nomenclatureId + " is not equal to " + NOMENCLATURE_ID_FIELD + ".");
+ if (NOMENCLATURE_ID_FIELD.equals(fieldName))
+ log.warn("Identifier field used in an option response suggester expression.");
+ return new SuggesterResponseExpression(responseName, nomenclatureName, nomenclatureId, fieldName);
+ }
+
+ /**
+ * Transforms the calculated variable with the magic expression that uses a VTL left join into "optionResponses"
+ * of suggester components. Also creates corresponding collected variables, and removes these fake calculated ones.
+ * @param lunaticQuestionnaire Lunatic questionnaire.
+ */
+ @Override
+ public void apply(Questionnaire lunaticQuestionnaire) {
+ //
+ Map suggesterResponseExpressions = mapSuggesterResponseExpressions(lunaticQuestionnaire);
+ Map suggesterComponents = gatherSuggesterComponents(lunaticQuestionnaire);
+ //
+ suggesterResponseExpressions.keySet().forEach(optionResponseName -> {
+ SuggesterResponseExpression suggesterResponseExpression = suggesterResponseExpressions.get(optionResponseName);
+ Suggester suggester = suggesterComponents.get(suggesterResponseExpression.responseName());
+ suggester.getOptionResponses().add(new Suggester.OptionResponse(
+ optionResponseName, suggesterResponseExpression.fieldName()));
+ convertOptionResponseVariable(lunaticQuestionnaire, optionResponseName);
+ });
+ }
+
+ private Map gatherSuggesterComponents(Questionnaire lunaticQuestionnaire) {
+ Map suggesterComponents = new HashMap<>();
+ putSuggesterComponents(suggesterComponents, lunaticQuestionnaire.getComponents());
+ return suggesterComponents;
+ }
+ private void putSuggesterComponents(Map suggesterComponents, List lunaticComponents) {
+ lunaticComponents.forEach(component -> {
+ if (component instanceof Suggester suggester){
+ ResponseType suggesterResponse = suggester.getResponse();
+ if (suggesterResponse == null)
+ throw new MappingException("Suggester '" + suggester.getId() + "' has no response.");
+ suggesterComponents.put(suggesterResponse.getName(), suggester);
+ }
+ if (component instanceof Loop loop)
+ putSuggesterComponents(suggesterComponents, loop.getComponents());
+ if (component instanceof Roundabout roundabout)
+ putSuggesterComponents(suggesterComponents, roundabout.getComponents());
+ });
+ }
+
+ /**
+ * Maps the information hold by calculated variables that have the magic expression for suggesters, and returns it
+ * in a map designed to make the link between a suggester component, one of its fields and the corresponding
+ * option response variable.
+ * @param lunaticQuestionnaire Lunatic questionnaire.
+ * @return A map of response name -> field name -> variable name.
+ */
+ private Map mapSuggesterResponseExpressions(Questionnaire lunaticQuestionnaire) {
+ Map result = new LinkedHashMap<>();
+ lunaticQuestionnaire.getVariables().stream()
+ .filter(CalculatedVariableType.class::isInstance)
+ .map(CalculatedVariableType.class::cast)
+ .filter(calculatedVariable -> {
+ try {
+ String editedExpression = calculatedVariable.getExpression().getValue()
+ .replace("\"", ""); // due to dirty workaround in Pogues
+ if (editedExpression.startsWith(VtlSyntaxUtils.LEFT_JOIN_OPERATOR)) {
+ calculatedVariable.getExpression().setValue(editedExpression);
+ return true;
+ }
+ return false;
+ } catch (NullPointerException e) {
+ throw new MappingException("Calculated variable '" + calculatedVariable.getName() + "' has no expression.");
+ }
+ })
+ .forEachOrdered(calculatedVariable -> {
+ String expression = calculatedVariable.getExpression().getValue();
+ try {
+ SuggesterResponseExpression suggesterResponseExpression = unpackSuggesterResponseExpression(expression);
+ result.put(calculatedVariable.getName(), suggesterResponseExpression);
+ } catch (InvalidSuggesterExpression e) {
+ log.error("Invalid usage of the left join operator in calculated variable {}.",
+ calculatedVariable.getName());
+ throw e;
+ }
+ });
+ return result;
+ }
+
+ /**
+ * Transforms the calculated variables that correspond to the option responses of suggesters into collected
+ * variables.
+ * @param lunaticQuestionnaire Lunatic questionnaire.
+ * @param optionResponseName Name of the option response variable to be transformed from calculated into collected.
+ */
+ private void convertOptionResponseVariable(Questionnaire lunaticQuestionnaire, String optionResponseName) {
+ VariableType fakeVariable = removeVariable(lunaticQuestionnaire, optionResponseName);
+ if (fakeVariable == null) {
+ log.error("Unable to remove variable {} in lunatic questionnaire {}.",
+ optionResponseName, lunaticQuestionnaire.getId());
+ throw new InvalidSuggesterExpression(
+ "Error when converting suggester option response variable " + optionResponseName + ".");
+ }
+ CollectedVariableType suggesterOptionVariable = new CollectedVariableType();
+ suggesterOptionVariable.setName(fakeVariable.getName());
+ suggesterOptionVariable.setIterationReference(fakeVariable.getIterationReference());
+ suggesterOptionVariable.setDimension(fakeVariable.getDimension());
+ assert fakeVariable.getDimension() != null : "Dimension processing must be called first.";
+ switch (fakeVariable.getDimension()) {
+ case SCALAR -> suggesterOptionVariable.setValues(new CollectedVariableValues.Scalar());
+ case ARRAY -> suggesterOptionVariable.setValues(new CollectedVariableValues.Array());
+ case DOUBLE_ARRAY -> throw new InvalidSuggesterExpression(
+ "Suggester option variable " + optionResponseName + " has an invalid scope.");
+ }
+ lunaticQuestionnaire.getVariables().add(suggesterOptionVariable);
+ }
+ private VariableType removeVariable(Questionnaire lunaticQuestionnaire, String variableName) {
+ for (VariableType variable : lunaticQuestionnaire.getVariables()) {
+ if (variableName.equals(variable.getName())) {
+ lunaticQuestionnaire.getVariables().remove(variable);
+ return variable;
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/eno-core/src/main/java/fr/insee/eno/core/utils/VtlSyntaxUtils.java b/eno-core/src/main/java/fr/insee/eno/core/utils/VtlSyntaxUtils.java
index 0f5206d4a..819d3a1e8 100644
--- a/eno-core/src/main/java/fr/insee/eno/core/utils/VtlSyntaxUtils.java
+++ b/eno-core/src/main/java/fr/insee/eno/core/utils/VtlSyntaxUtils.java
@@ -5,6 +5,9 @@
*/
public class VtlSyntaxUtils {
+ public static final String LEFT_JOIN_OPERATOR = "left_join";
+ public static final String USING_KEYWORD = "using";
+
private VtlSyntaxUtils() {}
private static final String VTL_CONCATENATION_OPERATOR = "||";
diff --git a/eno-core/src/test/java/fr/insee/eno/core/processing/out/steps/lunatic/LunaticSuggesterOptionResponsesTest.java b/eno-core/src/test/java/fr/insee/eno/core/processing/out/steps/lunatic/LunaticSuggesterOptionResponsesTest.java
new file mode 100644
index 000000000..ce48192da
--- /dev/null
+++ b/eno-core/src/test/java/fr/insee/eno/core/processing/out/steps/lunatic/LunaticSuggesterOptionResponsesTest.java
@@ -0,0 +1,158 @@
+package fr.insee.eno.core.processing.out.steps.lunatic;
+
+import fr.insee.eno.core.DDIToEno;
+import fr.insee.eno.core.exceptions.business.DDIParsingException;
+import fr.insee.eno.core.exceptions.business.InvalidSuggesterExpression;
+import fr.insee.eno.core.mappers.LunaticMapper;
+import fr.insee.eno.core.model.EnoQuestionnaire;
+import fr.insee.eno.core.parameter.EnoParameters;
+import fr.insee.eno.core.parameter.Format;
+import fr.insee.eno.core.processing.out.steps.lunatic.LunaticSuggesterOptionResponses.SuggesterResponseExpression;
+import fr.insee.lunatic.model.flat.*;
+import fr.insee.lunatic.model.flat.variable.*;
+import org.junit.jupiter.api.Test;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static fr.insee.eno.core.processing.out.steps.lunatic.LunaticSuggesterOptionResponses.unpackSuggesterResponseExpression;
+import static org.junit.jupiter.api.Assertions.*;
+
+class LunaticSuggesterOptionResponsesTest {
+
+ @Test
+ void unpackExpressionTest() throws InvalidSuggesterExpression {
+ //
+ String testExpression = """
+ left_join(RESPONSE_NAME, NOMENCLATURE_NAME using id, ATTRIBUTE_NAME)""";
+ //
+ SuggesterResponseExpression result = unpackSuggesterResponseExpression(testExpression);
+ //
+ assertEquals("RESPONSE_NAME", result.responseName());
+ assertEquals("NOMENCLATURE_NAME", result.storeName());
+ assertEquals("id", result.idField());
+ assertEquals("ATTRIBUTE_NAME", result.fieldName());
+ }
+
+ @Test
+ void unitTest() {
+ // Given
+ Questionnaire lunaticQuestionnaire = new Questionnaire();
+ // Some collected variable
+ CollectedVariableType fooCollected = new CollectedVariableType();
+ fooCollected.setName("FOO_COLLECTED");
+ lunaticQuestionnaire.getVariables().add(fooCollected);
+ // Some external variable
+ lunaticQuestionnaire.getVariables().add(new ExternalVariableType());
+ // Some calculated variable
+ CalculatedVariableType fooCalculated = new CalculatedVariableType();
+ fooCalculated.setName("FOO_CALCULATED");
+ fooCalculated.setExpression(new LabelType());
+ fooCalculated.getExpression().setValue("");
+ lunaticQuestionnaire.getVariables().add(fooCalculated);
+ // Suggester component
+ Suggester suggester = new Suggester();
+ suggester.setResponse(new ResponseType());
+ suggester.getResponse().setName("CITY_ID");
+ lunaticQuestionnaire.getComponents().add(suggester);
+ CollectedVariableType suggesterResponseVariable = new CollectedVariableType();
+ suggesterResponseVariable.setName("CITY_ID");
+ suggesterResponseVariable.setDimension(VariableDimension.SCALAR);
+ suggesterResponseVariable.setValues(new CollectedVariableValues.Scalar());
+ lunaticQuestionnaire.getVariables().add(suggesterResponseVariable);
+ // Suggester option response variables
+ String expression1 = """
+ left_join(CITY_ID, CITY_CODE_LIST using id, label)""";
+ CalculatedVariableType suggesterResponseVariable1 = new CalculatedVariableType();
+ suggesterResponseVariable1.setName("CITY_LABEL");
+ suggesterResponseVariable1.setExpression(new LabelType());
+ suggesterResponseVariable1.getExpression().setValue(expression1);
+ suggesterResponseVariable1.setDimension(VariableDimension.SCALAR);
+ lunaticQuestionnaire.getVariables().add(suggesterResponseVariable1);
+ String expression2 = """
+ left_join(CITY_ID, CITY_CODE_LIST using id, code)""";
+ CalculatedVariableType suggesterResponseVariable2 = new CalculatedVariableType();
+ suggesterResponseVariable2.setName("CITY_CODE");
+ suggesterResponseVariable2.setExpression(new LabelType());
+ suggesterResponseVariable2.getExpression().setValue(expression2);
+ suggesterResponseVariable2.setDimension(VariableDimension.SCALAR);
+ lunaticQuestionnaire.getVariables().add(suggesterResponseVariable2);
+
+ // When
+ LunaticSuggesterOptionResponses processing = new LunaticSuggesterOptionResponses();
+ processing.apply(lunaticQuestionnaire);
+
+ // Then
+ assertEquals(2, suggester.getOptionResponses().size());
+ assertEquals("CITY_LABEL", suggester.getOptionResponses().get(0).name());
+ assertEquals("CITY_CODE", suggester.getOptionResponses().get(1).name());
+ assertEquals("label", suggester.getOptionResponses().get(0).attribute());
+ assertEquals("code", suggester.getOptionResponses().get(1).attribute());
+ //
+ assertEquals(1, lunaticQuestionnaire.getVariables().stream()
+ .filter(CalculatedVariableType.class::isInstance).count());
+ //
+ Map collectedVariables = new HashMap<>();
+ lunaticQuestionnaire.getVariables().stream()
+ .filter(CollectedVariableType.class::isInstance).map(CollectedVariableType.class::cast)
+ .forEach(collectedVariable -> collectedVariables.put(collectedVariable.getName(), collectedVariable));
+ assertEquals(Set.of("FOO_COLLECTED", "CITY_ID", "CITY_LABEL", "CITY_CODE"), collectedVariables.keySet());
+ collectedVariables.values().stream()
+ .filter(variable -> !"FOO_COLLECTED".equals(variable.getName()))
+ .forEach(collectedVariable -> {
+ assertEquals(VariableDimension.SCALAR, collectedVariable.getDimension());
+ assertInstanceOf(CollectedVariableValues.Scalar.class, collectedVariable.getValues());
+ });
+ }
+
+ @Test
+ void integrationTest() throws DDIParsingException {
+ //
+ EnoQuestionnaire enoQuestionnaire = DDIToEno.transform(
+ this.getClass().getClassLoader().getResourceAsStream("integration/ddi/ddi-suggester-options.xml"),
+ EnoParameters.of(EnoParameters.Context.DEFAULT, EnoParameters.ModeParameter.CAWI, Format.LUNATIC));
+ Questionnaire lunaticQuestionnaire = new Questionnaire();
+ new LunaticMapper().mapQuestionnaire(enoQuestionnaire, lunaticQuestionnaire);
+ new LunaticSortComponents(enoQuestionnaire).apply(lunaticQuestionnaire);
+ new LunaticLoopResolution(enoQuestionnaire).apply(lunaticQuestionnaire);
+ new LunaticVariablesDimension(enoQuestionnaire).apply(lunaticQuestionnaire);
+
+ //
+ new LunaticSuggesterOptionResponses().apply(lunaticQuestionnaire);
+
+ // Suggester components option responses
+ Suggester citySuggester1 = (Suggester) lunaticQuestionnaire.getComponents().get(1);
+ Suggester citySuggester2 = (Suggester) lunaticQuestionnaire.getComponents().get(2);
+ Suggester nationalitySuggester = (Suggester) lunaticQuestionnaire.getComponents().get(3);
+ Loop loop = (Loop) lunaticQuestionnaire.getComponents().get(4);
+ Suggester activitySuggester = (Suggester) loop.getComponents().get(1);
+ //
+ List.of(citySuggester1, citySuggester2, nationalitySuggester, activitySuggester).forEach(suggester -> {
+ assertEquals(1, suggester.getOptionResponses().size());
+ assertEquals("label", suggester.getOptionResponses().getFirst().attribute());
+ });
+ assertEquals("CITY_OF_BIRTH_LABEL", citySuggester1.getOptionResponses().getFirst().name());
+ assertEquals("CURRENT_CITY_LABEL", citySuggester2.getOptionResponses().getFirst().name());
+ assertEquals("NATIONALITY_LABEL", nationalitySuggester.getOptionResponses().getFirst().name());
+ assertEquals("ACTIVITY_LABEL", activitySuggester.getOptionResponses().getFirst().name());
+
+ // Corresponding variables
+ assertTrue(lunaticQuestionnaire.getVariables().stream().noneMatch(CalculatedVariableType.class::isInstance));
+ //
+ Map variables = new HashMap<>();
+ lunaticQuestionnaire.getVariables().forEach(variable ->
+ variables.put(variable.getName(), (CollectedVariableType) variable));
+ //
+ List.of("CITY_OF_BIRTH_LABEL", "CURRENT_CITY_LABEL", "NATIONALITY_LABEL").forEach(variableName -> {
+ assertNull(variables.get(variableName).getIterationReference());
+ assertEquals(VariableDimension.SCALAR, variables.get(variableName).getDimension());
+ assertInstanceOf(CollectedVariableValues.Scalar.class, variables.get(variableName).getValues());
+ });
+ assertEquals(loop.getId(), variables.get("ACTIVITY_LABEL").getIterationReference());
+ assertEquals(VariableDimension.ARRAY, variables.get("ACTIVITY_LABEL").getDimension());
+ assertInstanceOf(CollectedVariableValues.Array.class, variables.get("ACTIVITY_LABEL").getValues());
+ }
+
+}
diff --git a/eno-core/src/test/resources/integration/ddi/ddi-suggester-options.xml b/eno-core/src/test/resources/integration/ddi/ddi-suggester-options.xml
new file mode 100644
index 000000000..82085542e
--- /dev/null
+++ b/eno-core/src/test/resources/integration/ddi/ddi-suggester-options.xml
@@ -0,0 +1,1384 @@
+
+
+ fr.insee
+ INSEE-m16kx7hl
+ 1
+
+
+ Eno - Suggester multiple variables
+
+
+
+ fr.insee
+ RessourcePackage-m16kx7hl
+ 1
+
+ fr.insee
+ InterviewerInstructionScheme-m16kx7hl
+ 1
+
+ A définir
+
+
+
+ fr.insee
+ ControlConstructScheme-m16kx7hl
+ 1
+
+ fr.insee
+ Sequence-m16kx7hl
+ 1
+
+ Eno - Suggester multiple variables
+
+ template
+
+ fr.insee
+ m16kqzg7
+ 1
+ Sequence
+
+
+
+ fr.insee
+ m16kqzg7
+ 1
+
+ S1
+
+
+ "Sequence"
+
+ module
+
+ fr.insee
+ m16kjhib-QC
+ 1
+ QuestionConstruct
+
+
+ fr.insee
+ m1adj8d6-QC
+ 1
+ QuestionConstruct
+
+
+ fr.insee
+ m1ad9dyh-QC
+ 1
+ QuestionConstruct
+
+
+ fr.insee
+ m1ageurs
+ 1
+ Loop
+
+
+
+ fr.insee
+ m1ag6y3a
+ 1
+
+ SS1
+
+
+ "Sub-sequence"
+
+ submodule
+
+ fr.insee
+ m1ageu2g-QC
+ 1
+ QuestionConstruct
+
+
+
+ fr.insee
+ m1ageurs
+ 1
+
+ ACTIVITY_LOOP
+
+
+
+ vtl
+ 1
+
+
+
+
+ vtl
+ 10
+
+
+
+
+ vtl
+ 1
+
+
+
+ fr.insee
+ m1ageurs-SEQ
+ 1
+ Sequence
+
+
+
+ fr.insee
+ m1ageurs-SEQ
+ 1
+ loopContent
+
+ fr.insee
+ m1ag6y3a
+ 1
+ Sequence
+
+
+
+ fr.insee
+ m16kjhib-QC
+ 1
+
+ CITY_OF_BIRTH
+
+
+ fr.insee
+ m16kjhib
+ 1
+ QuestionItem
+
+
+
+ fr.insee
+ m1adj8d6-QC
+ 1
+
+ CURRENT_CITY
+
+
+ fr.insee
+ m1adj8d6
+ 1
+ QuestionItem
+
+
+
+ fr.insee
+ m1ad9dyh-QC
+ 1
+
+ NATIONALITY
+
+
+ fr.insee
+ m1ad9dyh
+ 1
+ QuestionItem
+
+
+
+ fr.insee
+ m1ageu2g-QC
+ 1
+
+ ACTIVITY
+
+
+ fr.insee
+ m1ageu2g
+ 1
+ QuestionItem
+
+
+
+
+ fr.insee
+ QuestionScheme-m16kx7hl
+ 1
+
+ A définir
+
+
+ fr.insee
+ m16kjhib
+ 1
+
+ CITY_OF_BIRTH
+
+
+ fr.insee
+ m16kjhib-QOP-m16kfwqf
+ 1
+
+ CITY_OF_BIRTH
+
+
+
+
+ fr.insee
+ m16kjhib-RDOP-m16kfwqf
+ 1
+ OutParameter
+
+
+ fr.insee
+ m16kjhib-QOP-m16kfwqf
+ 1
+ OutParameter
+
+
+
+
+ "City of birth"
+
+
+
+ suggester
+
+ fr.insee
+ L_COMMUNES-2024
+ 1
+ CodeList
+
+
+ fr.insee
+ m16kjhib-RDOP-m16kfwqf
+ 1
+
+
+ fr.insee
+ L_COMMUNES-2024
+ 1
+ CodeList
+
+
+
+
+
+
+
+ fr.insee
+ m1adj8d6
+ 1
+
+ CURRENT_CITY
+
+
+ fr.insee
+ m1adj8d6-QOP-m1adayn7
+ 1
+
+ CURRENT_CITY
+
+
+
+
+ fr.insee
+ m1adj8d6-RDOP-m1adayn7
+ 1
+ OutParameter
+
+
+ fr.insee
+ m1adj8d6-QOP-m1adayn7
+ 1
+ OutParameter
+
+
+
+
+ "Current city"
+
+
+
+ suggester
+
+ fr.insee
+ L_COMMUNES-2024
+ 1
+ CodeList
+
+
+ fr.insee
+ m1adj8d6-RDOP-m1adayn7
+ 1
+
+
+ fr.insee
+ L_COMMUNES-2024
+ 1
+ CodeList
+
+
+
+
+
+
+
+ fr.insee
+ m1ad9dyh
+ 1
+
+ NATIONALITY
+
+
+ fr.insee
+ m1ad9dyh-QOP-m1adexql
+ 1
+
+ NATIONALITY
+
+
+
+
+ fr.insee
+ m1ad9dyh-RDOP-m1adexql
+ 1
+ OutParameter
+
+
+ fr.insee
+ m1ad9dyh-QOP-m1adexql
+ 1
+ OutParameter
+
+
+
+
+ "Nationality"
+
+
+
+ suggester
+
+ fr.insee
+ L_NATIONALITE-1-2-0
+ 1
+ CodeList
+
+
+ fr.insee
+ m1ad9dyh-RDOP-m1adexql
+ 1
+
+
+ fr.insee
+ L_NATIONALITE-1-2-0
+ 1
+ CodeList
+
+
+
+
+
+
+
+ fr.insee
+ m1ageu2g
+ 1
+
+ ACTIVITY
+
+
+ fr.insee
+ m1ageu2g-QOP-m1ajfscg
+ 1
+
+ ACTIVITY
+
+
+
+
+ fr.insee
+ m1ageu2g-RDOP-m1ajfscg
+ 1
+ OutParameter
+
+
+ fr.insee
+ m1ageu2g-QOP-m1ajfscg
+ 1
+ OutParameter
+
+
+
+
+ "Activity"
+
+
+
+ suggester
+
+ fr.insee
+ L_ACTIVITES-2-0-0
+ 1
+ CodeList
+
+
+ fr.insee
+ m1ageu2g-RDOP-m1ajfscg
+ 1
+
+
+ fr.insee
+ L_ACTIVITES-2-0-0
+ 1
+ CodeList
+
+
+
+
+
+
+
+
+ fr.insee
+ CategoryScheme-m16kx7hl
+ 1
+
+ A définir
+
+
+ fr.insee
+ INSEE-COMMUN-CA-Booleen-1
+ 1
+
+
+
+
+
+
+ fr.insee
+ ENO_SUGGESTER_MULTI-CLS
+ 1
+
+ ENO_SUGGESTER_MULTI
+
+
+ fr.insee
+ L_COMMUNES-2024
+ 1
+
+ SuggesterConfiguration
+
+ label
+ [\w]+
+ French
+ 3
+ false
+
+
+ tokenized
+
+ French
+ 3
+ [\w.]+
+ false
+
+
+ 1]]>
+
+
+ L_COMMUNES-2024
+
+
+ Communes 2024
+
+
+ urn:ddi:fr.insee:l_communes-2024:1
+ CodeList
+
+ Regular
+
+ Ordinal
+
+
+
+ fr.insee
+ L_NATIONALITE-1-2-0
+ 1
+
+ SuggesterConfiguration
+
+ label
+ [\w]+
+ French
+ 3
+ false
+
+
+ tokenized
+
+ French
+ 3
+ [\w.]+
+ false
+
+
+ 1]]>
+
+
+ L_NATIONALITE-1-2-0
+
+
+ Nationalités
+
+
+ urn:ddi:fr.insee:l_nationalite-1-2-0:1
+ CodeList
+
+ Regular
+
+ Ordinal
+
+
+
+ fr.insee
+ L_ACTIVITES-2-0-0
+ 1
+
+ SuggesterConfiguration
+
+ label
+ [\w]+
+ French
+ 3
+ false
+
+
+ EPHAD
+ HEPAD
+ EPAD
+ EPAHD
+ EPADH
+
+
+
+ URSAF
+ URSAFF
+
+
+
+ ASCENCEUR
+ ASSENCEUR
+ ACSENCEUR
+
+
+
+ JOAILLIER
+
+
+
+ ALIMANTAIRE
+
+
+
+ BRIQUETTERIE
+
+
+
+ PRESTATAIRE
+
+
+
+ ALIMANTAIRES
+
+
+
+ ECHAFFAUDAGE
+ ECHAFFAUDEUR
+
+
+
+ PLACO
+ PLACOPLATRE
+
+
+
+ PNEUS
+
+
+
+ AGGROALIMANTAIRE
+ AGROALIMANTAIRE
+
+
+
+ AGGROALIMANTAIRES
+ AGROALIMENTAIRES
+
+
+ a
+ au
+ dans
+ de
+ des
+ du
+ en
+ et
+ la
+ le
+ ou
+ sur
+ d
+ l
+ aux
+ dans
+ un
+ une
+ pour
+ avec
+ chez
+ par
+ les
+
+ tokenized
+
+ French
+ 3
+ [\w.]+
+ false
+
+
+ 1]]>
+
+
+ L_ACTIVITES-2-0-0
+
+
+ Activités
+
+
+ urn:ddi:fr.insee:l_activites-2-0-0:1
+ CodeList
+
+ Regular
+
+ Ordinal
+
+
+
+ fr.insee
+ INSEE-COMMUN-CL-Booleen
+ 1
+
+ Booleen
+
+ Regular
+
+ Ordinal
+
+
+ fr.insee
+ INSEE-COMMUN-CL-Booleen-1
+ 1
+
+ fr.insee
+ INSEE-COMMUN-CA-Booleen-1
+ 1
+ Category
+
+ 1
+
+
+
+
+ fr.insee
+ VariableScheme-m16kx7hl
+ 1
+
+ Variable Scheme for the survey
+
+
+ fr.insee
+ m1agh821
+ 1
+
+ CITY_OF_BIRTH_LABEL
+
+
+ "City of birth label"
+
+
+ fr.insee
+ m1agh821-VROP
+ 1
+
+
+
+ fr.insee
+ m1agh821-GI
+ 1
+ GenerationInstruction
+
+
+ fr.insee
+ m1agh821-GOP
+ 1
+ OutParameter
+
+
+ fr.insee
+ m1agh821-VROP
+ 1
+ OutParameter
+
+
+
+
+
+
+
+ fr.insee
+ m1ajd442
+ 1
+
+ CURRENT_CITY_LABEL
+
+
+ "Current city label"
+
+
+ fr.insee
+ m1ajd442-VROP
+ 1
+
+
+
+ fr.insee
+ m1ajd442-GI
+ 1
+ GenerationInstruction
+
+
+ fr.insee
+ m1ajd442-GOP
+ 1
+ OutParameter
+
+
+ fr.insee
+ m1ajd442-VROP
+ 1
+ OutParameter
+
+
+
+
+
+
+
+ fr.insee
+ m1awka9n
+ 1
+
+ NATIONALITY_LABEL
+
+
+ "Nationality label"
+
+
+ fr.insee
+ m1awka9n-VROP
+ 1
+
+
+
+ fr.insee
+ m1awka9n-GI
+ 1
+ GenerationInstruction
+
+
+ fr.insee
+ m1awka9n-GOP
+ 1
+ OutParameter
+
+
+ fr.insee
+ m1awka9n-VROP
+ 1
+ OutParameter
+
+
+
+
+
+
+
+ fr.insee
+ m1awevi4
+ 1
+
+ ACTIVITY_LABEL
+
+
+ "Activity label"
+
+
+ fr.insee
+ m1awevi4-VROP
+ 1
+
+
+
+ fr.insee
+ m1awevi4-GI
+ 1
+ GenerationInstruction
+
+
+ fr.insee
+ m1awevi4-GOP
+ 1
+ OutParameter
+
+
+ fr.insee
+ m1awevi4-VROP
+ 1
+ OutParameter
+
+
+
+
+
+
+
+ fr.insee
+ m1acyc1z
+ 1
+
+ CITY_OF_BIRTH
+
+
+ CITY_OF_BIRTH label
+
+
+ fr.insee
+ m16kjhib-QOP-m16kfwqf
+ 1
+ OutParameter
+
+
+ fr.insee
+ m16kjhib
+ 1
+ QuestionItem
+
+
+
+
+ fr.insee
+ L_COMMUNES-2024
+ 1
+ CodeList
+
+
+
+
+
+ fr.insee
+ m1adjivd
+ 1
+
+ CURRENT_CITY
+
+
+ CURRENT_CITY label
+
+
+ fr.insee
+ m1adj8d6-QOP-m1adayn7
+ 1
+ OutParameter
+
+
+ fr.insee
+ m1adj8d6
+ 1
+ QuestionItem
+
+
+
+
+ fr.insee
+ L_COMMUNES-2024
+ 1
+ CodeList
+
+
+
+
+
+ fr.insee
+ m1adfh5f
+ 1
+
+ NATIONALITY
+
+
+ NATIONALITY label
+
+
+ fr.insee
+ m1ad9dyh-QOP-m1adexql
+ 1
+ OutParameter
+
+
+ fr.insee
+ m1ad9dyh
+ 1
+ QuestionItem
+
+
+
+
+ fr.insee
+ L_NATIONALITE-1-2-0
+ 1
+ CodeList
+
+
+
+
+
+ fr.insee
+ m1agq89j
+ 1
+
+ ACTIVITY
+
+
+ ACTIVITY label
+
+
+ fr.insee
+ m1ageu2g-QOP-m1ajfscg
+ 1
+ OutParameter
+
+
+ fr.insee
+ m1ageu2g
+ 1
+ QuestionItem
+
+
+
+
+ fr.insee
+ L_ACTIVITES-2-0-0
+ 1
+ CodeList
+
+
+
+
+
+ fr.insee
+ m1ageurs-vg
+ 1
+
+
+ fr.insee
+ m1ageurs
+ 1
+ Loop
+
+
+ Loop
+
+ ACTIVITY_LOOP
+
+
+ fr.insee
+ m1awevi4
+ 1
+ Variable
+
+
+ fr.insee
+ m1agq89j
+ 1
+ Variable
+
+
+
+ fr.insee
+ INSEE-Instrument-m16kx7hl-vg
+ 1
+
+
+ fr.insee
+ Instrument-m16kx7hl
+ 1
+ Instrument
+
+
+ Questionnaire
+
+ ENO_SUGGESTER_MULTI
+
+
+ fr.insee
+ m1agh821
+ 1
+ Variable
+
+
+ fr.insee
+ m1ajd442
+ 1
+ Variable
+
+
+ fr.insee
+ m1awka9n
+ 1
+ Variable
+
+
+ fr.insee
+ m1acyc1z
+ 1
+ Variable
+
+
+ fr.insee
+ m1adjivd
+ 1
+ Variable
+
+
+ fr.insee
+ m1adfh5f
+ 1
+ Variable
+
+
+ fr.insee
+ m1ageurs-vg
+ 1
+ VariableGroup
+
+
+
+
+ fr.insee
+ INSEE-SIMPSONS-PIS-1
+ 1
+
+ SIMPSONS
+
+
+ Processing instructions of the Simpsons questionnaire
+
+
+ fr.insee
+ m1agh821-GI
+ 1
+
+ fr.insee
+ m16kjhib
+ 1
+ QuestionItem
+
+
+ fr.insee
+ m1acyc1z
+ 1
+ Variable
+
+
+
+ vtl
+
+ fr.insee
+ m1agh821-IP-1
+ 1
+
+ CITY_OF_BIRTH
+
+
+
+ fr.insee
+ m1agh821-GOP
+ 1
+
+
+
+ fr.insee
+ m16kjhib-QOP-m16kfwqf
+ 1
+ OutParameter
+
+
+ fr.insee
+ m1agh821-IP-1
+ 1
+ InParameter
+
+
+ left_join(m1agh821-IP-1, "L_COMMUNES-2024" using id, label)
+
+
+
+ fr.insee
+ Sequence-m16kx7hl
+ 1
+ Sequence
+
+
+
+ fr.insee
+ m1ajd442-GI
+ 1
+
+ fr.insee
+ m1adj8d6
+ 1
+ QuestionItem
+
+
+ fr.insee
+ m1adjivd
+ 1
+ Variable
+
+
+
+ vtl
+
+ fr.insee
+ m1ajd442-IP-1
+ 1
+
+ CURRENT_CITY
+
+
+
+ fr.insee
+ m1ajd442-GOP
+ 1
+
+
+
+ fr.insee
+ m1adj8d6-QOP-m1adayn7
+ 1
+ OutParameter
+
+
+ fr.insee
+ m1ajd442-IP-1
+ 1
+ InParameter
+
+
+ left_join(m1ajd442-IP-1, "L_COMMUNES-2024" using id, label)
+
+
+
+ fr.insee
+ Sequence-m16kx7hl
+ 1
+ Sequence
+
+
+
+ fr.insee
+ m1awka9n-GI
+ 1
+
+ fr.insee
+ m1ad9dyh
+ 1
+ QuestionItem
+
+
+ fr.insee
+ m1adfh5f
+ 1
+ Variable
+
+
+
+ vtl
+
+ fr.insee
+ m1awka9n-IP-1
+ 1
+
+ NATIONALITY
+
+
+
+ fr.insee
+ m1awka9n-GOP
+ 1
+
+
+
+ fr.insee
+ m1ad9dyh-QOP-m1adexql
+ 1
+ OutParameter
+
+
+ fr.insee
+ m1awka9n-IP-1
+ 1
+ InParameter
+
+
+ left_join(m1awka9n-IP-1, "L_NATIONALITE-1-2-0" using id, label)
+
+
+
+ fr.insee
+ Sequence-m16kx7hl
+ 1
+ Sequence
+
+
+
+ fr.insee
+ m1awevi4-GI
+ 1
+
+ fr.insee
+ m1ageu2g
+ 1
+ QuestionItem
+
+
+ fr.insee
+ m1agq89j
+ 1
+ Variable
+
+
+
+ vtl
+
+ fr.insee
+ m1awevi4-IP-1
+ 1
+
+ ACTIVITY
+
+
+
+ fr.insee
+ m1awevi4-GOP
+ 1
+
+
+
+ fr.insee
+ m1ageu2g-QOP-m1ajfscg
+ 1
+ OutParameter
+
+
+ fr.insee
+ m1awevi4-IP-1
+ 1
+ InParameter
+
+
+ left_join(m1awevi4-IP-1, "L_ACTIVITES-2-0-0" using id, label)
+
+
+
+ fr.insee
+ m1ageurs
+ 1
+ Loop
+
+
+
+
+ fr.insee
+ INSEE-SIMPSONS-MRS
+ 1
+
+ Liste de formats numériques et dates de
+ l'enquête
+ Numeric and DateTime list for the survey
+
+
+
+
+ fr.insee
+ StudyUnit-m16kx7hl
+ 1
+
+
+ fr.insee
+ DataCollection-m16kx7hl
+ 1
+
+ fr.insee
+ QuestionScheme-m16kx7hl
+ 1
+ QuestionScheme
+
+
+ fr.insee
+ ControlConstructScheme-m16kx7hl
+ 1
+ ControlConstructScheme
+
+
+ fr.insee
+ InterviewerInstructionScheme-m16kx7hl
+ 1
+ InterviewerInstructionScheme
+
+
+ fr.insee
+ InstrumentScheme-m16kx7hl
+ 1
+
+ fr.insee
+ Instrument-m16kx7hl
+ 1
+
+ ENO_SUGGESTER_MULTI
+
+
+ Eno - Suggester multiple variables questionnaire
+
+ A définir
+
+ fr.insee
+ Sequence-m16kx7hl
+ 1
+ Sequence
+
+
+
+
+
+
diff --git a/eno-core/src/test/resources/integration/pogues/pogues-suggester-options.json b/eno-core/src/test/resources/integration/pogues/pogues-suggester-options.json
new file mode 100644
index 000000000..91f58c467
--- /dev/null
+++ b/eno-core/src/test/resources/integration/pogues/pogues-suggester-options.json
@@ -0,0 +1,544 @@
+{
+ "id": "m16kx7hl",
+ "Name": "ENO_SUGGESTER_MULTI",
+ "Child": [
+ {
+ "id": "m16kqzg7",
+ "Name": "S1",
+ "type": "SequenceType",
+ "Child": [
+ {
+ "id": "m16kjhib",
+ "Name": "CITY_OF_BIRTH",
+ "type": "QuestionType",
+ "Label": [
+ "\"City of birth\""
+ ],
+ "depth": 2,
+ "Control": [],
+ "Response": [
+ {
+ "id": "m16kfwqf",
+ "Datatype": {
+ "type": "TextDatatypeType",
+ "Pattern": "",
+ "typeName": "TEXT",
+ "MaxLength": 1,
+ "visualizationHint": "SUGGESTER"
+ },
+ "mandatory": false,
+ "CodeListReference": "L_COMMUNES-2024",
+ "CollectedVariableReference": "m1acyc1z"
+ }
+ ],
+ "TargetMode": [
+ "CAPI",
+ "CATI",
+ "CAWI",
+ "PAPI"
+ ],
+ "Declaration": [],
+ "FlowControl": [],
+ "questionType": "SINGLE_CHOICE",
+ "ClarificationQuestion": []
+ },
+ {
+ "id": "m1adj8d6",
+ "Name": "CURRENT_CITY",
+ "type": "QuestionType",
+ "Label": [
+ "\"Current city\""
+ ],
+ "depth": 2,
+ "Control": [],
+ "Response": [
+ {
+ "id": "m1adayn7",
+ "Datatype": {
+ "type": "TextDatatypeType",
+ "Pattern": "",
+ "typeName": "TEXT",
+ "MaxLength": 1,
+ "visualizationHint": "SUGGESTER"
+ },
+ "mandatory": false,
+ "CodeListReference": "L_COMMUNES-2024",
+ "CollectedVariableReference": "m1adjivd"
+ }
+ ],
+ "TargetMode": [
+ "CAPI",
+ "CATI",
+ "CAWI",
+ "PAPI"
+ ],
+ "Declaration": [],
+ "FlowControl": [],
+ "questionType": "SINGLE_CHOICE",
+ "ClarificationQuestion": []
+ },
+ {
+ "id": "m1ad9dyh",
+ "Name": "NATIONALITY",
+ "type": "QuestionType",
+ "Label": [
+ "\"Nationality\""
+ ],
+ "depth": 2,
+ "Control": [],
+ "Response": [
+ {
+ "id": "m1adexql",
+ "Datatype": {
+ "type": "TextDatatypeType",
+ "Pattern": "",
+ "typeName": "TEXT",
+ "MaxLength": 1,
+ "visualizationHint": "SUGGESTER"
+ },
+ "mandatory": false,
+ "CodeListReference": "L_NATIONALITE-1-2-0",
+ "CollectedVariableReference": "m1adfh5f"
+ }
+ ],
+ "TargetMode": [
+ "CAPI",
+ "CATI",
+ "CAWI",
+ "PAPI"
+ ],
+ "Declaration": [],
+ "FlowControl": [],
+ "questionType": "SINGLE_CHOICE",
+ "ClarificationQuestion": []
+ },
+ {
+ "id": "m1ag6y3a",
+ "Name": "SS1",
+ "type": "SequenceType",
+ "Child": [
+ {
+ "id": "m1ageu2g",
+ "Name": "ACTIVITY",
+ "type": "QuestionType",
+ "Label": [
+ "\"Activity\""
+ ],
+ "depth": 3,
+ "Control": [],
+ "Response": [
+ {
+ "id": "m1ajfscg",
+ "Datatype": {
+ "type": "TextDatatypeType",
+ "Pattern": "",
+ "typeName": "TEXT",
+ "MaxLength": 1,
+ "visualizationHint": "SUGGESTER"
+ },
+ "mandatory": false,
+ "CodeListReference": "L_ACTIVITES-2-0-0",
+ "CollectedVariableReference": "m1agq89j"
+ }
+ ],
+ "TargetMode": [
+ "CAPI",
+ "CATI",
+ "CAWI",
+ "PAPI"
+ ],
+ "Declaration": [],
+ "FlowControl": [],
+ "questionType": "SINGLE_CHOICE",
+ "ClarificationQuestion": []
+ }
+ ],
+ "Label": [
+ "\"Sub-sequence\""
+ ],
+ "depth": 2,
+ "Control": [],
+ "TargetMode": [
+ "CAPI",
+ "CATI",
+ "CAWI",
+ "PAPI"
+ ],
+ "Declaration": [],
+ "FlowControl": [],
+ "genericName": "SUBMODULE"
+ }
+ ],
+ "Label": [
+ "\"Sequence\""
+ ],
+ "depth": 1,
+ "Control": [],
+ "TargetMode": [
+ "CAPI",
+ "CATI",
+ "CAWI",
+ "PAPI"
+ ],
+ "Declaration": [],
+ "FlowControl": [],
+ "genericName": "MODULE"
+ },
+ {
+ "id": "idendquest",
+ "Name": "QUESTIONNAIRE_END",
+ "type": "SequenceType",
+ "Child": [],
+ "Label": [
+ "QUESTIONNAIRE_END"
+ ],
+ "depth": 1,
+ "Control": [],
+ "TargetMode": [
+ "CAPI",
+ "CATI",
+ "CAWI",
+ "PAPI"
+ ],
+ "Declaration": [],
+ "FlowControl": [],
+ "genericName": "MODULE"
+ }
+ ],
+ "Label": [
+ "Eno - Suggester multiple variables"
+ ],
+ "final": false,
+ "owner": "DR59-SNDI59",
+ "agency": "fr.insee",
+ "CodeLists": {
+ "CodeList": [
+ {
+ "id": "L_COMMUNES-2024",
+ "Urn": "urn:ddi:fr.insee:l_communes-2024:1",
+ "Name": "L_COMMUNES-2024",
+ "Label": "Communes 2024",
+ "SuggesterParameters": {
+ "fields": [
+ {
+ "min": 3,
+ "name": "label",
+ "rules": [
+ "[\\w]+"
+ ],
+ "stemmer": false,
+ "language": "French"
+ }
+ ],
+ "version": 1,
+ "queryParser": {
+ "type": "tokenized",
+ "params": {
+ "min": 3,
+ "pattern": "[\\w.]+",
+ "stemmer": false,
+ "language": "French"
+ }
+ }
+ }
+ },
+ {
+ "id": "L_NATIONALITE-1-2-0",
+ "Urn": "urn:ddi:fr.insee:l_nationalite-1-2-0:1",
+ "Name": "L_NATIONALITE-1-2-0",
+ "Label": "Nationalités",
+ "SuggesterParameters": {
+ "fields": [
+ {
+ "min": 3,
+ "name": "label",
+ "rules": [
+ "[\\w]+"
+ ],
+ "stemmer": false,
+ "language": "French"
+ }
+ ],
+ "version": 1,
+ "queryParser": {
+ "type": "tokenized",
+ "params": {
+ "min": 3,
+ "pattern": "[\\w.]+",
+ "stemmer": false,
+ "language": "French"
+ }
+ }
+ }
+ },
+ {
+ "id": "L_ACTIVITES-2-0-0",
+ "Urn": "urn:ddi:fr.insee:l_activites-2-0-0:1",
+ "Name": "L_ACTIVITES-2-0-0",
+ "Label": "Activités",
+ "SuggesterParameters": {
+ "fields": [
+ {
+ "min": 3,
+ "name": "label",
+ "rules": [
+ "[\\w]+"
+ ],
+ "stemmer": false,
+ "language": "French",
+ "synonyms": {
+ "EHPAD": [
+ "EPHAD",
+ "HEPAD",
+ "EPAD",
+ "EPAHD",
+ "EPADH"
+ ],
+ "URSSAF": [
+ "URSAF",
+ "URSAFF"
+ ],
+ "ascenseurs": [
+ "ASCENCEUR",
+ "ASSENCEUR",
+ "ACSENCEUR"
+ ],
+ "joaillerie": [
+ "JOAILLIER"
+ ],
+ "alimentaire": [
+ "ALIMANTAIRE"
+ ],
+ "briqueterie": [
+ "BRIQUETTERIE"
+ ],
+ "prestations": [
+ "PRESTATAIRE"
+ ],
+ "alimentaires": [
+ "ALIMANTAIRES"
+ ],
+ "echafaudages": [
+ "ECHAFFAUDAGE",
+ "ECHAFFAUDEUR"
+ ],
+ "plaquisterie": [
+ "PLACO",
+ "PLACOPLATRE"
+ ],
+ "pneumatiques": [
+ "PNEUS"
+ ],
+ "agroalimentaire": [
+ "AGGROALIMANTAIRE",
+ "AGROALIMANTAIRE"
+ ],
+ "agroalimentaires": [
+ "AGGROALIMANTAIRES",
+ "AGROALIMENTAIRES"
+ ]
+ }
+ }
+ ],
+ "version": 1,
+ "stopWords": [
+ "a",
+ "au",
+ "dans",
+ "de",
+ "des",
+ "du",
+ "en",
+ "et",
+ "la",
+ "le",
+ "ou",
+ "sur",
+ "d",
+ "l",
+ "aux",
+ "dans",
+ "un",
+ "une",
+ "pour",
+ "avec",
+ "chez",
+ "par",
+ "les"
+ ],
+ "queryParser": {
+ "type": "tokenized",
+ "params": {
+ "min": 3,
+ "pattern": "[\\w.]+",
+ "stemmer": false,
+ "language": "French"
+ }
+ }
+ }
+ }
+ ]
+ },
+ "Variables": {
+ "Variable": [
+ {
+ "id": "m1agh821",
+ "Name": "CITY_OF_BIRTH_LABEL",
+ "type": "CalculatedVariableType",
+ "Label": "\"City of birth label\"",
+ "Formula": "left_join($CITY_OF_BIRTH$, \"L_COMMUNES-2024\" using id, label)",
+ "Datatype": {
+ "type": "TextDatatypeType",
+ "Pattern": "",
+ "typeName": "TEXT",
+ "MaxLength": 249
+ }
+ },
+ {
+ "id": "m1ajd442",
+ "Name": "CURRENT_CITY_LABEL",
+ "type": "CalculatedVariableType",
+ "Label": "\"Current city label\"",
+ "Formula": "left_join($CURRENT_CITY$, \"L_COMMUNES-2024\" using id, label)",
+ "Datatype": {
+ "type": "TextDatatypeType",
+ "Pattern": "",
+ "typeName": "TEXT",
+ "MaxLength": 249
+ }
+ },
+ {
+ "id": "m1awka9n",
+ "Name": "NATIONALITY_LABEL",
+ "type": "CalculatedVariableType",
+ "Label": "\"Nationality label\"",
+ "Formula": "left_join($NATIONALITY$, \"L_NATIONALITE-1-2-0\" using id, label)",
+ "Datatype": {
+ "type": "TextDatatypeType",
+ "Pattern": "",
+ "typeName": "TEXT",
+ "MaxLength": 249
+ }
+ },
+ {
+ "id": "m1awevi4",
+ "Name": "ACTIVITY_LABEL",
+ "type": "CalculatedVariableType",
+ "Label": "\"Activity label\"",
+ "Scope": "m1ageurs",
+ "Formula": "left_join($ACTIVITY$, \"L_ACTIVITES-2-0-0\" using id, label)",
+ "Datatype": {
+ "type": "TextDatatypeType",
+ "Pattern": "",
+ "typeName": "TEXT",
+ "MaxLength": 249
+ }
+ },
+ {
+ "id": "m1acyc1z",
+ "Name": "CITY_OF_BIRTH",
+ "type": "CollectedVariableType",
+ "Label": "CITY_OF_BIRTH label",
+ "Datatype": {
+ "type": "TextDatatypeType",
+ "Pattern": "",
+ "typeName": "TEXT",
+ "MaxLength": 1
+ },
+ "CodeListReference": "L_COMMUNES-2024"
+ },
+ {
+ "id": "m1adjivd",
+ "Name": "CURRENT_CITY",
+ "type": "CollectedVariableType",
+ "Label": "CURRENT_CITY label",
+ "Datatype": {
+ "type": "TextDatatypeType",
+ "Pattern": "",
+ "typeName": "TEXT",
+ "MaxLength": 1
+ },
+ "CodeListReference": "L_COMMUNES-2024"
+ },
+ {
+ "id": "m1adfh5f",
+ "Name": "NATIONALITY",
+ "type": "CollectedVariableType",
+ "Label": "NATIONALITY label",
+ "Datatype": {
+ "type": "TextDatatypeType",
+ "Pattern": "",
+ "typeName": "TEXT",
+ "MaxLength": 1
+ },
+ "CodeListReference": "L_NATIONALITE-1-2-0"
+ },
+ {
+ "id": "m1agq89j",
+ "Name": "ACTIVITY",
+ "type": "CollectedVariableType",
+ "Label": "ACTIVITY label",
+ "Scope": "m1ageurs",
+ "Datatype": {
+ "type": "TextDatatypeType",
+ "Pattern": "",
+ "typeName": "TEXT",
+ "MaxLength": 1
+ },
+ "CodeListReference": "L_ACTIVITES-2-0-0"
+ }
+ ]
+ },
+ "flowLogic": "FILTER",
+ "Iterations": {
+ "Iteration": [
+ {
+ "id": "m1ageurs",
+ "Name": "ACTIVITY_LOOP",
+ "Step": "1",
+ "type": "DynamicIterationType",
+ "Maximum": "10",
+ "Minimum": "1",
+ "MemberReference": [
+ "m1ag6y3a",
+ "m1ag6y3a"
+ ]
+ }
+ ]
+ },
+ "TargetMode": [
+ "CAPI",
+ "CATI",
+ "CAWI",
+ "PAPI"
+ ],
+ "FlowControl": [],
+ "genericName": "QUESTIONNAIRE",
+ "ComponentGroup": [
+ {
+ "id": "m16kx30l",
+ "Name": "PAGE_1",
+ "Label": [
+ "Components for page 1"
+ ],
+ "MemberReference": [
+ "m16kqzg7",
+ "m16kjhib",
+ "m1adj8d6",
+ "m1ad9dyh",
+ "m1ag6y3a",
+ "m1ageu2g",
+ "idendquest"
+ ]
+ }
+ ],
+ "DataCollection": [
+ {
+ "id": "s2106-dc",
+ "uri": "http://ddi:fr.insee:DataCollection.s2106-dc"
+ }
+ ],
+ "lastUpdatedDate": "Fri Sep 20 2024 17:46:28 GMT+0200 (heure d’été d’Europe centrale)",
+ "formulasLanguage": "VTL",
+ "childQuestionnaireRef": []
+}
\ No newline at end of file
diff --git a/settings.gradle.kts b/settings.gradle.kts
index d731f5384..a07a69117 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -8,7 +8,7 @@ pluginManagement {
dependencyResolutionManagement {
versionCatalogs {
create("libs") {
- version("lunatic-model", "3.14.0")
+ version("lunatic-model", "3.15.0")
version("pogues-model", "1.3.14")
library("lunatic-model", "fr.insee.lunatic", "lunatic-model").versionRef("lunatic-model")
library("pogues-model", "fr.insee.pogues", "pogues-model").versionRef("pogues-model")