Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/linked loop on referenced #160

Merged
merged 11 commits into from
Apr 27, 2023
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 {
nsenave marked this conversation as resolved.
Show resolved Hide resolved

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

}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ public class VariablesServiceImpl implements VariablesService {
@Autowired
private QuestionnairesServiceQuery questionnaireServiceQuery;

public VariablesServiceImpl() {}

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

public JSONArray getVariablesByQuestionnaireForPublicEnemy(String id){
try {
JSONObject questionnaire = questionnaireServiceQuery.getQuestionnaireByID(id);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package fr.insee.pogues.transforms.visualize.composition;

import fr.insee.pogues.exception.DeReferencingException;
import fr.insee.pogues.model.Questionnaire;

/**
* Interface for processing step when de-referencing a questionnaire.
*/
public interface CompositionStep {

/**
* Update questionnaire content with referenced questionnaire given.
* @param questionnaire Referencing questionnaire.
* @param referencedQuestionnaire Referenced questionnaire.
* @throws DeReferencingException if an error occurs during the de-referencing step.
*/
void apply(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) throws DeReferencingException;

}

This file was deleted.

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

import fr.insee.pogues.model.CodeLists;
import fr.insee.pogues.model.Questionnaire;
import lombok.extern.slf4j.Slf4j;

/**
* Implementation of CompositionStep to insert code lists of a referenced questionnaire.
*/
@Slf4j
class InsertCodeLists implements CompositionStep {

/**
* Insert code lists of the referenced questionnaire in the referencing questionnaire.
* @param questionnaire Referencing questionnaire.
* @param referencedQuestionnaire Referenced questionnaire.
*/
@Override
public void apply(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) {
CodeLists refCodeLists = referencedQuestionnaire.getCodeLists();
if (refCodeLists != null) {
nsenave marked this conversation as resolved.
Show resolved Hide resolved
questionnaire.setCodeLists(new CodeLists());
questionnaire.getCodeLists().getCodeList().addAll(refCodeLists.getCodeList());
log.info("Code lists from '{}' inserted in '{}'", referencedQuestionnaire.getId(), questionnaire.getId());
} else {
log.info("No code lists in referenced questionnaire '{}'", referencedQuestionnaire.getId());
}

}

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

import fr.insee.pogues.model.Questionnaire;
import lombok.extern.slf4j.Slf4j;

/**
* Implementation of CompositionStep to insert flow controls of a referenced questionnaire.
*/
@Slf4j
class InsertFlowControls implements CompositionStep {

/**
* Insert flow controls of the referenced questionnaire in the referencing questionnaire.
* @param questionnaire Referencing questionnaire.
* @param referencedQuestionnaire Referenced questionnaire.
*/
@Override
public void apply(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) {
questionnaire.getFlowControl().addAll(referencedQuestionnaire.getFlowControl());
log.info("FlowControl from '{}' inserted in '{}'", referencedQuestionnaire.getId(), questionnaire.getId());
}

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

import fr.insee.pogues.model.Questionnaire;
import lombok.extern.slf4j.Slf4j;

/**
* Implementation of CompositionStep to insert iterations of a referenced questionnaire.
*/
@Slf4j
class InsertIterations implements CompositionStep {

/**
* Insert iterations of the referenced questionnaire in the referencing questionnaire.
* @param questionnaire Referencing questionnaire.
* @param referencedQuestionnaire Referenced questionnaire.
*/
@Override
public void apply(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) {
nsenave marked this conversation as resolved.
Show resolved Hide resolved
Questionnaire.Iterations refIterations = referencedQuestionnaire.getIterations();
if (refIterations != null) {
if (questionnaire.getIterations() == null)
questionnaire.setIterations(new Questionnaire.Iterations());
questionnaire.getIterations().getIteration().addAll(refIterations.getIteration());
log.info("Iterations from '{}' inserted in '{}'", referencedQuestionnaire.getId(), questionnaire.getId());
} else {
log.info("No iterations in referenced questionnaire '{}'", referencedQuestionnaire.getId());
}
}

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

import fr.insee.pogues.exception.DeReferencingException;
import fr.insee.pogues.model.ComponentType;
import fr.insee.pogues.model.Questionnaire;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -9,19 +10,18 @@
import static fr.insee.pogues.utils.PoguesModelUtils.getSequences;

/**
* Methods to insert and update sequence objects when de-referencing a questionnaire.
* Implementation of CompositionStep to replace questionnaire reference by its sequences.
*/
@Slf4j
class SequenceComposition {

private SequenceComposition() {}
class InsertSequences implements CompositionStep {

/**
* Replace questionnaire reference by its sequences.
* @param questionnaire Referencing questionnaire.
* @param referencedQuestionnaire Referenced questionnaire.
*/
static void insertSequences(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) {
@Override
public void apply(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) {
//
List<ComponentType> refSequences = getSequences(referencedQuestionnaire);
int indexOfModification = 0;
Expand All @@ -38,6 +38,8 @@ static void insertSequences(Questionnaire questionnaire, Questionnaire reference
for (int i=0; i<refSequences.size();i++) {
questionnaire.getChild().add(indexOfModification, referencedQuestionnaire.getChild().get(refSequences.size()-1-i));
}
//
log.info("Sequences from '{}' inserted in '{}'", referencedQuestionnaire.getId(), questionnaire.getId());
}

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

import fr.insee.pogues.exception.DeReferencingException;
import fr.insee.pogues.model.Questionnaire;
import lombok.extern.slf4j.Slf4j;

/**
* Implementation of CompositionStep to insert variables of a referenced questionnaire.
*/
@Slf4j
class InsertVariables implements CompositionStep {

/**
* Insert variables of the referenced questionnaire in the referencing questionnaire.
* @param questionnaire Referencing questionnaire.
* @param referencedQuestionnaire Referenced questionnaire.
*/
@Override
public void apply(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) {
questionnaire.getVariables().getVariable().addAll(referencedQuestionnaire.getVariables().getVariable());
log.info("Variables from '{}' inserted in '{}'", referencedQuestionnaire.getId(), questionnaire.getId());
}

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

import fr.insee.pogues.exception.IllegalFlowControlException;
import fr.insee.pogues.exception.IllegalIterationException;
import fr.insee.pogues.model.CodeLists;
import fr.insee.pogues.model.FlowControlType;
import fr.insee.pogues.model.IterationType;
import fr.insee.pogues.exception.DeReferencingException;
import fr.insee.pogues.model.Questionnaire;
import lombok.extern.slf4j.Slf4j;

import static fr.insee.pogues.transforms.visualize.composition.FilterComposition.updateFlowControlBounds;
import static fr.insee.pogues.transforms.visualize.composition.LoopComposition.updateIterationBounds;
import static fr.insee.pogues.transforms.visualize.composition.LoopComposition.updateReferencedVariablesScope;
import static fr.insee.pogues.transforms.visualize.composition.SequenceComposition.insertSequences;

/**
* Class for the composition feature.
* Contains the logic to de-reference a questionnaire that contains references.
* De-referencing consists in replacing questionnaire references by their content.
* Note: 'composition' and 'de-referencing' words are used interchangeably.
*/
@Slf4j
public class QuestionnaireComposition {

private QuestionnaireComposition() {}

/**
* Replace referenced questionnaire by its component. Update elements that are impacted.
* @param questionnaire Referencing questionnaire.
* @param referencedQuestionnaire Referenced questionnaire.
* @throws IllegalFlowControlException if one of the FlowControl object involved is invalid.
* @throws IllegalIterationException if one of the Iteration object involved is invalid.
* Inner class of the composition class designed to chain de-referencing steps.
*/
public static void insertReference(Questionnaire questionnaire, Questionnaire referencedQuestionnaire)
throws IllegalFlowControlException, IllegalIterationException {
//
String id = questionnaire.getId();
String reference = referencedQuestionnaire.getId();
log.info("Starting de-referencing of questionnaire '{}' in questionnaire '{}'", reference, id);

// Update the scope of the referenced questionnaire variables
if (questionnaire.getIterations() != null)
updateReferencedVariablesScope(questionnaire, referencedQuestionnaire);

// Add sequences
insertSequences(questionnaire, referencedQuestionnaire);
log.info("Sequences from '{}' inserted in '{}'", reference, id);

// Add variables
questionnaire.getVariables().getVariable().addAll(referencedQuestionnaire.getVariables().getVariable());
log.info("Variables from '{}' inserted in '{}'", reference, id);

// Add code lists
CodeLists refCodeLists = referencedQuestionnaire.getCodeLists();
if (refCodeLists != null) {
questionnaire.setCodeLists(new CodeLists());
questionnaire.getCodeLists().getCodeList().addAll(refCodeLists.getCodeList());
log.info("Code lists from '{}' inserted in '{}'", reference, id);
} else {
log.info("No code lists in referenced questionnaire '{}'", reference);
static class DeReferencingPipeline {
Questionnaire questionnaire;
Questionnaire referencedQuestionnaire;
private DeReferencingPipeline(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) {
this.questionnaire = questionnaire;
this.referencedQuestionnaire = referencedQuestionnaire;
}

// Update filters in referencing questionnaire
for (FlowControlType flowControlType : questionnaire.getFlowControl()) {
updateFlowControlBounds(referencedQuestionnaire, flowControlType);
/**
* Return an instance of de-referencing pipeline.
* @param questionnaire Referencing questionnaire.
* @param referencedQuestionnaire Referenced questionnaire.
* @return A DeReferencingPipeline instance.
*/
static DeReferencingPipeline start(Questionnaire questionnaire, Questionnaire referencedQuestionnaire) {
log.info("Starting de-referencing of questionnaire '{}' in questionnaire '{}'",
referencedQuestionnaire.getId(), questionnaire.getId());
return new DeReferencingPipeline(questionnaire, referencedQuestionnaire);
}
log.info("Flow controls' bounds updated in '{}' when de-referencing '{}'", id, reference);

// Add flow controls (filters)
questionnaire.getFlowControl().addAll(referencedQuestionnaire.getFlowControl());
log.info("FlowControl from '{}' inserted in '{}'", reference, id);

// Update loops in referencing questionnaire
if (questionnaire.getIterations() != null) {
for (IterationType iterationType : questionnaire.getIterations().getIteration()) {
updateIterationBounds(referencedQuestionnaire, iterationType);
}
log.info("Iterations' bounds updated in '{}' when de-referencing '{}'", id, reference);
}

// Add iterations (loops)
Questionnaire.Iterations refIterations = referencedQuestionnaire.getIterations();
if (refIterations != null) {
questionnaire.setIterations(new Questionnaire.Iterations());
questionnaire.getIterations().getIteration().addAll(refIterations.getIteration());
log.info("Iterations from '{}' inserted in '{}'", reference, id);
} else {
log.info("No iterations in referenced questionnaire '{}'", reference);
/**
* Applies the composition step processing given. This method can be chained.
* @param compositionStep An implementation of the CompositionStep interface.
* @return The DeReferencingPipeline instance.
*/
DeReferencingPipeline then(CompositionStep compositionStep) throws DeReferencingException {
compositionStep.apply(questionnaire, referencedQuestionnaire);
return this;
}
}

// Component group is not updated since it is not used by eno generation
/**
* Replace referenced questionnaire by its component. Update elements that are impacted.
* Note: Component group is not updated since it is not used by eno generation.
* @param questionnaire Referencing questionnaire.
* @param referencedQuestionnaire Referenced questionnaire.
* @throws DeReferencingException if an error occurs during de-referencing.
*/
public static void insertReference(Questionnaire questionnaire, Questionnaire referencedQuestionnaire)
throws DeReferencingException {
//
DeReferencingPipeline.start(questionnaire, referencedQuestionnaire)
.then(new UpdateReferencedVariablesScope())
.then(new InsertSequences())
.then(new InsertVariables())
.then(new InsertCodeLists())
.then(new UpdateFlowControlBounds())
.then(new InsertFlowControls())
.then(new UpdateIterationBounds())
.then(new InsertIterations());
//
log.info("Finished de-referencing of questionnaire '{}' in questionnaire '{}'",
referencedQuestionnaire.getId(), questionnaire.getId());
}

}
Loading