-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathQuestionnaireMetadataService.java
More file actions
169 lines (148 loc) · 6.95 KB
/
Copy pathQuestionnaireMetadataService.java
File metadata and controls
169 lines (148 loc) · 6.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
package fr.insee.genesis.domain.service.metadata;
import fr.insee.bpm.exceptions.MetadataParserException;
import fr.insee.bpm.metadata.model.MetadataModel;
import fr.insee.bpm.metadata.model.Variable;
import fr.insee.bpm.metadata.model.VariableType;
import fr.insee.bpm.metadata.reader.ReaderUtils;
import fr.insee.bpm.metadata.reader.lunatic.LunaticReader;
import fr.insee.genesis.Constants;
import fr.insee.genesis.domain.model.metadata.QuestionnaireMetadataModel;
import fr.insee.genesis.domain.model.surveyunit.Mode;
import fr.insee.genesis.domain.ports.api.QuestionnaireMetadataApiPort;
import fr.insee.genesis.domain.ports.spi.QuestionnaireMetadataPersistancePort;
import fr.insee.genesis.exceptions.GenesisError;
import fr.insee.genesis.exceptions.GenesisException;
import fr.insee.genesis.infrastructure.utils.FileUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
import java.util.List;
@Service
@AllArgsConstructor
@Slf4j
public class QuestionnaireMetadataService implements QuestionnaireMetadataApiPort {
private static final String DDI_FILE_PATTERN = "ddi[\\w,\\s-]+\\.xml";
private static final String LUNATIC_FILE_PATTERN = "lunatic[\\w,\\s-]+\\.json";
QuestionnaireMetadataPersistancePort questionnaireMetadataPersistancePort;
@Override
public MetadataModel find(String questionnaireId, Mode mode) throws GenesisException {
List<QuestionnaireMetadataModel> questionnaireMetadataModels =
questionnaireMetadataPersistancePort.find(questionnaireId, mode);
if(questionnaireMetadataModels.isEmpty()){
throw new GenesisException(404, "Questionnaire metadata not found");
}
return questionnaireMetadataModels.getFirst().metadataModel();
}
public MetadataModel loadAndSaveIfNotExists(
String campaignName,
String questionnaireId,
Mode mode,
FileUtils fileUtils,
List<GenesisError> errors
) throws GenesisException {
List<QuestionnaireMetadataModel> storedMetadatas =
questionnaireMetadataPersistancePort.find(questionnaireId.toUpperCase(), mode);
if (!storedMetadatas.isEmpty()
&& storedMetadatas.getFirst().metadataModel() != null) {
return storedMetadatas.getFirst().metadataModel();
}
MetadataModel metadataModel =
readMetadatas(campaignName, mode.getModeName(), fileUtils, errors);
saveMetadata(questionnaireId.toUpperCase(), mode, metadataModel);
return metadataModel;
}
private void saveMetadata(String questionnaireId, Mode mode, MetadataModel metadataModel) {
questionnaireMetadataPersistancePort.save(
new QuestionnaireMetadataModel(
questionnaireId,
mode,
metadataModel
)
);
}
/**
* By folder defined by campaignName
* Attempt to parse DDI metadata first; if it fails, fall back to Lunatic parsing.
*
* @param campaignName name of the campaign
* @param modeName mode associated with the data
* @param fileUtils utility for file operations
* @param errors list to populate with errors
* @return VariablesMap or null if parsing fails
*/
private MetadataModel readMetadatas(String campaignName, String modeName, FileUtils fileUtils,
List<GenesisError> errors) throws GenesisException{
Path ddiFilePath;
MetadataModel metadataModel = null;
try {
ddiFilePath = fileUtils.findFile(String.format("%s/%s", fileUtils.getSpecFolder(campaignName), modeName), DDI_FILE_PATTERN);
metadataModel = parseMetadata(ddiFilePath.toString(), true);
} catch (RuntimeException e) {
//DDI file not found and already log - Go to next step
} catch (IOException e) {
log.warn("No DDI File found for {}, {} mode. Will try to use Lunatic...", campaignName, modeName);
}
if(metadataModel == null ){
log.warn("DDI not found or error occurred. Trying Lunatic metadata...for {}, {} mode", campaignName, modeName);
try {
Path lunaticFilePath = fileUtils.findFile(String.format("%s/%s", fileUtils.getSpecFolder(campaignName), modeName), LUNATIC_FILE_PATTERN);
return parseMetadata(lunaticFilePath.toString(), false);
} catch (Exception ex) {
log.error("Error reading Lunatic metadata file", ex);
errors.add(new GenesisError(ex.toString()));
return null;
}
}
if(!errors.isEmpty()){
throw new GenesisException(404, errors.getLast().getMessage());
}
return metadataModel;
}
/**
* Parse metadata file, either DDI or Lunatic, depending on the withDDI flag.
*
* @param metadataFilePath path to the metadata file
* @param withDDI true for DDI parsing, false for Lunatic parsing
* @return VariablesMap or null if an error occurs
*/
private MetadataModel parseMetadata(String metadataFilePath, boolean withDDI) {
try {
log.info("Try to read {} file: {}", withDDI ? "DDI" : "Lunatic", metadataFilePath);
if (withDDI) {
InputStream metadataInputStream = new FileInputStream(metadataFilePath);
MetadataModel metadataModel = ReaderUtils.getMetadataFromDDIAndLunatic(
Path.of(metadataFilePath).toFile().toURI().toURL().toString(),
metadataInputStream,metadataInputStream);
// Temporary solution
// the logic of adding variables from lunatic to the ones present in the DDI needs to be implemented in BPM
// (only in Kraftwerk for the moment)
for (String enoVar : Constants.getEnoVariables()){
metadataModel.getVariables().putVariable(new Variable(enoVar, metadataModel.getRootGroup(), VariableType.STRING));
}
return metadataModel;
} else {
return LunaticReader.getMetadataFromLunatic(
new FileInputStream(metadataFilePath));
}
} catch (MetadataParserException | IOException e) {
log.error("Error reading metadata file", e);
return null;
}
}
@Override
public void remove(String questionnaireId, Mode mode) {
questionnaireMetadataPersistancePort.remove(questionnaireId, mode);
}
@Override
public void save(String questionnaireId, Mode mode, MetadataModel metadataModel) {
questionnaireMetadataPersistancePort.save(new QuestionnaireMetadataModel(
questionnaireId,
mode,
metadataModel
));
}
}