diff --git a/pom.xml b/pom.xml
index 486aa22..8db339c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
lunatic-model
jar
- 3.12.0
+ 3.13.0
Lunatic Model
Classes and converters for the Lunatic model
https://inseefr.github.io/Lunatic-Model/
diff --git a/src/main/java/fr/insee/lunatic/model/flat/variable/CalculatedVariableType.java b/src/main/java/fr/insee/lunatic/model/flat/variable/CalculatedVariableType.java
index dd4efc4..f3f02f2 100644
--- a/src/main/java/fr/insee/lunatic/model/flat/variable/CalculatedVariableType.java
+++ b/src/main/java/fr/insee/lunatic/model/flat/variable/CalculatedVariableType.java
@@ -1,6 +1,8 @@
package fr.insee.lunatic.model.flat.variable;
+import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
import fr.insee.lunatic.model.flat.LabelType;
import lombok.Getter;
import lombok.Setter;
@@ -11,8 +13,6 @@
/**
* A calculated variable contains an expression to be evaluated at runtime.
*/
-@Getter
-@Setter
public class CalculatedVariableType extends VariableType {
public CalculatedVariableType() {
@@ -20,14 +20,53 @@ public CalculatedVariableType() {
}
/** Expression of the calculated variable. */
+ @Getter @Setter
protected LabelType expression;
/** Name of collected and/or external variables that are required to evaluate the expression. */
+ @Getter @Setter
@JsonInclude(JsonInclude.Include.NON_EMPTY)
protected List bindingDependencies = new ArrayList<>();
- /** Name of the collected variable that define the 'shape' of the variable.
- * To be replaced with iteration reference and dimension. */
- protected String shapeFrom;
+ /** Name of the collected variables that determine the 'shape' of the variable. */
+ @JsonInclude(JsonInclude.Include.NON_EMPTY)
+ protected List shapeFrom = new ArrayList<>();
+
+ /**
+ * Returns the list of the 'shape from' variable names.
+ * @return A list of variable names.
+ */
+ @JsonProperty("shapeFrom")
+ public List getShapeFromList() {
+ return shapeFrom;
+ }
+
+ @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
+ public void setShapeFrom(List variableNames) {
+ this.shapeFrom = variableNames;
+ }
+
+ /**
+ * Get the first variable in the shape from variables list.
+ * @return A variable name.
+ * @deprecated The shape from property is a list now so this method will be removed at some point.
+ */
+ @Deprecated(since = "3.13.0")
+ public String getShapeFrom() {
+ if (shapeFrom.isEmpty())
+ return null;
+ return shapeFrom.getFirst();
+ }
+
+ /**
+ * Set shape from variable.
+ * @param variableName Variable name.
+ * @deprecated The shape from property is now a list of variable names.
+ */
+ @Deprecated(since = "3.13.0")
+ public void setShapeFrom(String variableName) {
+ shapeFrom.clear();
+ shapeFrom.add(variableName);
+ }
}
diff --git a/src/test/java/fr/insee/lunatic/conversion/variable/CalculatedVariableSerializationTest.java b/src/test/java/fr/insee/lunatic/conversion/variable/CalculatedVariableSerializationTest.java
index f7c35d7..be753eb 100644
--- a/src/test/java/fr/insee/lunatic/conversion/variable/CalculatedVariableSerializationTest.java
+++ b/src/test/java/fr/insee/lunatic/conversion/variable/CalculatedVariableSerializationTest.java
@@ -54,7 +54,7 @@ class CalculatedVariableSerializationTest {
"value": "",
"type": "VTL"
},
- "shapeFrom": "SOME_COLLECTED_VARIABLE"
+ "shapeFrom": ["SOME_COLLECTED_VARIABLE"]
}
]
}""";
@@ -90,7 +90,7 @@ void serializeCalculatedVariable_withShapeFrom() throws SerializationException,
calculatedVariableType.setExpression(new LabelType());
calculatedVariableType.getExpression().setValue("");
calculatedVariableType.getExpression().setType(LabelTypeEnum.VTL);
- calculatedVariableType.setShapeFrom("SOME_COLLECTED_VARIABLE");
+ calculatedVariableType.getShapeFromList().add("SOME_COLLECTED_VARIABLE");
questionnaire.getVariables().add(calculatedVariableType);
//
String result = jsonSerializer.serialize(questionnaire);
@@ -124,8 +124,53 @@ void deserializeCalculatedVariable_withShapeFrom() throws SerializationException
assertEquals(1, questionnaire.getVariables().size());
CalculatedVariableType calculatedVariableType = assertInstanceOf(CalculatedVariableType.class,
questionnaire.getVariables().getFirst());
- assertEquals("SOME_COLLECTED_VARIABLE", calculatedVariableType.getShapeFrom());
+ assertEquals(1, calculatedVariableType.getShapeFromList().size());
+ assertEquals("SOME_COLLECTED_VARIABLE", calculatedVariableType.getShapeFromList().getFirst());
assertEquals(1, calculatedVariableType.getDimension().value());
}
+ @Test
+ void deserializeShapeFrom_twoVariables() throws SerializationException {
+ //
+ String jsonInput = """
+ {"componentType":"Questionnaire","variables":[
+ {"variableType":"CALCULATED","shapeFrom":["VAR1", "VAR2"]}
+ ]}""";
+ //
+ Questionnaire deserialized = jsonDeserializer.deserialize(new ByteArrayInputStream(jsonInput.getBytes()));
+ //
+ CalculatedVariableType calculatedVariable = (CalculatedVariableType) deserialized.getVariables().getFirst();
+ assertEquals(List.of("VAR1", "VAR2"), calculatedVariable.getShapeFromList());
+ }
+
+ @Test
+ void serializeShapeFrom_twoVariables() throws SerializationException, JSONException {
+ //
+ Questionnaire questionnaire = new Questionnaire();
+ CalculatedVariableType calculatedVariable = new CalculatedVariableType();
+ calculatedVariable.setShapeFrom(List.of("VAR1", "VAR2"));
+ questionnaire.getVariables().add(calculatedVariable);
+ //
+ String serialized = jsonSerializer.serialize(questionnaire);
+ //
+ String expected = """
+ {"componentType":"Questionnaire","variables":[
+ {"variableType":"CALCULATED","shapeFrom":["VAR1", "VAR2"]}
+ ]}""";
+ JSONAssert.assertEquals(expected, serialized, JSONCompareMode.STRICT);
+ }
+
+ @Test
+ void stringShapeFrom_backwardCompatibility() throws SerializationException {
+ //
+ String stringShapeFrom = """
+ {"componentType":"Questionnaire","variables":[
+ {"variableType":"CALCULATED","shapeFrom":"FOO"}
+ ]}""";
+ //
+ Questionnaire deserialized = jsonDeserializer.deserialize(new ByteArrayInputStream(stringShapeFrom.getBytes()));
+ CalculatedVariableType calculatedVariable = (CalculatedVariableType) deserialized.getVariables().getFirst();
+ assertEquals("FOO", calculatedVariable.getShapeFromList().getFirst());
+ }
+
}