1 package fr.ifremer.quadrige3.synchro.service.client;
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 import com.google.common.base.Joiner;
27 import com.google.common.base.Splitter;
28 import com.google.common.io.Files;
29 import fr.ifremer.common.synchro.service.SynchroResult;
30 import fr.ifremer.quadrige3.core.config.QuadrigeConfiguration;
31 import fr.ifremer.quadrige3.core.dao.technical.Assert;
32 import fr.ifremer.quadrige3.core.dao.technical.Dates;
33 import fr.ifremer.quadrige3.core.exception.QuadrigeTechnicalException;
34 import fr.ifremer.quadrige3.synchro.meta.data.DataSynchroTables;
35 import fr.ifremer.quadrige3.synchro.service.client.vo.SynchroClientExportResult;
36 import fr.ifremer.quadrige3.synchro.service.client.vo.SynchroClientExportToFileResult;
37 import fr.ifremer.quadrige3.synchro.service.client.vo.SynchroClientImportFromFileResult;
38 import fr.ifremer.quadrige3.synchro.service.client.vo.SynchroClientImportResult;
39 import fr.ifremer.quadrige3.synchro.service.data.DataSynchroContext;
40 import fr.ifremer.quadrige3.synchro.service.referential.ReferentialSynchroContext;
41 import fr.ifremer.quadrige3.synchro.vo.SynchroDateOperatorVO;
42 import fr.ifremer.quadrige3.synchro.vo.SynchroExportContextVO;
43 import org.apache.commons.collections4.CollectionUtils;
44 import org.apache.commons.io.FileUtils;
45 import org.apache.commons.lang3.StringUtils;
46 import org.apache.commons.logging.Log;
47 import org.apache.commons.logging.LogFactory;
48 import org.nuiton.i18n.I18n;
49 import org.springframework.context.annotation.Lazy;
50 import org.springframework.stereotype.Service;
51
52 import javax.annotation.Resource;
53 import java.io.File;
54 import java.io.FileWriter;
55 import java.io.IOException;
56 import java.nio.charset.Charset;
57 import java.text.DateFormat;
58 import java.text.SimpleDateFormat;
59 import java.util.Date;
60 import java.util.Set;
61
62
63
64
65
66
67 @Service("synchroHistoryService")
68 @Lazy
69 public class SynchroHistoryServiceImpl implements SynchroHistoryService {
70 private static final Log log = LogFactory.getLog(SynchroHistoryServiceImpl.class);
71
72 private static final String HISTORY_LOG_FILE = "synchro.txt";
73
74
75 static {
76 I18n.n("quadrige3.synchro.service.history.filter.date.EQUALS");
77 I18n.n("quadrige3.synchro.service.history.filter.date.BETWEEN");
78 I18n.n("quadrige3.synchro.service.history.filter.date.BEFORE");
79 I18n.n("quadrige3.synchro.service.history.filter.date.BEFORE_OR_EQUALS");
80 I18n.n("quadrige3.synchro.service.history.filter.date.AFTER");
81 I18n.n("quadrige3.synchro.service.history.filter.date.AFTER_OR_EQUALS");
82 }
83
84 @Resource
85 private QuadrigeConfiguration configuration;
86
87
88 @Override
89 public void save(int userId, SynchroClientImportResult result) {
90 Assert.notNull(result);
91 StringBuilder messageBuilder = new StringBuilder();
92
93 boolean withReferential = result.getReferentialResult() != null && result.getReferentialResult().getTotalTreated() > 0;
94 boolean withData = result.getDataResult() != null && result.getDataResult().getTotalTreated() > 0;
95
96
97 if (!withReferential && !withData) {
98 return;
99 }
100
101 Date referentialUpdateDate = result.getReferentialSynchronizationDate();
102 Date dataUpdateDate = result.getDataSynchronizationDate();
103
104 DateFormat dateFormat = DateFormat.getDateTimeInstance(SimpleDateFormat.LONG, SimpleDateFormat.LONG);
105
106
107 if (withData) {
108 Set<String> programCodes = result.getDataContext().getProgramCodes();
109 String programCodesStr = CollectionUtils.isEmpty(programCodes) ? "" : String.join(", ", programCodes);
110
111 messageBuilder.append(I18n.t("quadrige3.synchro.service.history.import", dateFormat.format(dataUpdateDate)));
112 messageBuilder.append("\n\t").append(I18n.t("quadrige3.synchro.service.history.import.importedPrograms", CollectionUtils.size(programCodes), programCodesStr));
113 }
114
115
116 else {
117 messageBuilder.append(I18n.t("quadrige3.synchro.service.history.import.referential",
118 dateFormat.format(referentialUpdateDate)));
119 }
120
121
122 if (messageBuilder.length() > 0) {
123 appendToHistoryFile(userId, messageBuilder.toString());
124 }
125 }
126
127
128 @Override
129 public void save(int userId, SynchroClientImportFromFileResult result) {
130 Assert.notNull(result);
131 Assert.notNull(result.getFile());
132 StringBuilder messageBuilder = new StringBuilder();
133
134 boolean withReferential = result.getReferentialResult() != null && result.getReferentialResult().getTotalTreated() > 0;
135 boolean withData = result.getDataResult() != null && result.getDataResult().getTotalTreated() > 0;
136
137 Date nowDate = new Date();
138 Date referentialUpdateDate = result.getReferentialSynchronizationDate();
139 if (referentialUpdateDate == null) {
140 referentialUpdateDate = nowDate;
141 }
142 Date dataUpdateDate = result.getDataSynchronizationDate();
143 if (dataUpdateDate == null) {
144 dataUpdateDate = nowDate;
145 }
146
147 DateFormat dateFormat = DateFormat.getDateTimeInstance(SimpleDateFormat.LONG, SimpleDateFormat.LONG);
148
149
150 if (withData && withReferential) {
151 messageBuilder.append(I18n.t("quadrige3.synchro.service.history.importFromFile", dateFormat.format(dataUpdateDate), result.getFile()));
152 messageBuilder.append("\n\t").append(I18n.t("quadrige3.synchro.service.history.importFromFile.data"));
153 messageBuilder.append("\n\t").append(I18n.t("quadrige3.synchro.service.history.importFromFile.referential"));
154 }
155
156
157 else if (withData) {
158 messageBuilder.append(I18n.t("quadrige3.synchro.service.history.importFromFile", dateFormat.format(dataUpdateDate), result.getFile()));
159 messageBuilder.append("\n\t").append(I18n.t("quadrige3.synchro.service.history.importFromFile.data"));
160 }
161
162
163 else if (withReferential) {
164 messageBuilder.append(I18n.t("quadrige3.synchro.service.history.importFromFile", dateFormat.format(referentialUpdateDate), result.getFile()));
165 messageBuilder.append("\n\t").append(I18n.t("quadrige3.synchro.service.history.importFromFile.referential"));
166 }
167
168
169 else {
170 messageBuilder.append(I18n.t("quadrige3.synchro.service.history.importFromFile", dateFormat.format(nowDate), result.getFile()));
171 messageBuilder.append("\n\t").append(I18n.t("quadrige3.synchro.service.history.importFromFile.noData"));
172 }
173
174
175 if (messageBuilder.length() > 0) {
176 appendToHistoryFile(userId, messageBuilder.toString());
177 }
178 }
179
180
181 @Override
182 public void save(int userId, SynchroClientExportResult result) {
183 Assert.notNull(result);
184
185 saveExportServerResult(userId, result.getServerResult(), result.getDataContext().getProgramCodes());
186 }
187
188
189 @Override
190 public void saveExportServerResult(int userId, SynchroResult serverResult, Set<String> programCodes) {
191 StringBuilder messageBuilder = new StringBuilder();
192
193 boolean hasUpdates = serverResult != null && serverResult.getTotalTreated() > 0;
194
195
196 if (!hasUpdates) {
197 return;
198 }
199
200
201 DateFormat dateFormat = DateFormat.getDateTimeInstance(SimpleDateFormat.LONG, SimpleDateFormat.LONG);
202
203
204
205 int surveyNbInserts = serverResult.getNbInserts(DataSynchroTables.SURVEY.name());
206 int surveyNbUpdates = serverResult.getNbUpdates(DataSynchroTables.SURVEY.name());
207 int surveyNbDeletes = serverResult.getNbDeletes(DataSynchroTables.SURVEY.name());
208
209 String rejectedRows = serverResult.getRejectedRows(DataSynchroTables.SURVEY.name());
210 int surveyNbRejects = countErrorItems(rejectedRows);
211
212 String programCodesStr = CollectionUtils.isEmpty(programCodes)
213 ? ""
214 : Joiner.on(", ").join(programCodes);
215
216 messageBuilder.append(I18n.t("quadrige3.synchro.service.history.export", dateFormat.format(new Date())));
217 messageBuilder.append("\n\t").append(I18n.t("quadrige3.synchro.service.history.export.exportedPrograms", CollectionUtils.size(programCodes), programCodesStr));
218 messageBuilder.append("\n\t").append(I18n.t("quadrige3.synchro.service.history.export.createdSurveys", surveyNbInserts));
219 messageBuilder.append("\n\t").append(I18n.t("quadrige3.synchro.service.history.export.updatedSurveys", surveyNbUpdates));
220 messageBuilder.append("\n\t").append(I18n.t("quadrige3.synchro.service.history.export.deletedSurveys", surveyNbDeletes));
221 messageBuilder.append("\n\t").append(I18n.t("quadrige3.synchro.service.history.export.rejectedSurveys", surveyNbRejects));
222
223
224 if (messageBuilder.length() > 0) {
225 appendToHistoryFile(userId, messageBuilder.toString());
226 }
227 }
228
229
230 @Override
231 public void save(int userId, SynchroClientExportToFileResult result) {
232 Assert.notNull(result);
233 Assert.notNull(result.getFile());
234 StringBuilder messageBuilder = new StringBuilder();
235
236 boolean withReferential = result.getReferentialResult() != null && result.getReferentialResult().getTotalTreated() > 0;
237 boolean withData = result.getDataResult() != null && result.getDataResult().getTotalTreated() > 0;
238
239
240 if (!withReferential && !withData) {
241 return;
242 }
243
244
245 DateFormat dateFormat = DateFormat.getDateTimeInstance(SimpleDateFormat.LONG, SimpleDateFormat.LONG);
246
247
248 if (withData) {
249
250 DataSynchroContext dataContext = result.getDataContext();
251 Set<String> programCodes = dataContext.getProgramCodes();
252 int surveyNbInserts = result.getDataResult().getNbInserts(DataSynchroTables.SURVEY.name());
253
254 StringBuilder filterMessageBuilder = new StringBuilder();
255
256
257 if (dataContext.isDirtyOnly()) {
258 filterMessageBuilder.append("\n\t")
259 .append(I18n.t("quadrige3.synchro.service.history.filter.withDirtyOnly"));
260 }
261
262
263 if (dataContext.getDataStartDate() != null) {
264 SynchroDateOperatorVO operator = dataContext.getDateOperator();
265 String datePattern = I18n.t("quadrige3.synchro.service.history.filter.date.pattern");
266 filterMessageBuilder.append("\n\t")
267 .append(I18n.t("quadrige3.synchro.service.history.filter.date." + operator.name(),
268 Dates.formatDate(dataContext.getDataStartDate(), datePattern),
269 Dates.formatDate(dataContext.getDataEndDate(), datePattern)));
270 }
271
272
273 if (CollectionUtils.isNotEmpty(programCodes)) {
274 String programCodesStr = CollectionUtils.isEmpty(programCodes)
275 ? ""
276 : Joiner.on(", ").join(programCodes);
277 filterMessageBuilder
278 .append("\n\t")
279 .append(I18n.t("quadrige3.synchro.service.history.filter.program",
280 CollectionUtils.size(programCodes),
281 programCodesStr));
282 }
283
284 messageBuilder.append(I18n.t("quadrige3.synchro.service.history.exportToFile",
285 dateFormat.format(new Date()),
286 result.getFile().getPath(),
287 filterMessageBuilder.toString()));
288 messageBuilder.append("\n\t").append(I18n.t("quadrige3.synchro.service.history.exportToFile.exportedSurveys", surveyNbInserts));
289 }
290
291
292 else if (withReferential) {
293 ReferentialSynchroContext referentialContext = result.getReferentialContext();
294 Set<String> programCodes = referentialContext.getProgramCodes();
295
296 StringBuilder filterMessageBuilder = new StringBuilder();
297
298
299 if (CollectionUtils.isNotEmpty(programCodes)) {
300 String programCodesStr = CollectionUtils.isEmpty(programCodes)
301 ? ""
302 : Joiner.on(", ").join(programCodes);
303 filterMessageBuilder
304 .append("\n\t")
305 .append(I18n.t("quadrige3.synchro.service.history.filter.program",
306 CollectionUtils.size(programCodes),
307 programCodesStr));
308 }
309
310
311 messageBuilder.append(I18n.t("quadrige3.synchro.service.history.exportToFile.referential",
312 dateFormat.format(new Date()),
313 result.getFile().getPath(),
314 filterMessageBuilder.toString()));
315 }
316
317
318 if (messageBuilder.length() > 0) {
319 appendToHistoryFile(userId, messageBuilder.toString());
320 }
321 }
322
323
324 @Override
325 public String getContent(int userId) {
326 File file = getHistoryFileByUserId(userId);
327 if (!file.exists()) {
328 return null;
329 }
330
331 try {
332 return FileUtils.readFileToString(file, Charset.defaultCharset());
333 } catch (IOException e) {
334 throw new QuadrigeTechnicalException(I18n.t("quadrige3.service.synchroHistory.readContent.failed"), e);
335 }
336 }
337
338
339 @Override
340 public File getHistoryFileByUserId(int userId) {
341 return new File(
342 configuration.getSynchronizationDirectory(),
343 new StringBuilder()
344 .append(userId)
345 .append(File.separator)
346 .append(HISTORY_LOG_FILE)
347 .toString());
348 }
349
350 @Override
351 public void saveExportError(int userId, SynchroExportContextVO exportContext, String message) {
352
353 StringBuilder messageBuilder = new StringBuilder();
354
355
356 DateFormat dateFormat = DateFormat.getDateTimeInstance(SimpleDateFormat.LONG, SimpleDateFormat.LONG);
357
358
359 String programCodesStr = CollectionUtils.isEmpty(exportContext.getDataProgramCodes())
360 ? ""
361 : Joiner.on(", ").join(exportContext.getDataProgramCodes());
362 messageBuilder.append(I18n.t("quadrige3.synchro.service.history.export.failed", dateFormat.format(new Date())));
363 messageBuilder.append("\n\t")
364 .append(I18n.t("quadrige3.synchro.service.history.export.exportedPrograms", CollectionUtils.size(exportContext.getDataProgramCodes()), programCodesStr));
365 messageBuilder.append("\n\t").append(I18n.t("quadrige3.synchro.service.history.export.error", message));
366
367
368 appendToHistoryFile(userId, messageBuilder.toString());
369 }
370
371
372
373
374
375
376
377
378
379
380
381
382
383 protected void appendToHistoryFile(int userId, String messageToAppend) {
384 File historyFile = getHistoryFileByUserId(userId);
385
386 try {
387
388
389 Files.createParentDirs(historyFile);
390
391 try (FileWriter fw = new FileWriter(historyFile, true)) {
392 fw.write('\n');
393 fw.write(messageToAppend);
394 fw.write('\n');
395 }
396 } catch (IOException e) {
397 throw new QuadrigeTechnicalException(I18n.t("quadrige3.synchro.service.history.error", historyFile.getPath()), e);
398 }
399 }
400
401
402
403
404
405
406
407
408
409
410 protected int countErrorItems(String rejectedRows) {
411 if (StringUtils.isBlank(rejectedRows)) {
412 return 0;
413 }
414 return Splitter.on('\n').trimResults().omitEmptyStrings().splitToList(rejectedRows).size();
415 }
416
417 }