diff --git a/pom.xml b/pom.xml index 7691c2a5..1dbc12eb 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,9 @@ lunatic-model jar - 2.3.1 + + 2.3.2 + Lunatic Model Classes and converters for the Lunatic model @@ -16,6 +18,7 @@ 9.7.0-8 UTF-8 UTF-8 + 11 @@ -48,12 +51,7 @@ slf4j-api 1.7.25 - - junit - junit - 4.13.1 - test - + org.xmlunit xmlunit-matchers @@ -83,22 +81,22 @@ jaxb-api 2.3.1 + + org.junit.jupiter + junit-jupiter + 5.8.1 + test + + org.apache.maven.plugins maven-compiler-plugin - - 1.8 - 1.8 - UTF-8 - UTF-8 - UTF-8 - -Dfile.encoding=UTF-8 - + 3.10.1 @@ -109,8 +107,6 @@ 2.22.0 UTF-8 - UTF-8 - UTF-8 -Dfile.encoding=UTF-8 -Djavax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory diff --git a/src/main/java/fr/insee/lunatic/conversion/JSONCleaner.java b/src/main/java/fr/insee/lunatic/conversion/JSONCleaner.java index 326750a9..bbd93f4c 100644 --- a/src/main/java/fr/insee/lunatic/conversion/JSONCleaner.java +++ b/src/main/java/fr/insee/lunatic/conversion/JSONCleaner.java @@ -1,15 +1,12 @@ package fr.insee.lunatic.conversion; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.InputStream; -import java.io.OutputStream; - +import fr.insee.lunatic.Constants; +import fr.insee.lunatic.utils.XslTransformation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import fr.insee.lunatic.Constants; -import fr.insee.lunatic.utils.XslTransformation; +import java.io.*; +import java.nio.charset.StandardCharsets; /** * remove technical attribute as xsi:type @@ -19,7 +16,7 @@ */ public class JSONCleaner { - private static XslTransformation saxonService = new XslTransformation(); + private static final XslTransformation saxonService = new XslTransformation(); private static final Logger logger = LoggerFactory.getLogger(JSONCleaner.class); @@ -28,15 +25,21 @@ public String clean(String jsonString) throws Exception { if ((jsonString == null) || (jsonString.length() == 0)) return null; - InputStream json = new ByteArrayInputStream(wrapJsonWithXml(jsonString).getBytes("UTF-8")); + InputStream json = new ByteArrayInputStream(wrapJsonWithXml(jsonString).getBytes(StandardCharsets.UTF_8)); + + // Unchanged step: use XSLT "cleaning" sheet + String generatedUsingXslt = generate(json); - return this.generate(json); + // New step: apply (Java) symLinks cleaning + JSONSymLinksCleaner jsonSymLinksCleaner = new JSONSymLinksCleaner(); + return jsonSymLinksCleaner.clean(generatedUsingXslt); } public String generate(InputStream isFinalInput) throws Exception { OutputStream osOutputFile = generateOS(isFinalInput); String res = osOutputFile.toString(); osOutputFile.close(); + return res; } @@ -63,4 +66,5 @@ public String preProcessJson2XML(String json) { .replaceAll("<", "<") .replaceAll(">", ">"); } + } diff --git a/src/main/java/fr/insee/lunatic/conversion/JSONDeserializer.java b/src/main/java/fr/insee/lunatic/conversion/JSONDeserializer.java index e1412913..97ae451f 100644 --- a/src/main/java/fr/insee/lunatic/conversion/JSONDeserializer.java +++ b/src/main/java/fr/insee/lunatic/conversion/JSONDeserializer.java @@ -1,15 +1,15 @@ package fr.insee.lunatic.conversion; +import fr.insee.lunatic.model.flat.Questionnaire; +import org.eclipse.persistence.jaxb.UnmarshallerProperties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; import javax.xml.transform.stream.StreamSource; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.eclipse.persistence.jaxb.UnmarshallerProperties; - -import fr.insee.lunatic.model.flat.Questionnaire; +import java.io.InputStream; public class JSONDeserializer { @@ -36,4 +36,23 @@ public Questionnaire deserialize(String fileName) throws JAXBException { return questionnaire; } + public Questionnaire deserialize(InputStream jsonQuestionnaire) throws JAXBException { + if (jsonQuestionnaire == null) return null; + + logger.debug("Deserializing questionnaire from input stream"); + + JAXBContext context = JAXBContext.newInstance(Questionnaire.class); + Unmarshaller unmarshaller = context.createUnmarshaller(); + unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json"); + unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false); + + StreamSource json = new StreamSource(jsonQuestionnaire); + Questionnaire questionnaire = unmarshaller.unmarshal(json, Questionnaire.class).getValue(); + + logger.debug("Questionnaire " + questionnaire.getId() + " successfully deserialized"); + + return questionnaire; + } + + } diff --git a/src/main/java/fr/insee/lunatic/conversion/JSONSerializer.java b/src/main/java/fr/insee/lunatic/conversion/JSONSerializer.java index 4a68d944..04785c97 100644 --- a/src/main/java/fr/insee/lunatic/conversion/JSONSerializer.java +++ b/src/main/java/fr/insee/lunatic/conversion/JSONSerializer.java @@ -1,17 +1,20 @@ package fr.insee.lunatic.conversion; -import java.io.ByteArrayOutputStream; -import java.io.UnsupportedEncodingException; +import fr.insee.lunatic.exception.SerializationException; +import fr.insee.lunatic.model.flat.Questionnaire; +import org.eclipse.persistence.jaxb.MarshallerProperties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import javax.json.Json; +import javax.json.JsonObject; +import javax.json.JsonReader; +import javax.json.JsonWriter; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.eclipse.persistence.jaxb.MarshallerProperties; - -import fr.insee.lunatic.model.flat.Questionnaire; +import java.io.*; +import java.nio.charset.StandardCharsets; public class JSONSerializer { @@ -37,8 +40,36 @@ public String serialize(Questionnaire questionnaire) throws JAXBException, Unsup ByteArrayOutputStream baos = new ByteArrayOutputStream(); marshaller.marshal(questionnaire, baos); - + return baos.toString("UTF-8"); } + + /** serialize method returns a json string beginning with {"Questionnaire": {...}}. + * The need is to actually have questionnaire content directly at the root of the json tree. + * This method returns the json content of the given questionnaire without the "Questionnaire" level. + * @param questionnaire Lunatic questionnaire object (flat model). + * @return The questionnaire as a json string. + */ + public String serialize2(Questionnaire questionnaire) throws SerializationException { + // + String questionnaireString; + try { + questionnaireString = serialize(questionnaire); + } catch (JAXBException | UnsupportedEncodingException e) { + throw new SerializationException("Error when calling first serialize method.", e); + } + // + try (JsonReader jsonReader = Json.createReader( + new ByteArrayInputStream(questionnaireString.getBytes(StandardCharsets.UTF_8))); + OutputStream outputStream = new ByteArrayOutputStream(); + JsonWriter jsonWriter = Json.createWriter(outputStream)) { + JsonObject questionnaireJson = jsonReader.readObject(); + JsonObject contentJson = questionnaireJson.getJsonObject("Questionnaire"); + jsonWriter.writeObject(contentJson); + return outputStream.toString(); + } catch (IOException e) { + throw new SerializationException("Error when removing \"Questionnaire\" level of given questionnaire.", e); + } + } } diff --git a/src/main/java/fr/insee/lunatic/conversion/JSONSymLinksCleaner.java b/src/main/java/fr/insee/lunatic/conversion/JSONSymLinksCleaner.java new file mode 100644 index 00000000..322e19f5 --- /dev/null +++ b/src/main/java/fr/insee/lunatic/conversion/JSONSymLinksCleaner.java @@ -0,0 +1,102 @@ +package fr.insee.lunatic.conversion; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.json.*; +import java.io.*; +import java.nio.charset.StandardCharsets; + +public class JSONSymLinksCleaner { + + private static final Logger logger = LoggerFactory.getLogger(JSONSymLinksCleaner.class); + + /** + * Given a Lunatic JSON flat questionnaire, replace the source/target fields by key/values in "symLinks" attribute + * in "PairwiseLinks" components to be compliant with the Lunatic JS library. + * Warning: no validation is done on the string input. */ + public String clean(String stringFlatQuestionnaire) throws IOException { + + if (stringFlatQuestionnaire == null) { + logger.warn("null string given in JSON SymLinks cleaner."); + return null; + } + + // Read the json string into a JsonObject + try (JsonReader jsonReader = Json.createReader( + new ByteArrayInputStream(stringFlatQuestionnaire.getBytes(StandardCharsets.UTF_8)))) { + JsonObject jsonQuestionnaire = jsonReader.readObject(); + + // We will copy the entire input json object, except the "symLinks" attribute in PairwiseLinks components + JsonObjectBuilder jsonQuestionnaireBuilder = Json.createObjectBuilder(); + editQuestionnaire(jsonQuestionnaire, jsonQuestionnaireBuilder); + + OutputStream outputStream = new ByteArrayOutputStream(); + + JsonWriter jsonWriter = Json.createWriter(outputStream); + jsonWriter.writeObject(jsonQuestionnaireBuilder.build()); + + String result = outputStream.toString(); + outputStream.close(); + + return result; + } + + } + + private static void editQuestionnaire(JsonObject jsonQuestionnaire, JsonObjectBuilder jsonQuestionnaireBuilder) { + jsonQuestionnaire.forEach((key, jsonValue) -> { + if (! "components".equals(key)) { + jsonQuestionnaireBuilder.add(key, jsonValue); + } else { + editComponents(jsonQuestionnaireBuilder, (JsonArray) jsonValue); + } + }); + } + + private static void editComponents(JsonObjectBuilder jsonQuestionnaireBuilder, JsonArray jsonComponents) { + JsonArrayBuilder jsonComponentsBuilder = Json.createArrayBuilder(); + for (JsonValue jsonValue1 : jsonComponents) { + JsonObject jsonComponent = (JsonObject) jsonValue1; + if (! "PairwiseLinks".equals(jsonComponent.getString("componentType"))) { + jsonComponentsBuilder.add(jsonValue1); + } else { + editPairwiseLinks(jsonComponentsBuilder, (JsonObject) jsonValue1); + } + } + jsonQuestionnaireBuilder.add("components", jsonComponentsBuilder.build()); + } + + private static void editPairwiseLinks(JsonArrayBuilder jsonComponentsBuilder, JsonObject jsonPairwiseLinks) { + JsonObjectBuilder jsonPairwiseBuilder = Json.createObjectBuilder(); + jsonPairwiseLinks.forEach((key2, jsonValue2) -> { + if (! "symLinks".equals(key2)) { + jsonPairwiseBuilder.add(key2, jsonValue2); + } else { + editSymLinks(jsonPairwiseBuilder, (JsonObject) jsonValue2); + } + }); + jsonComponentsBuilder.add(jsonPairwiseBuilder.build()); + } + + private static void editSymLinks(JsonObjectBuilder jsonPairwiseBuilder, JsonObject jsonSymLinks) { + JsonObjectBuilder jsonSymLinksBuilder = Json.createObjectBuilder(); + JsonObjectBuilder jsonLINKSBuilder = Json.createObjectBuilder(); + String symLinksName = jsonSymLinks.getJsonString("name").getString(); + jsonSymLinks.getJsonArray("LINK").forEach(jsonValue3 -> { + JsonObject jsonSourceTarget = (JsonObject) jsonValue3; + JsonString sourceKey = (JsonString) jsonSourceTarget.get("source"); + JsonString targetKey = (JsonString) jsonSourceTarget.get("target"); + // target field is not mandatory and can be null + // json converted from xml can contain "null" string values + if (targetKey != null && !"null".equals(targetKey.getString())) { + jsonLINKSBuilder.add(sourceKey.getString(), targetKey); + } else { + jsonLINKSBuilder.addNull(sourceKey.getString()); + } + }); + jsonSymLinksBuilder.add(symLinksName, jsonLINKSBuilder.build()); + jsonPairwiseBuilder.add("symLinks", jsonSymLinksBuilder.build()); + } + +} diff --git a/src/main/java/fr/insee/lunatic/exception/SerializationException.java b/src/main/java/fr/insee/lunatic/exception/SerializationException.java new file mode 100644 index 00000000..febb80dd --- /dev/null +++ b/src/main/java/fr/insee/lunatic/exception/SerializationException.java @@ -0,0 +1,10 @@ +package fr.insee.lunatic.exception; + +/** Thrown when an error occurs during serialization of a questionnaire object. */ +public class SerializationException extends Exception { + + public SerializationException(String message, Exception e) { + super(message, e); + } + +} diff --git a/src/main/resources/xsd/LunaticModel.xsd b/src/main/resources/xsd/LunaticModel.xsd index 5b4da2b6..5c2d6fb0 100644 --- a/src/main/resources/xsd/LunaticModel.xsd +++ b/src/main/resources/xsd/LunaticModel.xsd @@ -32,7 +32,7 @@ - + @@ -115,6 +115,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -146,6 +174,7 @@ + diff --git a/src/main/resources/xsd/LunaticModelFlat.xsd b/src/main/resources/xsd/LunaticModelFlat.xsd index a490618a..f27fef6b 100644 --- a/src/main/resources/xsd/LunaticModelFlat.xsd +++ b/src/main/resources/xsd/LunaticModelFlat.xsd @@ -32,7 +32,7 @@ - + @@ -101,7 +101,7 @@ - + @@ -111,6 +111,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -141,6 +168,7 @@ + diff --git a/src/main/resources/xslt/json-cleaner.xsl b/src/main/resources/xslt/json-cleaner.xsl index acddd0ce..abfb987a 100644 --- a/src/main/resources/xslt/json-cleaner.xsl +++ b/src/main/resources/xslt/json-cleaner.xsl @@ -100,11 +100,35 @@ - + + + + + + + + + + + + + + + + + + + + + + + + - - + diff --git a/src/test/java/fr/insee/lunatic/test/DataTranslatorsTest.java b/src/test/java/fr/insee/lunatic/test/DataTranslatorsTest.java index 7a340b44..fb95a5b6 100644 --- a/src/test/java/fr/insee/lunatic/test/DataTranslatorsTest.java +++ b/src/test/java/fr/insee/lunatic/test/DataTranslatorsTest.java @@ -1,25 +1,25 @@ package fr.insee.lunatic.test; -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; - +import fr.insee.lunatic.Constants; +import fr.insee.lunatic.conversion.data.JSONLunaticDataToXML; +import fr.insee.lunatic.conversion.data.XMLLunaticDataToJSON; +import fr.insee.lunatic.test.utils.XMLDiff; import org.apache.commons.io.FileUtils; import org.json.JSONObject; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import org.skyscreamer.jsonassert.JSONAssert; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xmlunit.diff.Diff; -import fr.insee.lunatic.Constants; -import fr.insee.lunatic.conversion.data.JSONLunaticDataToXML; -import fr.insee.lunatic.conversion.data.XMLLunaticDataToJSON; +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; public class DataTranslatorsTest { @@ -27,7 +27,7 @@ public class DataTranslatorsTest { private static final Logger logger = LoggerFactory.getLogger(DataTranslatorsTest.class); - @BeforeClass + @BeforeAll public static void setUpBeforeClass() throws Exception { } @@ -53,14 +53,14 @@ public void testDataXMLToJSON() { } catch (IOException e) { e.printStackTrace(); - Assert.fail(); + Assertions.fail(); } catch (NullPointerException e) { e.printStackTrace(); - Assert.fail(); + Assertions.fail(); } catch (Exception e) { e.printStackTrace(); System.out.println(e.getMessage()); - Assert.fail(); + Assertions.fail(); } } @@ -79,18 +79,18 @@ public void testDataJSONToXML() { File expectedFile = new File(String.format("%s/out/data.xml", basePath)); Diff diff = xmlDiff.getDiff(xmlOut,expectedFile); - Assert.assertFalse(getDiffMessage(diff, basePath), diff.hasDifferences()); + Assertions.assertFalse( diff.hasDifferences(), getDiffMessage(diff, basePath)); } catch (IOException e) { e.printStackTrace(); - Assert.fail(); + Assertions.fail(); } catch (NullPointerException e) { e.printStackTrace(); - Assert.fail(); + Assertions.fail(); } catch (Exception e) { e.printStackTrace(); System.out.println(e.getMessage()); - Assert.fail(); + Assertions.fail(); } } diff --git a/src/test/java/fr/insee/lunatic/test/JSONSerializerTest.java b/src/test/java/fr/insee/lunatic/test/JSONSerializerTest.java new file mode 100644 index 00000000..d45cdd2b --- /dev/null +++ b/src/test/java/fr/insee/lunatic/test/JSONSerializerTest.java @@ -0,0 +1,42 @@ +package fr.insee.lunatic.test; + +import fr.insee.lunatic.conversion.JSONSerializer; +import fr.insee.lunatic.exception.SerializationException; +import fr.insee.lunatic.model.flat.Questionnaire; +import fr.insee.lunatic.test.utils.JsonFormatter; +import org.junit.jupiter.api.Test; + +import javax.xml.bind.JAXBException; +import java.io.UnsupportedEncodingException; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class JSONSerializerTest { + + @Test + void serialize_simplestCase() throws JAXBException, UnsupportedEncodingException { + // + Questionnaire questionnaire = new Questionnaire(); + questionnaire.setId("foo-id"); + // + JSONSerializer serializer = new JSONSerializer(); + String result = serializer.serialize(questionnaire); + // + assertEquals("{\"Questionnaire\":{\"id\":\"foo-id\"}}", + JsonFormatter.compress(result)); + } + + @Test + void serialize2_simplestCase() throws SerializationException { + // + Questionnaire questionnaire = new Questionnaire(); + questionnaire.setId("foo-id"); + // + JSONSerializer serializer = new JSONSerializer(); + String result = serializer.serialize2(questionnaire); + // + assertEquals("{\"id\":\"foo-id\"}", + JsonFormatter.compress(result)); + } + +} diff --git a/src/test/java/fr/insee/lunatic/test/JSONSymLinksCleanerTest.java b/src/test/java/fr/insee/lunatic/test/JSONSymLinksCleanerTest.java new file mode 100644 index 00000000..b217a3c3 --- /dev/null +++ b/src/test/java/fr/insee/lunatic/test/JSONSymLinksCleanerTest.java @@ -0,0 +1,37 @@ +package fr.insee.lunatic.test; + +import fr.insee.lunatic.conversion.JSONSymLinksCleaner; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import javax.json.Json; +import javax.json.JsonObject; +import javax.json.JsonReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; + +import static org.junit.jupiter.api.Assertions.*; + +class JSONSymLinksCleanerTest { + + JSONSymLinksCleaner symLinksCleaner; + + @BeforeEach + public void initCleaner() { + symLinksCleaner = new JSONSymLinksCleaner(); + } + + @Test + void nullString() throws IOException { + assertNull(symLinksCleaner.clean(null)); + } + + @Test + void sandbox_testJsonObjectGetString() { + JsonReader reader = Json.createReader(new ByteArrayInputStream("{\"foo\":1}".getBytes())); + JsonObject jsonObject = reader.readObject(); + assertThrows(ClassCastException.class, () -> jsonObject.getString("foo")); + assertEquals("1", String.valueOf(jsonObject.get("foo"))); + } + +} diff --git a/src/test/java/fr/insee/lunatic/test/LunaticXmlToDataTest.java b/src/test/java/fr/insee/lunatic/test/LunaticXmlToDataTest.java index c10eae20..a93b0638 100644 --- a/src/test/java/fr/insee/lunatic/test/LunaticXmlToDataTest.java +++ b/src/test/java/fr/insee/lunatic/test/LunaticXmlToDataTest.java @@ -1,14 +1,14 @@ package fr.insee.lunatic.test; import fr.insee.lunatic.Constants; -import fr.insee.lunatic.conversion.data.JSONLunaticDataToXML; import fr.insee.lunatic.conversion.data.XMLLunaticDataToJSON; import fr.insee.lunatic.conversion.data.XMLLunaticToXMLEmptyData; +import fr.insee.lunatic.test.utils.XMLDiff; import org.apache.commons.io.FileUtils; import org.json.JSONObject; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import org.skyscreamer.jsonassert.JSONAssert; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -27,12 +27,12 @@ public class LunaticXmlToDataTest { private static final Logger logger = LoggerFactory.getLogger(LunaticXmlToDataTest.class); - @BeforeClass + @BeforeAll public static void setUpBeforeClass() throws Exception { } - @Test + @org.junit.jupiter.api.Test public void testLunaticXml2EmptyXmlData() { logger.debug("Launch test : lunaticXML to empty xml data"); try { @@ -46,18 +46,18 @@ public void testLunaticXml2EmptyXmlData() { File expectedFile = new File(String.format("%s/out/questionnaire-data.xml", Constants.RESOURCES_FOLDER_DATA_PATH)); Diff diff = xmlDiff.getDiff(xmlOut,expectedFile); - Assert.assertFalse(getDiffMessage(diff, basePath), diff.hasDifferences()); + Assertions.assertFalse(diff.hasDifferences(), getDiffMessage(diff, basePath)); } catch (IOException e) { e.printStackTrace(); - Assert.fail(); + Assertions.fail(); } catch (NullPointerException e) { e.printStackTrace(); - Assert.fail(); + Assertions.fail(); } catch (Exception e) { e.printStackTrace(); System.out.println(e.getMessage()); - Assert.fail(); + Assertions.fail(); } } @@ -86,14 +86,14 @@ public void testLunaticXml2EmptyJsonData() { } catch (IOException e) { e.printStackTrace(); - Assert.fail(); + Assertions.fail(); } catch (NullPointerException e) { e.printStackTrace(); - Assert.fail(); + Assertions.fail(); } catch (Exception e) { e.printStackTrace(); System.out.println(e.getMessage()); - Assert.fail(); + Assertions.fail(); } } diff --git a/src/test/java/fr/insee/lunatic/test/PairwiseTest.java b/src/test/java/fr/insee/lunatic/test/PairwiseTest.java new file mode 100644 index 00000000..628964f8 --- /dev/null +++ b/src/test/java/fr/insee/lunatic/test/PairwiseTest.java @@ -0,0 +1,83 @@ +package fr.insee.lunatic.test; + +import fr.insee.lunatic.conversion.JSONCleaner; +import fr.insee.lunatic.conversion.JSONDeserializer; +import fr.insee.lunatic.conversion.XMLLunaticFlatToJSONLunaticFlatTranslator; +import fr.insee.lunatic.conversion.XMLLunaticToXMLLunaticFlatTranslator; +import fr.insee.lunatic.model.flat.PairwiseLinks; +import fr.insee.lunatic.model.flat.Questionnaire; +import org.junit.jupiter.api.Test; + +import javax.xml.bind.JAXBException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** Test class to see if PairwiseLinks object doesn't break translators */ +class PairwiseTest { + + @Test + void deserializeQuestionnaireContainingPairwise_doesContainPairwise() throws JAXBException { + // + JSONDeserializer jsonDeserializer = new JSONDeserializer(); + // + Questionnaire questionnaire = jsonDeserializer.deserialize( + this.getClass().getClassLoader().getResourceAsStream("pairwise/pairwise-flat.json")); + // + assertNotNull(questionnaire); + assertTrue(questionnaire.getComponents().stream() + .anyMatch(componentType -> componentType instanceof PairwiseLinks)); + } + + @Test + void transformAndClean_questionnaireWithPairwise_doesNotThrow() throws Exception { + // + XMLLunaticToXMLLunaticFlatTranslator translator = new XMLLunaticToXMLLunaticFlatTranslator(); + XMLLunaticFlatToJSONLunaticFlatTranslator translator2 = new XMLLunaticFlatToJSONLunaticFlatTranslator(); + JSONCleaner jsonCleaner = new JSONCleaner(); + // + String result = jsonCleaner.clean( + translator2.translate( + translator.generate( + this.getClass().getClassLoader().getResourceAsStream("pairwise/pairwise-hierarchical-test.xml") + ))); + // + assertNotNull(result); + } + + @Test + void transformAndClean_questionnaireWithPairwise_writeOutput() throws Exception { + // + XMLLunaticToXMLLunaticFlatTranslator translator = new XMLLunaticToXMLLunaticFlatTranslator(); + XMLLunaticFlatToJSONLunaticFlatTranslator translator2 = new XMLLunaticFlatToJSONLunaticFlatTranslator(); + JSONCleaner jsonCleaner = new JSONCleaner(); + // + URL pairwiseFileUrl = this.getClass().getClassLoader().getResource("pairwise/pairwise-hierarchical-test.xml"); + assert pairwiseFileUrl != null; + // + Path pairwisePath = Path.of(pairwiseFileUrl.toURI()).getParent(); + Path outPath = Files.createTempDirectory(pairwisePath, "out"); + System.out.printf("Writing test pairwise outputs in \n%s\n", outPath); + + // + String xmlFlat = translator.generate(pairwiseFileUrl.openStream()); + Files.writeString( + outPath.resolve("pairwise-flat.xml"), + xmlFlat); + String jsonFlat = translator2.translate(xmlFlat); + Files.writeString( + outPath.resolve("pairwise-flat.json"), + jsonFlat); + String result = jsonCleaner.clean(jsonFlat); + Files.writeString( + outPath.resolve("pairwise-cleaned.json"), + result); + + // + assertNotNull(result); + } + +} diff --git a/src/test/java/fr/insee/lunatic/test/TranslatorsTest.java b/src/test/java/fr/insee/lunatic/test/TranslatorsTest.java index 2e06414e..eaef4db7 100644 --- a/src/test/java/fr/insee/lunatic/test/TranslatorsTest.java +++ b/src/test/java/fr/insee/lunatic/test/TranslatorsTest.java @@ -1,16 +1,15 @@ package fr.insee.lunatic.test; -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; - +import fr.insee.lunatic.Constants; +import fr.insee.lunatic.conversion.JSONCleaner; +import fr.insee.lunatic.conversion.XMLLunaticFlatToJSONLunaticFlatTranslator; +import fr.insee.lunatic.conversion.XMLLunaticToJSONLunaticTranslator; +import fr.insee.lunatic.conversion.XMLLunaticToXMLLunaticFlatTranslator; +import fr.insee.lunatic.test.utils.XMLDiff; import org.json.JSONObject; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import org.skyscreamer.jsonassert.Customization; import org.skyscreamer.jsonassert.JSONAssert; import org.skyscreamer.jsonassert.JSONCompareMode; @@ -19,41 +18,51 @@ import org.slf4j.LoggerFactory; import org.xmlunit.diff.Diff; -import fr.insee.lunatic.Constants; -import fr.insee.lunatic.conversion.JSONCleaner; -import fr.insee.lunatic.conversion.XMLLunaticFlatToJSONLunaticFlatTranslator; -import fr.insee.lunatic.conversion.XMLLunaticToJSONLunaticTranslator; -import fr.insee.lunatic.conversion.XMLLunaticToXMLLunaticFlatTranslator; +import javax.json.Json; +import javax.json.JsonArray; +import javax.json.JsonObject; +import javax.json.JsonReader; +import javax.json.stream.JsonParser; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; public class TranslatorsTest { private XMLDiff xmlDiff = new XMLDiff(); - + private static final Logger logger = LoggerFactory.getLogger(TranslatorsTest.class); - - @BeforeClass + + @BeforeAll public static void setUpBeforeClass() throws Exception { } - - - @Test + + @org.junit.jupiter.api.Test public void testQuestionnaireXMLFToJSONF() { logger.debug("Launch test : XMLLunaticFlat -> JSONLunaticFlat"); try { String basePath = Constants.RESOURCES_FOLDER_XMLF_2_JSONF_PATH; - + Path outPath = Paths.get(Constants.TEMP_FOLDER_PATH + "/xmlf-2-jsonf-out.json"); Files.deleteIfExists(outPath); Path outputFile = Files.createFile(outPath); - + File in = new File(String.format("%s/form_flat.xml", Constants.RESOURCES_FOLDER_DUMMY_PATH)); - + XMLLunaticFlatToJSONLunaticFlatTranslator translator = new XMLLunaticFlatToJSONLunaticFlatTranslator(); JSONCleaner jsonCleaner = new JSONCleaner(); - + String jsonQuestionnaire = jsonCleaner.clean(translator.translate(in)); JSONObject jsonOut = new JSONObject(jsonQuestionnaire); - + Files.write(outputFile, jsonQuestionnaire.getBytes("UTF-8")); logger.debug("File generated at : "+outputFile.toString()); @@ -68,79 +77,79 @@ public void testQuestionnaireXMLFToJSONF() { } catch (IOException e) { e.printStackTrace(); - Assert.fail(); + Assertions.fail(); } catch (NullPointerException e) { e.printStackTrace(); - Assert.fail(); + Assertions.fail(); } catch (Exception e) { e.printStackTrace(); System.out.println(e.getMessage()); - Assert.fail(); + Assertions.fail(); } } - + @Test public void testQuestionnaireXMLHToXMLF() { logger.debug("Launch test : XMLLunatic -> XMLLunaticFlat"); try { String basePath = Constants.RESOURCES_FOLDER_XMLH_2_XMLF_PATH; - + Path outPath = Paths.get(Constants.TEMP_FOLDER_PATH + "/xmlh-2-xmlf-out.xml"); Files.deleteIfExists(outPath); Path outputFile = Files.createFile(outPath); - + File in = new File(String.format("%s/form.xml", Constants.RESOURCES_FOLDER_DUMMY_PATH)); - + XMLLunaticToXMLLunaticFlatTranslator translator = new XMLLunaticToXMLLunaticFlatTranslator(); String xmlQuestionnaire = translator.generate(in); Files.write(outputFile, xmlQuestionnaire.getBytes("UTF-8")); logger.debug("File generated at : "+outputFile.toString()); - + File expectedFile = new File(String.format("%s/out.xml", basePath)); Diff diff = xmlDiff.getDiff(outputFile.toFile(),expectedFile); - Assert.assertFalse(getDiffMessage(diff, basePath), diff.hasDifferences()); - + Assertions.assertFalse(diff.hasDifferences(), getDiffMessage(diff, basePath)); + } catch (IOException e) { e.printStackTrace(); - Assert.fail(); + Assertions.fail(); } catch (NullPointerException e) { e.printStackTrace(); - Assert.fail(); + Assertions.fail(); } catch (Exception e) { e.printStackTrace(); System.out.println(e.getMessage()); - Assert.fail(); + Assertions.fail(); } } - + @Test public void testQuestionnaireXMLHToJSONF() { logger.debug("Launch test : XMLLunatic -> JSONLunaticFlat"); try { - + long startTime = System.currentTimeMillis(); - + String basePath = Constants.RESOURCES_FOLDER_XMLH_2_JSONF_PATH; - + Path outPath = Paths.get(Constants.TEMP_FOLDER_PATH + "/xmlh-2-jsonf-out.json"); Files.deleteIfExists(outPath); Path outputFile = Files.createFile(outPath); File in = new File(String.format("%s/form.xml", Constants.RESOURCES_FOLDER_DUMMY_PATH)); - + XMLLunaticToXMLLunaticFlatTranslator translator = new XMLLunaticToXMLLunaticFlatTranslator(); XMLLunaticFlatToJSONLunaticFlatTranslator translator2 = new XMLLunaticFlatToJSONLunaticFlatTranslator(); - JSONCleaner jsonCleaner = new JSONCleaner(); - + JSONCleaner jsonCleaner = new JSONCleaner(); + String jsonQuestionnaire = jsonCleaner.clean(translator2.translate(translator.generate(in))); JSONObject jsonOut = new JSONObject(jsonQuestionnaire); Files.write(outputFile, jsonQuestionnaire.getBytes("UTF-8")); - + long elapsedTime = System.currentTimeMillis() - startTime; - + logger.debug("File generated at : "+outputFile.toString()); logger.debug("Transformation time for eno-XML to json lunatic fo JS: " + elapsedTime +" ms"); @@ -153,32 +162,32 @@ public void testQuestionnaireXMLHToJSONF() { new Customization("enoCoreVersion",(o1, o2) -> true))); } catch (IOException e) { e.printStackTrace(); - Assert.fail(); + Assertions.fail(); } catch (NullPointerException e) { e.printStackTrace(); - Assert.fail(); + Assertions.fail(); } catch (Exception e) { e.printStackTrace(); System.out.println(e.getMessage()); - Assert.fail(); + Assertions.fail(); } } - + @Test public void testQuestionnaireXMLHToJSONH() { logger.debug("Launch test : XMLLunatic -> JSONLunaticH"); try { String basePath = Constants.RESOURCES_FOLDER_XMLH_2_JSONH_PATH; - + Path outPath = Paths.get(Constants.TEMP_FOLDER_PATH + "/xmlh-2-jsonh-out.json"); Files.deleteIfExists(outPath); Path outputFile = Files.createFile(outPath); - + File in = new File(String.format("%s/form.xml", Constants.RESOURCES_FOLDER_DUMMY_PATH)); XMLLunaticToJSONLunaticTranslator translator = new XMLLunaticToJSONLunaticTranslator(); JSONCleaner jsonCleaner = new JSONCleaner(); - + String jsonQuestionnaire = jsonCleaner.clean(translator.translate(in)); JSONObject jsonOut = new JSONObject(jsonQuestionnaire); Files.write(outputFile, jsonQuestionnaire.getBytes("UTF-8")); @@ -195,14 +204,14 @@ public void testQuestionnaireXMLHToJSONH() { } catch (IOException e) { e.printStackTrace(); - Assert.fail(); + Assertions.fail(); } catch (NullPointerException e) { e.printStackTrace(); - Assert.fail(); + Assertions.fail(); } catch (Exception e) { e.printStackTrace(); System.out.println(e.getMessage()); - Assert.fail(); + Assertions.fail(); } } @@ -210,6 +219,30 @@ private String getDiffMessage(Diff diff, String path) { return String.format("Transformed output for %s should match expected XML document:\n %s", path, diff.toString()); } - - + + @Test + void xmlHierarchicalToJsonFlat_resizingIssue() throws Exception { + // + XMLLunaticToXMLLunaticFlatTranslator translator1 = new XMLLunaticToXMLLunaticFlatTranslator(); + XMLLunaticFlatToJSONLunaticFlatTranslator translator2 = new XMLLunaticFlatToJSONLunaticFlatTranslator(); + JSONCleaner cleaner = new JSONCleaner(); + // + String xmlFlat = translator1.generate(this.getClass().getClassLoader().getResourceAsStream( + "pairwise/resizing-issue/lb3ei722-lunatic-hierarchical.xml")); + String jsonFlat = translator2.translate(xmlFlat); + String result = cleaner.clean(jsonFlat); + // + assertNotNull(result); + try (JsonReader jsonReader = Json.createReader( + new ByteArrayInputStream(result.getBytes(StandardCharsets.UTF_8)))) { + JsonObject resultJson = jsonReader.readObject(); + JsonArray resizingVariables = resultJson.getJsonObject("resizing").getJsonObject("NB") + .getJsonArray("variables"); + assertEquals(2, resizingVariables.size()); + String variableName1 = resizingVariables.getString(0); + String variableName2 = resizingVariables.getString(1); + assertEquals(Set.of("PRENOM", "AGE"), Set.of(variableName1, variableName2)); + } + } + } diff --git a/src/test/java/fr/insee/lunatic/test/ValidatorTest.java b/src/test/java/fr/insee/lunatic/test/ValidatorTest.java index fc35b272..7f5c881a 100644 --- a/src/test/java/fr/insee/lunatic/test/ValidatorTest.java +++ b/src/test/java/fr/insee/lunatic/test/ValidatorTest.java @@ -1,27 +1,14 @@ package fr.insee.lunatic.test; -import fr.insee.lunatic.Constants; -import fr.insee.lunatic.conversion.JSONCleaner; -import fr.insee.lunatic.conversion.XMLLunaticFlatToJSONLunaticFlatTranslator; -import fr.insee.lunatic.conversion.XMLLunaticToJSONLunaticTranslator; -import fr.insee.lunatic.conversion.XMLLunaticToXMLLunaticFlatTranslator; +import fr.insee.lunatic.test.utils.XMLDiff; import fr.insee.lunatic.utils.Modele; import fr.insee.lunatic.utils.SchemaValidator; -import org.json.JSONObject; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; -import org.skyscreamer.jsonassert.JSONAssert; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.xmlunit.diff.Diff; import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; public class ValidatorTest { @@ -37,10 +24,10 @@ public void testValidateH() { File in = new File(String.format("%s/form.xml", basePath)); try { SchemaValidator schemaValidator = new SchemaValidator(Modele.HIERARCHICAL); - Assert.assertTrue(schemaValidator.validateFile(in)); + Assertions.assertTrue(schemaValidator.validateFile(in)); } catch (Exception e) { - Assert.fail(); + Assertions.fail(); // TODO Auto-generated catch block e.printStackTrace(); } @@ -52,10 +39,10 @@ public void testValidateF() { File in = new File(String.format("%s/form_flat.xml", basePath)); try { SchemaValidator schemaValidator = new SchemaValidator(Modele.FLAT); - Assert.assertTrue(schemaValidator.validateFile(in)); + Assertions.assertTrue(schemaValidator.validateFile(in)); } catch (Exception e) { - Assert.fail(); + Assertions.fail(); // TODO Auto-generated catch block e.printStackTrace(); } diff --git a/src/test/java/fr/insee/lunatic/test/utils/JsonFormatter.java b/src/test/java/fr/insee/lunatic/test/utils/JsonFormatter.java new file mode 100644 index 00000000..0ec679aa --- /dev/null +++ b/src/test/java/fr/insee/lunatic/test/utils/JsonFormatter.java @@ -0,0 +1,18 @@ +package fr.insee.lunatic.test.utils; + +/** + * Utils class to facilitate json comparison in tests. + */ +public class JsonFormatter { + + /** + * Compress the json string by removing line breaks and spaces. + * Warning: this method also removes spaces inside string content. + * @param jsonString Json string. + * @return Compressed json string. + */ + public static String compress(String jsonString) { + return jsonString.replaceAll("\\s+","").replaceAll("\\n+",""); + } + +} diff --git a/src/test/java/fr/insee/lunatic/test/XMLDiff.java b/src/test/java/fr/insee/lunatic/test/utils/XMLDiff.java similarity index 97% rename from src/test/java/fr/insee/lunatic/test/XMLDiff.java rename to src/test/java/fr/insee/lunatic/test/utils/XMLDiff.java index e2b20664..991d7646 100644 --- a/src/test/java/fr/insee/lunatic/test/XMLDiff.java +++ b/src/test/java/fr/insee/lunatic/test/utils/XMLDiff.java @@ -1,4 +1,4 @@ -package fr.insee.lunatic.test; +package fr.insee.lunatic.test.utils; import java.io.File; import javax.xml.transform.stream.StreamSource; diff --git a/src/test/resources/pairwise/pairwise-flat.json b/src/test/resources/pairwise/pairwise-flat.json new file mode 100644 index 00000000..b14cc015 --- /dev/null +++ b/src/test/resources/pairwise/pairwise-flat.json @@ -0,0 +1,643 @@ +{ + "id" : "lcswhwa1", + "modele" : "L2A2_LOOP", + "enoCoreVersion" : "2.4.1-pairwise-dev-pairwise", + "lunaticModelVersion" : "2.3.2-rc4", + "generatingDate" : "30-01-2023 21:23:48", + "missing" : false, + "pagination" : "question", + "maxPage" : "7", + "label" : { + "value" : "Recette liens deux à deux --- Boucle", + "type" : "VTL|MD" + }, + "components" : [ { + "id" : "lcswhkve", + "componentType" : "Sequence", + "page" : "1", + "type" : "Sequence", + "label" : { + "value" : "\"I - \" || \"Composition du ménage\"", + "type" : "VTL|MD" + }, + "conditionFilter" : { + "value" : "true", + "type" : "VTL" + }, + "hierarchy" : { + "sequence" : { + "id" : "lcswhkve", + "page" : "1", + "label" : { + "value" : "\"I - \" || \"Composition du ménage\"", + "type" : "VTL|MD" + } + } + } + }, { + "id" : "lcswldsp", + "componentType" : "InputNumber", + "mandatory" : false, + "page" : "2", + "min" : 1.0, + "max" : 10.0, + "decimals" : 0, + "type" : "InputNumber", + "label" : { + "value" : "\"➡ \" || \"Combien de personnes dans votre ménage ?\"", + "type" : "VTL|MD" + }, + "conditionFilter" : { + "value" : "true", + "type" : "VTL" + }, + "controls" : [ { + "id" : "lcswldsp-format-borne-inf-sup", + "typeOfControl" : "FORMAT", + "criticality" : "ERROR", + "control" : { + "value" : "not(not(isnull(NB)) and (1>NB or 10NB)", + "type" : "VTL" + }, + "errorMessage" : { + "value" : "\"Le nombre doit comporter au maximum 0 chiffre(s) après la virgule.\"", + "type" : "VTL|MD" + } + } ], + "hierarchy" : { + "sequence" : { + "id" : "lcswhkve", + "page" : "1", + "label" : { + "value" : "\"I - \" || \"Composition du ménage\"", + "type" : "VTL|MD" + } + } + }, + "bindingDependencies" : [ "NB" ], + "response" : { + "name" : "NB" + } + }, { + "id" : "lcswrct3", + "componentType" : "Loop", + "page" : "3", + "depth" : 1, + "paginatedLoop" : false, + "type" : "Loop", + "conditionFilter" : { + "value" : "true", + "type" : "VTL" + }, + "hierarchy" : { + "sequence" : { + "id" : "lcswhkve", + "page" : "1", + "label" : { + "value" : "\"I - \" || \"Composition du ménage\"", + "type" : "VTL|MD" + } + } + }, + "bindingDependencies" : [ "NB", "PRENOM" ], + "loopDependencies" : [ "NB" ], + "lines" : { + "min" : { + "value" : "nvl(NB, 1)", + "type" : "VTL" + }, + "max" : { + "value" : "nvl(NB, 1)", + "type" : "VTL" + } + }, + "components" : [ { + "id" : "lcswbr49", + "componentType" : "Subsequence", + "page" : "3", + "goToPage" : "3", + "type" : "Subsequence", + "label" : { + "value" : "Prénoms", + "type" : "VTL|MD" + }, + "conditionFilter" : { + "value" : "true", + "type" : "VTL" + }, + "hierarchy" : { + "sequence" : { + "id" : "lcswhkve", + "page" : "1", + "label" : { + "value" : "\"I - \" || \"Composition du ménage\"", + "type" : "VTL|MD" + } + }, + "subSequence" : { + "id" : "lcswbr49", + "page" : "3", + "label" : { + "value" : "Prénoms", + "type" : "VTL|MD" + } + } + }, + "bindingDependencies" : [ "NB" ] + }, { + "id" : "lcswmnod", + "componentType" : "Input", + "mandatory" : false, + "page" : "3", + "maxLength" : 249, + "type" : "Input", + "label" : { + "value" : "\"➡ \" || \"Prénom ?\"", + "type" : "VTL|MD" + }, + "conditionFilter" : { + "value" : "true", + "type" : "VTL" + }, + "hierarchy" : { + "sequence" : { + "id" : "lcswhkve", + "page" : "1", + "label" : { + "value" : "\"I - \" || \"Composition du ménage\"", + "type" : "VTL|MD" + } + }, + "subSequence" : { + "id" : "lcswbr49", + "page" : "3", + "label" : { + "value" : "Prénoms", + "type" : "VTL|MD" + } + } + }, + "bindingDependencies" : [ "PRENOM", "NB" ], + "response" : { + "name" : "PRENOM" + } + } ] + }, { + "id" : "lcswo5m5", + "componentType" : "Subsequence", + "goToPage" : "4", + "type" : "Subsequence", + "label" : { + "value" : "Liens deux à deux", + "type" : "VTL|MD" + }, + "conditionFilter" : { + "value" : "true", + "type" : "VTL" + }, + "hierarchy" : { + "sequence" : { + "id" : "lcswhkve", + "page" : "1", + "label" : { + "value" : "\"I - \" || \"Composition du ménage\"", + "type" : "VTL|MD" + } + }, + "subSequence" : { + "id" : "lcswo5m5", + "page" : "4", + "label" : { + "value" : "Liens deux à deux", + "type" : "VTL|MD" + } + } + } + }, { + "id" : "lcsxm1eu", + "componentType" : "PairwiseLinks", + "mandatory" : false, + "page" : "4", + "type" : "PairwiseLinks", + "conditionFilter" : { + "value" : "true", + "type" : "VTL" + }, + "hierarchy" : { + "sequence" : { + "id" : "lcswhkve", + "page" : "1", + "label" : { + "value" : "\"I - \" || \"Composition du ménage\"", + "type" : "VTL|MD" + } + }, + "subSequence" : { + "id" : "lcswo5m5", + "page" : "4", + "label" : { + "value" : "Liens deux à deux", + "type" : "VTL|MD" + } + } + }, + "bindingDependencies" : [ "LIENS" ], + "xAxisIterations" : { + "value" : "count(PRENOM)", + "type" : "VTL" + }, + "yAxisIterations" : { + "value" : "count(PRENOM)", + "type" : "VTL" + }, + "components" : [ { + "id" : "lcsxm1eu-pairwise-dropdown", + "componentType" : "Dropdown", + "mandatory" : false, + "page" : "5", + "type" : "Dropdown", + "label" : { + "value" : "\"➡ \" || \"Quels sont vos liens ?\"", + "type" : "VTL|MD" + }, + "conditionFilter" : { + "value" : "xAxis <> yAxis", + "type" : "VTL" + }, + "bindingDependencies" : [ "LIENS" ], + "options" : [ { + "value" : "1", + "label" : { + "value" : "Son conjoint, sa conjointe", + "type" : "VTL|MD" + } + }, { + "value" : "2", + "label" : { + "value" : "Sa mère, son père", + "type" : "VTL|MD" + } + }, { + "value" : "3", + "label" : { + "value" : "Sa fille, son fils", + "type" : "VTL|MD" + } + }, { + "value" : "4", + "label" : { + "value" : "Sa soeur, son frère (y compris demi et quasi)", + "type" : "VTL|MD" + } + }, { + "value" : "5", + "label" : { + "value" : "Sa belle-mère, son beau-père (conjoint.e d’un des parents)", + "type" : "VTL|MD" + } + }, { + "value" : "6", + "label" : { + "value" : "L’enfant du conjoint (belle-fille, beau-fils)", + "type" : "VTL|MD" + } + }, { + "value" : "7", + "label" : { + "value" : "Sa belle-mère, son beau-père (parent du conjoint)", + "type" : "VTL|MD" + } + }, { + "value" : "8", + "label" : { + "value" : "Sa belle-fille, son beau-fils (conjoint.e d’un enfant)", + "type" : "VTL|MD" + } + }, { + "value" : "9", + "label" : { + "value" : "Sa grand-mère, son grand-père", + "type" : "VTL|MD" + } + }, { + "value" : "10", + "label" : { + "value" : "Sa petite-fille, petit-fils", + "type" : "VTL|MD" + } + }, { + "value" : "11", + "label" : { + "value" : "Sa tante, son oncle", + "type" : "VTL|MD" + } + }, { + "value" : "12", + "label" : { + "value" : "Sa cousine, son cousin", + "type" : "VTL|MD" + } + }, { + "value" : "13", + "label" : { + "value" : "Sa nièce, son neveu", + "type" : "VTL|MD" + } + }, { + "value" : "14", + "label" : { + "value" : "Un enfant placé en famille d’accueil", + "type" : "VTL|MD" + } + }, { + "value" : "15", + "label" : { + "value" : "Sa belle-soeur, son beau-frère", + "type" : "VTL|MD" + } + }, { + "value" : "16", + "label" : { + "value" : "Un autre lien familial", + "type" : "VTL|MD" + } + }, { + "value" : "17", + "label" : { + "value" : "Autre lien (employé de maison, salarié logé, jeune au pair …)", + "type" : "VTL|MD" + } + } ], + "response" : { + "name" : "LIENS" + } + } ], + "symLinks" : { + "name" : "LIENS", + "LINK" : [ { + "source" : "1", + "target" : "1" + }, { + "source" : "2", + "target" : "3" + }, { + "source" : "3", + "target" : "2" + }, { + "source" : "4", + "target" : "4" + }, { + "source" : "5", + "target" : "6" + }, { + "source" : "6", + "target" : "5" + }, { + "source" : "7", + "target" : "8" + }, { + "source" : "8", + "target" : "7" + }, { + "source" : "9", + "target" : "10" + }, { + "source" : "10", + "target" : "9" + }, { + "source" : "11", + "target" : "13" + }, { + "source" : "12", + "target" : "12" + }, { + "source" : "13", + "target" : "11" + }, { + "source" : "14", + "target" : "null" + }, { + "source" : "15", + "target" : "null" + }, { + "source" : "16", + "target" : "16" + }, { + "source" : "17", + "target" : "17" + }, { + "source" : "18", + "target" : "18" + } ] + } + }, { + "id" : "COMMENT-SEQ", + "componentType" : "Sequence", + "page" : "6", + "type" : "Sequence", + "label" : { + "value" : "\"Commentaire\"", + "type" : "VTL|MD" + }, + "conditionFilter" : { + "value" : "true", + "type" : "VTL" + }, + "hierarchy" : { + "sequence" : { + "id" : "COMMENT-SEQ", + "page" : "6", + "label" : { + "value" : "\"Commentaire\"", + "type" : "VTL|MD" + } + } + } + }, { + "id" : "COMMENT-QUESTION", + "componentType" : "Textarea", + "mandatory" : false, + "page" : "7", + "maxLength" : 2000, + "type" : "Textarea", + "label" : { + "value" : "\"Avez-vous des remarques concernant l'enquête ou des commentaires ?\"", + "type" : "VTL|MD" + }, + "conditionFilter" : { + "value" : "true", + "type" : "VTL" + }, + "hierarchy" : { + "sequence" : { + "id" : "COMMENT-SEQ", + "page" : "6", + "label" : { + "value" : "\"Commentaire\"", + "type" : "VTL|MD" + } + } + }, + "bindingDependencies" : [ "COMMENT_QE" ], + "response" : { + "name" : "COMMENT_QE" + } + } ], + "variables" : [ { + "variableType" : "COLLECTED", + "type" : "VariableType", + "name" : "COMMENT_QE", + "values" : { + "PREVIOUS" : null, + "COLLECTED" : null, + "FORCED" : null, + "EDITED" : null, + "INPUTED" : null + } + }, { + "variableType" : "COLLECTED", + "type" : "VariableType", + "name" : "NB", + "values" : { + "PREVIOUS" : null, + "COLLECTED" : null, + "FORCED" : null, + "EDITED" : null, + "INPUTED" : null + } + }, { + "variableType" : "COLLECTED", + "type" : "VariableTypeArray", + "name" : "PRENOM", + "values" : { + "PREVIOUS" : { + "PREVIOUS" : [ null ] + }, + "COLLECTED" : { + "COLLECTED" : [ null ] + }, + "FORCED" : { + "FORCED" : [ null ] + }, + "EDITED" : { + "EDITED" : [ null ] + }, + "INPUTED" : { + "INPUTED" : [ null ] + } + } + }, { + "variableType" : "COLLECTED", + "type" : "VariableTypeArray", + "name" : "LIENS", + "values" : { + "PREVIOUS" : { + "PREVIOUS" : [ { + "type" : "PREVIOUSArray", + "PREVIOUS" : [ null ] + } ] + }, + "COLLECTED" : { + "COLLECTED" : [ { + "type" : "COLLECTEDArray", + "COLLECTED" : [ null ] + } ] + }, + "FORCED" : { + "FORCED" : [ { + "type" : "FORCEDArray", + "FORCED" : [ null ] + } ] + }, + "EDITED" : { + "EDITED" : [ { + "type" : "EDITEDArray", + "EDITED" : [ null ] + } ] + }, + "INPUTED" : { + "INPUTED" : [ { + "type" : "INPUTEDArray", + "INPUTED" : [ null ] + } ] + } + } + }, { + "variableType" : "CALCULATED", + "type" : "VariableType", + "name" : "FILTER_RESULT_NB", + "expression" : { + "value" : "true", + "type" : "VTL" + }, + "inFilter" : "false" + }, { + "variableType" : "CALCULATED", + "type" : "VariableType", + "name" : "FILTER_RESULT_PRENOM", + "expression" : { + "value" : "true", + "type" : "VTL" + }, + "shapeFrom" : "PRENOM", + "inFilter" : "false" + }, { + "variableType" : "CALCULATED", + "type" : "VariableType", + "name" : "FILTER_RESULT_LIENS", + "expression" : { + "value" : "xAxis <> yAxis", + "type" : "VTL" + }, + "inFilter" : "false" + }, { + "variableType" : "CALCULATED", + "type" : "VariableType", + "name" : "xAxis", + "expression" : { + "value" : "PRENOM", + "type" : "VTL" + }, + "bindingDependencies" : [ "PRENOM" ], + "shapeFrom" : "PRENOM", + "inFilter" : "true" + }, { + "variableType" : "CALCULATED", + "type" : "VariableType", + "name" : "yAxis", + "expression" : { + "value" : "PRENOM", + "type" : "VTL" + }, + "bindingDependencies" : [ "PRENOM" ], + "shapeFrom" : "PRENOM", + "inFilter" : "true" + } ], + "cleaning" : { + }, + "resizing" : { + "NB" : [ { + "size" : "nvl(NB, 1)", + "variables" : "PRENOM", + "value" : "\n " + } ], + "PRENOM" : [ { + "sizeForLinksVariables" : "count(PRENOM)", + "sizeForLinksVariables" : "count(PRENOM)", + "linksVariables" : "LIENS", + "value" : "\n " + } ] + } +} \ No newline at end of file diff --git a/src/test/resources/pairwise/pairwise-flat.xml b/src/test/resources/pairwise/pairwise-flat.xml new file mode 100644 index 00000000..d0e5a40d --- /dev/null +++ b/src/test/resources/pairwise/pairwise-flat.xml @@ -0,0 +1,622 @@ + + + + + + + true + VTL + + + + + + + + + + + true + VTL + + + + not(not(isnull(NB)) and (1>NB or 10<NB)) + VTL + + + " La valeur doit être comprise entre 1 et 10." + VTL|MD + + + + + not(not(isnull(NB)) and round(NB,0)<>NB) + VTL + + + "Le nombre doit comporter au maximum 0 chiffre(s) après la virgule." + VTL|MD + + + + + + + + NB + + + + + + nvl(NB, 1) + VTL + + + nvl(NB, 1) + VTL + + + + true + VTL + + + + + + + NB + PRENOM + NB + + + + true + VTL + + + + + + + + + + NB + + + + + true + VTL + + + + + + + + + + PRENOM + NB + + + + + + + true + VTL + + + + + + + + + + + + + true + VTL + + + + + + + + + + LIENS + + count(PRENOM) + VTL + + + count(PRENOM) + VTL + + + + 1 + 1 + + + 2 + 3 + + + 3 + 2 + + + 4 + 4 + + + 5 + 6 + + + 6 + 5 + + + 7 + 8 + + + 8 + 7 + + + 9 + 10 + + + 10 + 9 + + + 11 + 13 + + + 12 + 12 + + + 13 + 11 + + + 14 + null + + + 15 + null + + + 16 + 16 + + + 17 + 17 + + + 18 + 18 + + + + + + xAxis <> yAxis + VTL + + LIENS + + 1 + + + + 2 + + + + 3 + + + + 4 + + + + 5 + + + + 6 + + + + 7 + + + + 8 + + + + 9 + + + + 10 + + + + 11 + + + + 12 + + + + 13 + + + + 14 + + + + 15 + + + + 16 + + + + 17 + + + + + + + + + true + VTL + + + + + + + + + + + true + VTL + + + + + + + COMMENT_QE + + + + COMMENT_QE + + + + + + + + + + + NB + + + + + + + + + + PRENOM + + + + + + + + + + + + + + + + + + + + LIENS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + FILTER_RESULT_NB + + true + VTL + + false + + + FILTER_RESULT_PRENOM + + true + VTL + + PRENOM + false + + + FILTER_RESULT_LIENS + + xAxis <> yAxis + VTL + + false + + + xAxis + + PRENOM + VTL + + PRENOM + PRENOM + true + + + yAxis + + PRENOM + VTL + + PRENOM + PRENOM + true + + + + + nvl(NB, 1) + PRENOM + + + count(PRENOM) + count(PRENOM) + LIENS + + + diff --git a/src/test/resources/pairwise/pairwise-hierarchical-test.xml b/src/test/resources/pairwise/pairwise-hierarchical-test.xml new file mode 100644 index 00000000..603e8ac4 --- /dev/null +++ b/src/test/resources/pairwise/pairwise-hierarchical-test.xml @@ -0,0 +1,622 @@ + + + + + + + true + VTL + + + + + + + + + + true + VTL + + + + not(not(isnull(NB)) and (1>NB or 10<NB)) + VTL + + + " La valeur doit être comprise entre 1 et 10." + VTL|MD + + + + + not(not(isnull(NB)) and round(NB,0)<>NB) + VTL + + + "Le nombre doit comporter au maximum 0 chiffre(s) après la virgule." + VTL|MD + + + + + + + + NB + + + + + + nvl(NB, 1) + VTL + + + nvl(NB, 1) + VTL + + + + true + VTL + + + + + + + NB + PRENOM + NB + + + + true + VTL + + + + + + + + + + NB + + + + true + VTL + + + + + + + + + + PRENOM + NB + + + + + + + + true + VTL + + + + + + + + + + + + true + VTL + + + + + + + + + + LIENS + + count(PRENOM) + VTL + + + count(PRENOM) + VTL + + + + 1 + 1 + + + 2 + 3 + + + 3 + 2 + + + 4 + 4 + + + 5 + 6 + + + 6 + 5 + + + 7 + 8 + + + 8 + 7 + + + 9 + 10 + + + 10 + 9 + + + 11 + 13 + + + 12 + 12 + + + 13 + 11 + + + 14 + null + + + 15 + null + + + 16 + 16 + + + 17 + 17 + + + 18 + 18 + + + + + + xAxis <> yAxis + VTL + + LIENS + + 1 + + + + 2 + + + + 3 + + + + 4 + + + + 5 + + + + 6 + + + + 7 + + + + 8 + + + + 9 + + + + 10 + + + + 11 + + + + 12 + + + + 13 + + + + 14 + + + + 15 + + + + 16 + + + + 17 + + + + + + + + + + + true + VTL + + + + + + + + + + true + VTL + + + + + + + COMMENT_QE + + + + + COMMENT_QE + + + + + + + + + + + NB + + + + + + + + + + PRENOM + + + + + + + + + + + + + + + + + + + + LIENS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + FILTER_RESULT_NB + + true + VTL + + false + + + FILTER_RESULT_PRENOM + + true + VTL + + PRENOM + false + + + FILTER_RESULT_LIENS + + xAxis <> yAxis + VTL + + false + + + xAxis + + PRENOM + VTL + + PRENOM + PRENOM + true + + + yAxis + + PRENOM + VTL + + PRENOM + PRENOM + true + + + + + nvl(NB, 1) + PRENOM + + + count(PRENOM) + count(PRENOM) + LIENS + + + diff --git a/src/test/resources/pairwise/resizing-issue/lb3ei722-lunatic-expected.json b/src/test/resources/pairwise/resizing-issue/lb3ei722-lunatic-expected.json new file mode 100644 index 00000000..98295d71 --- /dev/null +++ b/src/test/resources/pairwise/resizing-issue/lb3ei722-lunatic-expected.json @@ -0,0 +1,649 @@ + + { "id" : "lb3ei722", + "modele" : "TESTSURSUM", + "enoCoreVersion" : "2.4.1", + "lunaticModelVersion" : "2.3.1", + "generatingDate" : "25-05-2023 14:42:02", + "missing" : false, + "pagination" : "question", + "maxPage" : "10", + "label" : + { "value" : "QNONREG - sum, min dans une boucle et sur controle prénom et test filtre occurrence", + "type" : "VTL|MD" }, + "components" : + [ + { "id" : "ksyjs7vy", + "componentType" : "Sequence", + "page" : "1", + "label" : + { "value" : "\"I - \" || \"S0\"", + "type" : "VTL|MD" }, + "conditionFilter" : + { "value" : "true", + "type" : "VTL" }, + "hierarchy" : + { "sequence" : + { "id" : "ksyjs7vy", + "page" : "1", + "label" : + { "value" : "\"I - \" || \"S0\"", + "type" : "VTL|MD" } } } }, + + { "id" : "kze792d8", + "componentType" : "InputNumber", + "mandatory" : false, + "page" : "2", + "min" : 0, + "max" : 10, + "decimals" : 0, + "label" : + { "value" : "\"➡ \" || \"NB\"", + "type" : "VTL|MD" }, + "conditionFilter" : + { "value" : "true", + "type" : "VTL" }, + "controls" : + [ + { "id" : "kze792d8-format-borne-inf-sup", + "typeOfControl" : "FORMAT", + "criticality" : "ERROR", + "control" : + { "value" : "not(not(isnull(NB)) and (0>NB or 10NB)", + "type" : "VTL" }, + "errorMessage" : + { "value" : "\"Le nombre doit comporter au maximum 0 chiffre(s) après la virgule.\"", + "type" : "VTL|MD" } } ], + "hierarchy" : + { "sequence" : + { "id" : "ksyjs7vy", + "page" : "1", + "label" : + { "value" : "\"I - \" || \"S0\"", + "type" : "VTL|MD" } } }, + "bindingDependencies" : + [ "NB" ], + "response" : + { "name" : "NB" } }, + + { "id" : "ksykfdm9", + "componentType" : "Loop", + "page" : "3", + "depth" : 1, + "paginatedLoop" : false, + "conditionFilter" : + { "value" : "true", + "type" : "VTL" }, + "hierarchy" : + { "sequence" : + { "id" : "ksyjs7vy", + "page" : "1", + "label" : + { "value" : "\"I - \" || \"S0\"", + "type" : "VTL|MD" } } }, + "bindingDependencies" : + [ "NB", + "PRENOM" ], + "loopDependencies" : + [ "NB" ], + "lines" : + { "min" : + { "value" : "cast(NB,integer)", + "type" : "VTL" }, + "max" : + { "value" : "cast(NB,integer)", + "type" : "VTL" } }, + "components" : + [ + { "id" : "ksynhpl3", + "componentType" : "Subsequence", + "page" : "3", + "goToPage" : "3", + "label" : + { "value" : "\"Habitants\"", + "type" : "VTL|MD" }, + "conditionFilter" : + { "value" : "true", + "type" : "VTL" }, + "hierarchy" : + { "sequence" : + { "id" : "ksyjs7vy", + "page" : "1", + "label" : + { "value" : "\"I - \" || \"S0\"", + "type" : "VTL|MD" } }, + "subSequence" : + { "id" : "ksynhpl3", + "page" : "3", + "label" : + { "value" : "\"Habitants\"", + "type" : "VTL|MD" } } }, + "bindingDependencies" : + [ "NB" ] }, + + { "id" : "ksyjvi40", + "componentType" : "Input", + "mandatory" : false, + "page" : "3", + "maxLength" : 249, + "label" : + { "value" : "\"➡ \" || \"prénom\"", + "type" : "VTL|MD" }, + "declarations" : + [ + { "id" : "ksyjvi40-l7uj49ok", + "declarationType" : "HELP", + "position" : "AFTER_QUESTION_TEXT", + "label" : + { "value" : "\"Tester Prénom vide et Prénom = A\"", + "type" : "VTL|MD" } } ], + "conditionFilter" : + { "value" : "true", + "type" : "VTL" }, + "controls" : + [ + { "id" : "ksyjvi40-CI-0", + "typeOfControl" : "CONSISTENCY", + "criticality" : "WARN", + "control" : + { "value" : "not(nvl(PRENOM,\"\")=\"\")", + "type" : "VTL" }, + "errorMessage" : + { "value" : "\"Prenom est vide - controle nvl\"", + "type" : "VTL|MD" }, + "bindingDependencies" : + [ "PRENOM" ] }, + + { "id" : "ksyjvi40-CI-1", + "typeOfControl" : "CONSISTENCY", + "criticality" : "WARN", + "control" : + { "value" : "not(PRENOM = \"A\")", + "type" : "VTL" }, + "errorMessage" : + { "value" : "\"PRénom vaut A\"", + "type" : "VTL|MD" }, + "bindingDependencies" : + [ "PRENOM" ] } ], + "hierarchy" : + { "sequence" : + { "id" : "ksyjs7vy", + "page" : "1", + "label" : + { "value" : "\"I - \" || \"S0\"", + "type" : "VTL|MD" } }, + "subSequence" : + { "id" : "ksynhpl3", + "page" : "3", + "label" : + { "value" : "\"Habitants\"", + "type" : "VTL|MD" } } }, + "bindingDependencies" : + [ "PRENOM", + "NB" ], + "response" : + { "name" : "PRENOM" } } ] }, + + { "id" : "ksyniqzx", + "componentType" : "Sequence", + "page" : "4", + "label" : + { "value" : "\"II - \" || \"S1\"", + "type" : "VTL|MD" }, + "conditionFilter" : + { "value" : "true", + "type" : "VTL" }, + "hierarchy" : + { "sequence" : + { "id" : "ksyniqzx", + "page" : "4", + "label" : + { "value" : "\"II - \" || \"S1\"", + "type" : "VTL|MD" } } } }, + + { "id" : "ksynkaoo", + "componentType" : "Loop", + "page" : "5", + "maxPage" : "1", + "depth" : 1, + "paginatedLoop" : true, + "conditionFilter" : + { "value" : "true", + "type" : "VTL" }, + "hierarchy" : + { "sequence" : + { "id" : "ksyniqzx", + "page" : "4", + "label" : + { "value" : "\"II - \" || \"S1\"", + "type" : "VTL|MD" } } }, + "bindingDependencies" : + [ "AGE", + "IND_MAJEUR", + "PRENOM" ], + "loopDependencies" : + [ "PRENOM" ], + "components" : + [ + { "id" : "ksyjxw3a", + "componentType" : "Subsequence", + "goToPage" : "5.1", + "label" : + { "value" : "\"Les ages\"", + "type" : "VTL|MD" }, + "conditionFilter" : + { "value" : "true", + "type" : "VTL" }, + "hierarchy" : + { "sequence" : + { "id" : "ksyniqzx", + "page" : "4", + "label" : + { "value" : "\"II - \" || \"S1\"", + "type" : "VTL|MD" } }, + "subSequence" : + { "id" : "ksyjxw3a", + "page" : "5.1", + "label" : + { "value" : "\"Les ages\"", + "type" : "VTL|MD" } } }, + "bindingDependencies" : + [ "PRENOM" ] }, + + { "id" : "ksyke448", + "componentType" : "InputNumber", + "mandatory" : false, + "page" : "5.1", + "min" : 0, + "max" : 100, + "decimals" : 0, + "label" : + { "value" : "\"➡ \" || \"Age de l’individu : \" || PRENOM", + "type" : "VTL|MD" }, + "declarations" : + [ + { "id" : "ksyke448-ktwsl4qu", + "declarationType" : "HELP", + "position" : "AFTER_QUESTION_TEXT", + "label" : + { "value" : "\"AGE vaut : \" || cast(AGE,string)", + "type" : "VTL|MD" } }, + + { "id" : "ksyke448-l7g2enbf", + "declarationType" : "HELP", + "position" : "AFTER_QUESTION_TEXT", + "label" : + { "value" : "\"IND_MAJEUR :\" || cast(IND_MAJEUR,string)", + "type" : "VTL|MD" } } ], + "conditionFilter" : + { "value" : "true", + "type" : "VTL" }, + "controls" : + [ + { "id" : "ksyke448-format-borne-inf-sup", + "typeOfControl" : "FORMAT", + "criticality" : "ERROR", + "control" : + { "value" : "not(not(isnull(AGE)) and (0>AGE or 100AGE)", + "type" : "VTL" }, + "errorMessage" : + { "value" : "\"Le nombre doit comporter au maximum 0 chiffre(s) après la virgule.\"", + "type" : "VTL|MD" } }, + + { "id" : "ksyke448-CI-0", + "typeOfControl" : "CONSISTENCY", + "criticality" : "WARN", + "control" : + { "value" : "not(isnull(AGE))", + "type" : "VTL" }, + "errorMessage" : + { "value" : "\"Age est vide\"", + "type" : "VTL|MD" }, + "bindingDependencies" : + [ "AGE" ] } ], + "hierarchy" : + { "sequence" : + { "id" : "ksyniqzx", + "page" : "4", + "label" : + { "value" : "\"II - \" || \"S1\"", + "type" : "VTL|MD" } }, + "subSequence" : + { "id" : "ksyjxw3a", + "page" : "5.1", + "label" : + { "value" : "\"Les ages\"", + "type" : "VTL|MD" } } }, + "bindingDependencies" : + [ "AGE", + "IND_MAJEUR", + "PRENOM" ], + "response" : + { "name" : "AGE" } } ], + "iterations" : + { "value" : "count(PRENOM)", + "type" : "VTL" } }, + + { "id" : "ku2pnlmr", + "componentType" : "Subsequence", + "page" : "6", + "goToPage" : "6", + "label" : + { "value" : "\"Affichage de qq var\"", + "type" : "VTL|MD" }, + "declarations" : + [ + { "id" : "ku2pnlmr-l7t4dzz2", + "declarationType" : "HELP", + "position" : "AFTER_QUESTION_TEXT", + "label" : + { "value" : "\"Affichage du nb de majeurs : \" || cast(SUM_MAJEUR,string)", + "type" : "VTL|MD" } }, + + { "id" : "ku2pnlmr-l806u4c8", + "declarationType" : "HELP", + "position" : "AFTER_QUESTION_TEXT", + "label" : + { "value" : "\"Affichage du somme age : \" || cast(SUM_AGE,string)", + "type" : "VTL|MD" } }, + + { "id" : "ku2pnlmr-lg6mo14c", + "declarationType" : "HELP", + "position" : "AFTER_QUESTION_TEXT", + "label" : + { "value" : "\"Affichage du min des ages sans cast: \" || cast(MIN_AGE,string)", + "type" : "VTL|MD" } } ], + "conditionFilter" : + { "value" : "true", + "type" : "VTL" }, + "hierarchy" : + { "sequence" : + { "id" : "ksyniqzx", + "page" : "4", + "label" : + { "value" : "\"II - \" || \"S1\"", + "type" : "VTL|MD" } }, + "subSequence" : + { "id" : "ku2pnlmr", + "page" : "6", + "label" : + { "value" : "\"Affichage de qq var\"", + "type" : "VTL|MD" } } }, + "bindingDependencies" : + [ "SUM_MAJEUR", + "SUM_AGE", + "MIN_AGE" ] }, + + { "id" : "ku2pxugf", + "componentType" : "Input", + "mandatory" : false, + "page" : "7", + "maxLength" : 249, + "label" : + { "value" : "\"➡ \" || \"divers\"", + "type" : "VTL|MD" }, + "conditionFilter" : + { "value" : "(SUM_MAJEUR > 0)", + "type" : "VTL", + "bindingDependencies" : + [ "SUM_MAJEUR", + "IND_MAJEUR", + "AGE" ] }, + "hierarchy" : + { "sequence" : + { "id" : "ksyniqzx", + "page" : "4", + "label" : + { "value" : "\"II - \" || \"S1\"", + "type" : "VTL|MD" } }, + "subSequence" : + { "id" : "ku2pnlmr", + "page" : "6", + "label" : + { "value" : "\"Affichage de qq var\"", + "type" : "VTL|MD" } } }, + "bindingDependencies" : + [ "DIVERS" ], + "response" : + { "name" : "DIVERS" } }, + + { "id" : "l7yz0fe5", + "componentType" : "Sequence", + "page" : "8", + "label" : + { "value" : "\"III - \" || \"S3\"", + "type" : "VTL|MD" }, + "declarations" : + [ + { "id" : "l7yz0fe5-l7yyye9y", + "declarationType" : "HELP", + "position" : "AFTER_QUESTION_TEXT", + "label" : + { "value" : "\"Affichage de la somme des ages : \" || cast(SUM_AGE,string)", + "type" : "VTL|MD" } }, + + { "id" : "l7yz0fe5-l7yz5mgk", + "declarationType" : "HELP", + "position" : "AFTER_QUESTION_TEXT", + "label" : + { "value" : "\"Affichage du nb de majeurs : \" || cast(SUM_MAJEUR,string)", + "type" : "VTL|MD" } }, + + { "id" : "l7yz0fe5-l7yyrp0q", + "declarationType" : "HELP", + "position" : "AFTER_QUESTION_TEXT", + "label" : + { "value" : "\"Affichage du min des ages : \" || cast(MIN_AGE,string)", + "type" : "VTL|MD" } } ], + "conditionFilter" : + { "value" : "true", + "type" : "VTL" }, + "hierarchy" : + { "sequence" : + { "id" : "l7yz0fe5", + "page" : "8", + "label" : + { "value" : "\"III - \" || \"S3\"", + "type" : "VTL|MD" } } }, + "bindingDependencies" : + [ "SUM_AGE", + "SUM_MAJEUR", + "MIN_AGE" ] }, + + { "id" : "COMMENT-SEQ", + "componentType" : "Sequence", + "page" : "9", + "label" : + { "value" : "\"Commentaire\"", + "type" : "VTL|MD" }, + "conditionFilter" : + { "value" : "true", + "type" : "VTL" }, + "hierarchy" : + { "sequence" : + { "id" : "COMMENT-SEQ", + "page" : "9", + "label" : + { "value" : "\"Commentaire\"", + "type" : "VTL|MD" } } } }, + + { "id" : "COMMENT-QUESTION", + "componentType" : "Textarea", + "mandatory" : false, + "page" : "10", + "maxLength" : 2000, + "label" : + { "value" : "\"Avez-vous des remarques concernant l'enquête ou des commentaires ?\"", + "type" : "VTL|MD" }, + "conditionFilter" : + { "value" : "true", + "type" : "VTL" }, + "hierarchy" : + { "sequence" : + { "id" : "COMMENT-SEQ", + "page" : "9", + "label" : + { "value" : "\"Commentaire\"", + "type" : "VTL|MD" } } }, + "bindingDependencies" : + [ "COMMENT_QE" ], + "response" : + { "name" : "COMMENT_QE" } } ], + "variables" : + [ + { "variableType" : "COLLECTED", + "name" : "COMMENT_QE", + "values" : + { "PREVIOUS" : null, + "COLLECTED" : null, + "FORCED" : null, + "EDITED" : null, + "INPUTED" : null } }, + + { "variableType" : "COLLECTED", + "name" : "NB", + "values" : + { "PREVIOUS" : null, + "COLLECTED" : null, + "FORCED" : null, + "EDITED" : null, + "INPUTED" : null } }, + + { "variableType" : "COLLECTED", + "name" : "PRENOM", + "values" : + { "PREVIOUS" : + [ null ], + "COLLECTED" : + [ null ], + "FORCED" : + [ null ], + "EDITED" : + [ null ], + "INPUTED" : + [ null ] } }, + + { "variableType" : "COLLECTED", + "name" : "AGE", + "values" : + { "PREVIOUS" : + [ null ], + "COLLECTED" : + [ null ], + "FORCED" : + [ null ], + "EDITED" : + [ null ], + "INPUTED" : + [ null ] } }, + + { "variableType" : "COLLECTED", + "name" : "DIVERS", + "values" : + { "PREVIOUS" : null, + "COLLECTED" : null, + "FORCED" : null, + "EDITED" : null, + "INPUTED" : null } }, + + { "variableType" : "CALCULATED", + "name" : "FILTER_RESULT_NB", + "expression" : + { "value" : "true", + "type" : "VTL" }, + "inFilter" : "false" }, + + { "variableType" : "CALCULATED", + "name" : "FILTER_RESULT_PRENOM", + "expression" : + { "value" : "true", + "type" : "VTL" }, + "shapeFrom" : "PRENOM", + "inFilter" : "false" }, + + { "variableType" : "CALCULATED", + "name" : "IND_MAJEUR", + "expression" : + { "value" : "if nvl(AGE,0) > 17 then 1 else 0", + "type" : "VTL" }, + "bindingDependencies" : + [ "AGE" ], + "shapeFrom" : "PRENOM", + "inFilter" : "true" }, + + { "variableType" : "CALCULATED", + "name" : "FILTER_RESULT_AGE", + "expression" : + { "value" : "true", + "type" : "VTL" }, + "shapeFrom" : "AGE", + "inFilter" : "false" }, + + { "variableType" : "CALCULATED", + "name" : "FILTER_RESULT_DIVERS", + "expression" : + { "value" : "(SUM_MAJEUR > 0)", + "type" : "VTL" }, + "bindingDependencies" : + [ "SUM_MAJEUR" ], + "inFilter" : "false" }, + + { "variableType" : "CALCULATED", + "name" : "SUM_MAJEUR", + "expression" : + { "value" : "sum(IND_MAJEUR)", + "type" : "VTL" }, + "bindingDependencies" : + [ "IND_MAJEUR", + "AGE" ], + "inFilter" : "true" }, + + { "variableType" : "CALCULATED", + "name" : "SUM_AGE", + "expression" : + { "value" : "sum(AGE)", + "type" : "VTL" }, + "bindingDependencies" : + [ "AGE" ], + "inFilter" : "false" }, + + { "variableType" : "CALCULATED", + "name" : "MIN_AGE", + "expression" : + { "value" : "min(AGE)", + "type" : "VTL" }, + "bindingDependencies" : + [ "AGE" ], + "inFilter" : "false" } ], + "cleaning" : + { "SUM_MAJEUR" : + { "DIVERS" : "(SUM_MAJEUR > 0)" }, + "IND_MAJEUR" : + { "DIVERS" : "(SUM_MAJEUR > 0)" }, + "AGE" : + { "DIVERS" : "(SUM_MAJEUR > 0)" } }, + "resizing" : + { "NB" : + { "size" : "cast(NB,integer)", + "variables" : + [ "PRENOM", + "AGE" ] } } } \ No newline at end of file diff --git a/src/test/resources/pairwise/resizing-issue/lb3ei722-lunatic-hierarchical.xml b/src/test/resources/pairwise/resizing-issue/lb3ei722-lunatic-hierarchical.xml new file mode 100644 index 00000000..22d3ce25 --- /dev/null +++ b/src/test/resources/pairwise/resizing-issue/lb3ei722-lunatic-hierarchical.xml @@ -0,0 +1,717 @@ + + + + + + + true + VTL + + + + + + + + + + true + VTL + + + + not(not(isnull(NB)) and (0>NB or 10<NB)) + VTL + + + " La valeur doit être comprise entre 0 et 10." + VTL|MD + + + + + not(not(isnull(NB)) and round(NB,0)<>NB) + VTL + + + "Le nombre doit comporter au maximum 0 chiffre(s) après la virgule." + VTL|MD + + + + + + + + NB + + + + + + cast(NB,integer) + VTL + + + cast(NB,integer) + VTL + + + + true + VTL + + + + + + + NB + PRENOM + NB + + + + true + VTL + + + + + + + + + + NB + + + + + + + true + VTL + + + + not(nvl(PRENOM,"")="") + VTL + + + "Prenom est vide - controle nvl" + VTL|MD + + PRENOM + + + + not(PRENOM = "A") + VTL + + + "PRénom vaut A" + VTL|MD + + PRENOM + + + + + + + + + + PRENOM + NB + + + + + + + + + true + VTL + + + + + + + + + count(PRENOM) + VTL + + + true + VTL + + + + + + + AGE + IND_MAJEUR + PRENOM + PRENOM + + + + true + VTL + + + + + + + + + + PRENOM + + + + + + + + + + true + VTL + + + + not(not(isnull(AGE)) and (0>AGE or 100<AGE)) + VTL + + + " La valeur doit être comprise entre 0 et 100." + VTL|MD + + + + + not(not(isnull(AGE)) and round(AGE,0)<>AGE) + VTL + + + "Le nombre doit comporter au maximum 0 chiffre(s) après la virgule." + VTL|MD + + + + + not(isnull(AGE)) + VTL + + + "Age est vide" + VTL|MD + + AGE + + + + + + + + + + AGE + IND_MAJEUR + PRENOM + + + + + + + + + + + + + + + + + true + VTL + + + + + + + + + + SUM_MAJEUR + SUM_AGE + MIN_AGE + + + + (SUM_MAJEUR > 0) + VTL + SUM_MAJEUR + IND_MAJEUR + AGE + + + + + + + + + + DIVERS + + + + + + + + + + + + + + + + + true + VTL + + + + + + + SUM_AGE + SUM_MAJEUR + MIN_AGE + + + + + true + VTL + + + + + + + + + + true + VTL + + + + + + + COMMENT_QE + + + + + COMMENT_QE + + + + + + + + + + + NB + + + + + + + + + + PRENOM + + + + + + + + + + + + + + + + + + + + AGE + + + + + + + + + + + + + + + + + + + + DIVERS + + + + + + + + + + FILTER_RESULT_NB + + true + VTL + + false + + + FILTER_RESULT_PRENOM + + true + VTL + + PRENOM + false + + + IND_MAJEUR + + if nvl(AGE,0) > 17 then 1 else 0 + VTL + + AGE + PRENOM + true + + + FILTER_RESULT_AGE + + true + VTL + + AGE + false + + + FILTER_RESULT_DIVERS + + (SUM_MAJEUR > 0) + VTL + + SUM_MAJEUR + false + + + SUM_MAJEUR + + sum(IND_MAJEUR) + VTL + + IND_MAJEUR + AGE + true + + + SUM_AGE + + sum(AGE) + VTL + + AGE + false + + + MIN_AGE + + min(AGE) + VTL + + AGE + false + + + + (SUM_MAJEUR > 0) + + + (SUM_MAJEUR > 0) + + + (SUM_MAJEUR > 0) + + + + + cast(NB,integer) + PRENOM + AGE + + +