Skip to content

Commit

Permalink
Merge pull request #172 from InseeFr/develop
Browse files Browse the repository at this point in the history
feat: questionnaire composition + restricted stamp properties
  • Loading branch information
ORogel authored Jun 5, 2023
2 parents d9b7939 + 173c46d commit 6bec4cc
Show file tree
Hide file tree
Showing 67 changed files with 11,288 additions and 367 deletions.
53 changes: 27 additions & 26 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
<groupId>fr.insee</groupId>
<artifactId>Pogues-BO</artifactId>
<packaging>war</packaging>
<version>4.0.8</version>

<version>4.1.0</version>

<name>Pogues-BO</name>

<properties>
Expand All @@ -33,7 +35,6 @@
<sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
<sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
<sonar.language>java</sonar.language>
<sonar.jacoco.reportPath>${project.basedir}/../target/jacoco.exec</sonar.jacoco.reportPath>
<argLine>-Xms256m -Xmx512m -XX:MaxPermSize=128m -ea -Dfile.encoding=UTF-8</argLine>
</properties>

Expand Down Expand Up @@ -175,6 +176,11 @@
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.moxy</artifactId>
<version>2.6.0</version>
</dependency>
</dependencies>

<build>
Expand All @@ -185,29 +191,25 @@
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.version}</version>
<executions>
<!-- Prepare the property pointing to the JaCoCo runtime agent which is
passed as VM argument when the Maven Surefire plugin is executed. -->
<execution>
<id>pre-unit-test</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<!-- Set the name of the property containing the settings for JaCoCo
runtime agent. -->
<propertyName>surefireArgLine</propertyName>
<append>true</append>
</configuration>
</execution>
<execution>
<id>post-unit-test</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
<executions>
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<goals>
<goal>report</goal>
</goals>
<configuration>
<formats>
<format>XML</format>
</formats>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
Expand All @@ -223,5 +225,4 @@

</build>


</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package fr.insee.pogues.exception;

/**
* Exception thrown if an error occurs during questionnaire de-referencing (composition feature).
*/
public class DeReferencingException extends Exception {

public DeReferencingException(String message, Exception e) {
super(message, e);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package fr.insee.pogues.exception;

public class IllegalFlowControlException extends Exception {

public IllegalFlowControlException(String message) {
super(message);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package fr.insee.pogues.exception;

public class IllegalIterationException extends Exception {

public IllegalIterationException(String message) {
super(message);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package fr.insee.pogues.exception;

/** Thrown when a referenced questionnaire is null when doing questionnaire de-referencing. */
public class NullReferenceException extends Exception {

public NullReferenceException(String message) {
super(message);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package fr.insee.pogues.exception;

public class PoguesDeserializationException extends Exception {

public PoguesDeserializationException(String message, Exception e) {
super(message, e);
}

public PoguesDeserializationException(String message) {
super(message);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package fr.insee.pogues.persistence.service;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;

public interface VariablesService {

/**
* Used for pogues frontend
* @param id questionnaire id
* @return variables as json string with caveats from pogues-model (like format for datedatatype, ...)
*/
String getVariablesByQuestionnaire(String id);

/**
* Used for public enemy, delivers
* @param id
* @return variables as json directly from DB
*/
JSONArray getVariablesByQuestionnaireForPublicEnemy(String id);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package fr.insee.pogues.persistence.service;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamSource;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.eclipse.persistence.jaxb.MarshallerProperties;
import org.eclipse.persistence.jaxb.UnmarshallerProperties;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import fr.insee.pogues.model.Questionnaire;
import fr.insee.pogues.persistence.query.QuestionnairesServiceQuery;

@Service
@Slf4j
public class VariablesServiceImpl implements VariablesService {

private static final Logger logger = LogManager.getLogger(VariablesServiceImpl.class);

@Autowired
JdbcTemplate jdbcTemplate;

@Autowired
private QuestionnairesServiceQuery questionnaireServiceQuery;

public VariablesServiceImpl() {}

public VariablesServiceImpl(QuestionnairesServiceQuery questionnairesServiceQuery) {
this.questionnaireServiceQuery = questionnairesServiceQuery;
}

public JSONArray getVariablesByQuestionnaireForPublicEnemy(String id){
try {
JSONObject questionnaire = questionnaireServiceQuery.getQuestionnaireByID(id);
// We test the existence of the questionnaire in repository
if (questionnaire != null) {
JSONObject variables = (JSONObject) questionnaire.get("Variables");
return (JSONArray) variables.get("Variable");
}
} catch (Exception e) {
log.error("Exception occurred when trying to get variables from questionnaire with id={}", id, e);
}
return null;
}

public String getVariablesByQuestionnaire(String id){
StreamSource json = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
JSONObject questionnaire = questionnaireServiceQuery.getQuestionnaireByID(id);
// We test the existence of the questionnaire in repository
if (questionnaire != null) {
logger.info("Deserializing questionnaire ");
JAXBContext context = JAXBContext.newInstance(Questionnaire.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json");
unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
try(InputStream inQuestionnaire = new ByteArrayInputStream(questionnaire.toString().getBytes())){
json = new StreamSource(inQuestionnaire);
Questionnaire questionnaireJava = unmarshaller.unmarshal(json, Questionnaire.class).getValue();
logger.info("Questionnaire " + questionnaireJava.getId() + " successfully deserialized");
logger.info("Serializing variables for questionnaire {}", questionnaireJava.getId());
JAXBContext context2 = JAXBContext.newInstance(Questionnaire.Variables.class);
Marshaller marshaller = context2.createMarshaller();
marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/json");
// Set it to true if you need to include the JSON root element in the JSON output
marshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, true);
// Set it to true if you need the JSON output to formatted
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
// Marshal the questionnaire object to JSON and put the output in a string
marshaller.marshal(questionnaireJava.getVariables(), baos);
}
return baos.toString(StandardCharsets.UTF_8);
}
} catch (Exception e) {
log.error("Exception occurred when trying to get variables from questionnaire with id={}", id, e);
} finally {
IOUtils.closeQuietly(baos);
}
return null;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package fr.insee.pogues.transforms.visualize;

import fr.insee.pogues.transforms.Transformer;

public interface PoguesJSONToPoguesJSONDeref extends Transformer {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package fr.insee.pogues.transforms.visualize;

import fr.insee.pogues.exception.NullReferenceException;
import fr.insee.pogues.model.Questionnaire;
import fr.insee.pogues.persistence.service.QuestionnairesService;
import fr.insee.pogues.utils.PoguesDeserializer;
import fr.insee.pogues.utils.PoguesSerializer;
import fr.insee.pogues.transforms.visualize.composition.QuestionnaireComposition;
import fr.insee.pogues.utils.json.JSONFunctions;
import org.apache.commons.io.IOUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;

@Service
public class PoguesJSONToPoguesJSONDerefImpl implements PoguesJSONToPoguesJSONDeref{

static final Logger logger = LogManager.getLogger(PoguesJSONToPoguesJSONDerefImpl.class);

private static final String NULL_INPUT_MESSAGE = "Null input";
private static final String NULL_OUTPUT_MESSAGE = "Null output";

@Autowired
QuestionnairesService questionnairesService;

public PoguesJSONToPoguesJSONDerefImpl() {}

public PoguesJSONToPoguesJSONDerefImpl(QuestionnairesService questionnairesService) {
this.questionnairesService = questionnairesService;
}

@Override
public void transform(InputStream input, OutputStream output, Map<String, Object> params, String surveyName) throws Exception {
if (null == input) {
throw new NullPointerException(NULL_INPUT_MESSAGE);
}
if (null == output) {
throw new NullPointerException(NULL_OUTPUT_MESSAGE);
}
String jsonDeref = transform(input, params, surveyName);
output.write(jsonDeref.getBytes(StandardCharsets.UTF_8));
}

@Override
public String transform(InputStream input, Map<String, Object> params, String surveyName) throws Exception {
if (null == input) {
throw new NullPointerException(NULL_INPUT_MESSAGE);
}
return transform(IOUtils.toString(input, StandardCharsets.UTF_8), params, surveyName);
}

@Override
public String transform(String input, Map<String, Object> params, String surveyName) throws Exception {
if (null == input) {
throw new NullPointerException(NULL_INPUT_MESSAGE);
}
// TODO: This parameter could be replaced by logical check in back-office
// (when Pogues-Model supports "childQuestionnaireRef")
if (!(boolean) params.get("needDeref")) {
logger.info("No de-referencing needed");
return input;
}
Questionnaire questionnaire = transformAsQuestionnaire(input);
return PoguesSerializer.questionnaireJavaToString(questionnaire);
}

public Questionnaire transformAsQuestionnaire(String input) throws Exception {
if (null == input) {
throw new NullPointerException(NULL_INPUT_MESSAGE);
}
// Parse Pogues json questionnaire
JSONParser parser = new JSONParser();
JSONObject jsonQuestionnaire = (JSONObject) parser.parse(input);
// Get referenced questionnaire identifiers
// TODO: The "childQuestionnaireRef" in the json should be supported by Pogues-Model
List<String> references = JSONFunctions.getChildReferencesFromQuestionnaire(jsonQuestionnaire);
// Deserialize json into questionnaire object
Questionnaire questionnaire = PoguesDeserializer.questionnaireToJavaObject(jsonQuestionnaire);
//
deReference(references, questionnaire);
logger.info("Sequences inserted");
//
return questionnaire;
}

private void deReference(List<String> references, Questionnaire questionnaire) throws Exception {
for (String reference : references) {
JSONObject referencedJsonQuestionnaire = questionnairesService.getQuestionnaireByID(reference);
if (referencedJsonQuestionnaire == null) {
throw new NullReferenceException(String.format(
"Null reference behind reference '%s' in questionnaire '%s'.",
reference, questionnaire.getId()));
} else {
Questionnaire referencedQuestionnaire = PoguesDeserializer.questionnaireToJavaObject(referencedJsonQuestionnaire);
// Coherence check
if (! reference.equals(referencedQuestionnaire.getId())) {
logger.warn("Reference '{}' found in questionnaire '{}' mismatch referenced questionnaire's id '{}'",
reference, questionnaire.getId(), referencedQuestionnaire.getId());
}
//
QuestionnaireComposition.insertReference(questionnaire, referencedQuestionnaire);
}
}
}

}
Loading

0 comments on commit 6bec4cc

Please sign in to comment.