1 package fr.ifremer.tutti.service.genericformat;
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 import com.google.common.base.Function;
28 import com.google.common.base.Preconditions;
29 import com.google.common.collect.ArrayListMultimap;
30 import com.google.common.collect.ImmutableSet;
31 import com.google.common.collect.Multimap;
32 import com.google.common.collect.Ordering;
33 import fr.ifremer.adagio.core.dao.referential.ObjectTypeCode;
34 import fr.ifremer.tutti.persistence.ProgressionModel;
35 import fr.ifremer.tutti.persistence.entities.data.CatchBatch;
36 import fr.ifremer.tutti.persistence.entities.data.Cruise;
37 import fr.ifremer.tutti.persistence.entities.data.Cruises;
38 import fr.ifremer.tutti.persistence.entities.data.FishingOperation;
39 import fr.ifremer.tutti.persistence.entities.data.SampleCategoryModel;
40 import fr.ifremer.tutti.persistence.entities.protocol.TuttiProtocol;
41 import fr.ifremer.tutti.persistence.entities.referential.Caracteristic;
42 import fr.ifremer.tutti.persistence.entities.referential.Gear;
43 import fr.ifremer.tutti.persistence.entities.referential.Person;
44 import fr.ifremer.tutti.persistence.entities.referential.TuttiReferentialEntity;
45 import fr.ifremer.tutti.persistence.entities.referential.Vessel;
46 import fr.ifremer.tutti.persistence.model.CruiseDataModel;
47 import fr.ifremer.tutti.service.PersistenceService;
48 import fr.ifremer.tutti.service.ValidationService;
49 import fr.ifremer.tutti.service.csv.CaracteristicValueParseException;
50 import fr.ifremer.tutti.service.csv.CaracteristicValueParserFormatter;
51 import fr.ifremer.tutti.service.genericformat.consumer.CsvConsumerForAccidentalCatch;
52 import fr.ifremer.tutti.service.genericformat.consumer.CsvConsumerForAttachment;
53 import fr.ifremer.tutti.service.genericformat.consumer.CsvConsumerForCatch;
54 import fr.ifremer.tutti.service.genericformat.consumer.CsvConsumerForGearCaracteristic;
55 import fr.ifremer.tutti.service.genericformat.consumer.CsvConsumerForIndividualObservation;
56 import fr.ifremer.tutti.service.genericformat.consumer.CsvConsumerForMarineLitter;
57 import fr.ifremer.tutti.service.genericformat.consumer.CsvConsumerForOperation;
58 import fr.ifremer.tutti.service.genericformat.consumer.CsvConsumerForParameter;
59 import fr.ifremer.tutti.service.genericformat.consumer.CsvConsumerForSampleCategory;
60 import fr.ifremer.tutti.service.genericformat.consumer.CsvConsumerForSurvey;
61 import fr.ifremer.tutti.service.genericformat.csv.AttachmentRow;
62 import fr.ifremer.tutti.service.genericformat.csv.RowWithCruiseContextSupport;
63 import fr.ifremer.tutti.service.referential.consumer.CsvConsumerForTemporaryGear;
64 import fr.ifremer.tutti.service.referential.consumer.CsvConsumerForTemporaryPerson;
65 import fr.ifremer.tutti.service.referential.consumer.CsvConsumerForTemporarySpecies;
66 import fr.ifremer.tutti.service.referential.consumer.CsvConsumerForTemporaryVessel;
67 import org.apache.commons.collections4.CollectionUtils;
68 import org.nuiton.decorator.Decorator;
69
70 import java.io.Closeable;
71 import java.io.File;
72 import java.io.Serializable;
73 import java.nio.file.Path;
74 import java.text.ParseException;
75 import java.util.Collection;
76 import java.util.Iterator;
77 import java.util.LinkedHashMap;
78 import java.util.LinkedHashSet;
79 import java.util.Map;
80 import java.util.Set;
81
82
83
84
85
86
87
88 public abstract class GenericFormatContextSupport implements Closeable, Iterable<GenericFormatImportCruiseContext> {
89
90 private final GenericFormatImportRequest importRequest;
91
92 private final ProgressionModel progressionModel;
93
94 private final Decorator<Cruise> cruiseDecorator;
95
96 private final Decorator<FishingOperation> fishingOperationDecorator;
97
98 private final GenericFormatImportEntityParserFactory importEntityParserFactory;
99
100 private final GenericFormatImportValidationHelper validationHelper;
101
102 private Set<String> archiveLayoutErrors;
103
104 private TuttiProtocol importedProtocol;
105
106 private SampleCategoryModel importedSampleCategoryModel;
107
108 private final GenericFormatCsvFileResult sampleCategoryFileResult;
109
110 private final GenericFormatReferentialImportResult<Gear, Integer> referentialTemporaryGearFileResult;
111
112 private final GenericFormatReferentialImportResult<Person, Integer> referentialTemporaryPersonFileResult;
113
114 private final GenericFormatReferentialSpeciesImportResult referentialTemporarySpeciesFileResult;
115
116 private final GenericFormatReferentialImportResult<Vessel, String> referentialTemporaryVesselFileResult;
117
118 private final GenericFormatFileResult protocolFileResult;
119
120 private final GenericFormatCsvFileResult surveyFileResult;
121
122 private final GenericFormatCsvFileResult accidentalCatchFileResult;
123
124 private final GenericFormatCsvFileResult individualObservationFileResult;
125
126 private final GenericFormatCsvFileResult marineLitterFileResult;
127
128 private final GenericFormatCsvFileResult catchFileResult;
129
130 private final GenericFormatCsvFileResult parameterFileResult;
131
132 private final GenericFormatCsvFileResult operationFileResult;
133
134 private final GenericFormatCsvFileResult gearCaracteristicFileResult;
135
136 private final GenericFormatCsvFileResult attachmentFileResult;
137
138 private final Map<String, GenericFormatImportCruiseContext> cruiseContexts;
139
140 private final Set<String> skippedCruisesNaturalId;
141
142 private String protocolOriginalName;
143
144 private final Multimap<String, AttachmentRow> attachmentRows;
145
146 protected abstract void onClose();
147
148 public GenericFormatContextSupport(GenericFormatImportRequest importRequest,
149 ProgressionModel progressionModel,
150 PersistenceService persistenceService,
151 Decorator<Cruise> cruiseDecorator,
152 Decorator<FishingOperation> fishingOperationDecorator) {
153
154 Preconditions.checkNotNull(importRequest);
155 Preconditions.checkNotNull(progressionModel);
156 Preconditions.checkNotNull(persistenceService);
157 Preconditions.checkNotNull(cruiseDecorator);
158 Preconditions.checkNotNull(fishingOperationDecorator);
159
160 this.importRequest = importRequest;
161 this.progressionModel = progressionModel;
162 this.cruiseDecorator = cruiseDecorator;
163 this.fishingOperationDecorator = fishingOperationDecorator;
164 this.importEntityParserFactory = new GenericFormatImportEntityParserFactory(persistenceService, this);
165 this.validationHelper = new GenericFormatImportValidationHelper(this, new ValidationService());
166 this.cruiseContexts = new LinkedHashMap<>();
167 this.skippedCruisesNaturalId = new LinkedHashSet<>();
168
169 GenericFormatArchive archive = importRequest.getArchive();
170
171 this.sampleCategoryFileResult = createFileResult(archive.getSampleCategoryModelPath(), true);
172
173 this.referentialTemporaryGearFileResult = createReferentialFileResult(archive.getTemporaryReferentialGearsPath());
174 this.referentialTemporaryPersonFileResult = createReferentialFileResult(archive.getTemporaryReferentialPersonsPath());
175 this.referentialTemporaryVesselFileResult = createReferentialFileResult(archive.getTemporaryReferentialVesselsPath());
176 File file = archive.getTemporaryReferentialSpeciesPath().toFile();
177 this.referentialTemporarySpeciesFileResult = new GenericFormatReferentialSpeciesImportResult(file.getName(), file.exists());
178 this.protocolFileResult = createFileResult(archive.getProtocolPath(), false);
179
180 this.surveyFileResult = createFileResult(archive.getSurveyPath(), true);
181 this.gearCaracteristicFileResult = createFileResult(archive.getGearCaracteristicsPath(), true);
182 this.operationFileResult = createFileResult(archive.getOperationPath(), true);
183 this.parameterFileResult = createFileResult(archive.getParameterPath(), true);
184 this.catchFileResult = createFileResult(archive.getCatchPath(), true);
185 this.marineLitterFileResult = createFileResult(archive.getMarineLitterPath(), true);
186 this.individualObservationFileResult = createFileResult(archive.getIndividualObservationPath(), true);
187 this.accidentalCatchFileResult = createFileResult(archive.getAccidentalCatchPath(), true);
188 this.attachmentFileResult = createFileResult(archive.getAttachmentFilePath(), true);
189
190 this.attachmentRows = ArrayListMultimap.create();
191 }
192
193 @Override
194 public final void close() {
195
196 try {
197
198 onClose();
199
200 } finally {
201
202 validationHelper.close();
203
204 for (GenericFormatImportCruiseContext cruiseContext : cruiseContexts.values()) {
205 cruiseContext.close();
206 }
207 cruiseContexts.clear();
208
209 }
210
211 }
212
213 @Override
214 public Iterator<GenericFormatImportCruiseContext> iterator() {
215 return ImmutableSet.copyOf(cruiseContexts.values()).iterator();
216 }
217
218 public boolean isArchiveLayoutValid() {
219 return CollectionUtils.isEmpty(archiveLayoutErrors);
220 }
221
222 public void setArchiveLayoutErrors(Set<String> archiveLayoutErrors) {
223 this.archiveLayoutErrors = archiveLayoutErrors;
224 }
225
226 public Set<String> getArchiveLayoutErrors() {
227 return ImmutableSet.copyOf(archiveLayoutErrors);
228 }
229
230 public GenericFormatCsvFileResult getSampleCategoryFileResult() {
231 return sampleCategoryFileResult;
232 }
233
234 public GenericFormatReferentialImportResult<Gear, Integer> getReferentialTemporaryGearFileResult() {
235 return referentialTemporaryGearFileResult;
236 }
237
238 public GenericFormatReferentialImportResult<Person, Integer> getReferentialTemporaryPersonFileResult() {
239 return referentialTemporaryPersonFileResult;
240 }
241
242 public GenericFormatReferentialSpeciesImportResult getReferentialTemporarySpeciesFileResult() {
243 return referentialTemporarySpeciesFileResult;
244 }
245
246 public GenericFormatReferentialImportResult<Vessel, String> getReferentialTemporaryVesselFileResult() {
247 return referentialTemporaryVesselFileResult;
248 }
249
250 public GenericFormatFileResult getProtocolFileResult() {
251 return protocolFileResult;
252 }
253
254 public GenericFormatCsvFileResult getSurveyFileResult() {
255 return surveyFileResult;
256 }
257
258 public GenericFormatCsvFileResult getGearCaracteristicFileResult() {
259 return gearCaracteristicFileResult;
260 }
261
262 public GenericFormatCsvFileResult getOperationFileResult() {
263 return operationFileResult;
264 }
265
266 public GenericFormatCsvFileResult getParameterFileResult() {
267 return parameterFileResult;
268 }
269
270 public GenericFormatCsvFileResult getCatchFileResult() {
271 return catchFileResult;
272 }
273
274 public GenericFormatCsvFileResult getMarineLitterFileResult() {
275 return marineLitterFileResult;
276 }
277
278 public GenericFormatCsvFileResult getIndividualObservationFileResult() {
279 return individualObservationFileResult;
280 }
281
282 public GenericFormatCsvFileResult getAccidentalCatchFileResult() {
283 return accidentalCatchFileResult;
284 }
285
286 public GenericFormatCsvFileResult getAttachmentFileResult() {
287 return attachmentFileResult;
288 }
289
290 public GenericFormatImportRequest getImportRequest() {
291 return importRequest;
292 }
293
294 public TuttiProtocol getImportedProtocol() {
295 return importedProtocol;
296 }
297
298 public void setImportedProtocol(TuttiProtocol importedProtocol) {
299 this.importedProtocol = importedProtocol;
300 }
301
302 public SampleCategoryModel getImportedSampleCategoryModel() {
303 return importedSampleCategoryModel;
304 }
305
306 public void setImportedSampleCategoryModel(SampleCategoryModel importedSampleCategoryModel) {
307 this.importedSampleCategoryModel = importedSampleCategoryModel;
308 }
309
310 public boolean isCruiseAlreadyImported(Cruise cruise) {
311
312 GenericFormatImportCruiseContext cruiseContext = getCruiseContext(cruise);
313 return cruiseContext != null;
314
315 }
316
317 public void addImportedCruise(Cruise cruise, CruiseDataModel selectedCruise, CruiseDataModel existingCruiseData, Set<FishingOperation> existingFishingOperations) {
318
319 String cruiseId = cruise.getId();
320
321 GenericFormatImportCruiseContext cruiseContext = new GenericFormatImportCruiseContext(cruise, selectedCruise, existingCruiseData, existingFishingOperations, cruiseDecorator.toString(cruise));
322 cruiseContexts.put(cruiseId, cruiseContext);
323
324 }
325
326 public void addSkippedCruise(Cruise cruise) {
327
328 String naturalId = Cruises.getNaturalId(cruise);
329 skippedCruisesNaturalId.add(naturalId);
330
331 }
332
333 public void addImportedFishingOperation(FishingOperation fishingOperation, CatchBatch catchBatch) {
334
335 GenericFormatImportCruiseContext cruiseContext = getCruiseContext(fishingOperation.getCruise());
336 String fishingOperationLabel = decorate(fishingOperation);
337 cruiseContext.addFishingOperation(fishingOperation, catchBatch, fishingOperationLabel);
338
339 }
340
341 public boolean isCruiseSkipped(RowWithCruiseContextSupport row) {
342
343 Cruise cruise = row.getCruise();
344 String naturalId = Cruises.getNaturalId(cruise);
345 return skippedCruisesNaturalId.contains(naturalId);
346
347 }
348
349 public GenericFormatImportCruiseContext getCruiseContext(RowWithCruiseContextSupport row) {
350
351 Cruise cruise = row.getCruise();
352
353 GenericFormatImportCruiseContext result = null;
354 for (GenericFormatImportCruiseContext cruiseContext : cruiseContexts.values()) {
355
356 boolean equals = Cruises.equals(cruise, cruiseContext.getCruise());
357 if (equals) {
358 result = cruiseContext;
359 break;
360 }
361
362 }
363 return result;
364
365 }
366
367 public GenericFormatImportCruiseContext getCruiseContext(Cruise cruise) {
368
369 return cruiseContexts.get(cruise.getId());
370
371 }
372
373 public CsvConsumerForSampleCategory loadSampleCategories(boolean failFast) {
374 sampleCategoryFileResult.setImported(true);
375 surveyFileResult.setLinesCount(importRequest.getArchive().getSampleCategoryLineCount());
376 return new CsvConsumerForSampleCategory(importRequest.getArchive().getSampleCategoryModelPath(), importRequest.getCsvSeparator(), importEntityParserFactory, failFast);
377 }
378
379 public CsvConsumerForSurvey loadSurveys(boolean failFast) {
380 surveyFileResult.setImported(true);
381 surveyFileResult.setLinesCount(importRequest.getArchive().getSurveyLineCount());
382 return new CsvConsumerForSurvey(importRequest.getArchive().getSurveyPath(), importRequest.getCsvSeparator(), importEntityParserFactory, failFast);
383 }
384
385 public CsvConsumerForGearCaracteristic loadGearCaracteristics(boolean failFast) {
386 gearCaracteristicFileResult.setImported(true);
387 gearCaracteristicFileResult.setLinesCount(importRequest.getArchive().getGearCaracteristicsPathLineCount());
388 return new CsvConsumerForGearCaracteristic(importRequest.getArchive().getGearCaracteristicsPath(), importRequest.getCsvSeparator(), importEntityParserFactory, failFast);
389 }
390
391 public CsvConsumerForOperation loadOperations(boolean failFast) {
392 operationFileResult.setImported(true);
393 operationFileResult.setLinesCount(importRequest.getArchive().getOperationPathLineCount());
394 return new CsvConsumerForOperation(importRequest.getArchive().getOperationPath(), importRequest.getCsvSeparator(), importEntityParserFactory, failFast);
395 }
396
397 public CsvConsumerForParameter loadParameters(boolean failFast) {
398 parameterFileResult.setImported(true);
399 parameterFileResult.setLinesCount(importRequest.getArchive().getParameterPathLineCount());
400 return new CsvConsumerForParameter(importRequest.getArchive().getParameterPath(), importRequest.getCsvSeparator(), importEntityParserFactory, failFast);
401 }
402
403 public CsvConsumerForCatch loadCatches(boolean failFast) {
404 catchFileResult.setImported(true);
405 catchFileResult.setLinesCount(importRequest.getArchive().getCatchPathLineCount());
406 return new CsvConsumerForCatch(importRequest.getArchive().getCatchPath(), importRequest.getCsvSeparator(), getImportedSampleCategoryModel(), importEntityParserFactory, failFast);
407 }
408
409 public CsvConsumerForMarineLitter loadMarineLitters(boolean failFast) {
410 marineLitterFileResult.setImported(true);
411 marineLitterFileResult.setLinesCount(importRequest.getArchive().getMarineLitterPathLineCount());
412 return new CsvConsumerForMarineLitter(importRequest.getArchive().getMarineLitterPath(), importRequest.getCsvSeparator(), importEntityParserFactory, failFast);
413 }
414
415 public CsvConsumerForIndividualObservation loadIndividualObservations(boolean failFast) {
416 individualObservationFileResult.setImported(true);
417 individualObservationFileResult.setLinesCount(importRequest.getArchive().getIndividualObservationPathLineCount());
418 return new CsvConsumerForIndividualObservation(importRequest.getArchive().getIndividualObservationPath(), importRequest.getCsvSeparator(), importEntityParserFactory, failFast);
419 }
420
421 public CsvConsumerForAccidentalCatch loadAccidentalCatches(boolean failFast) {
422 accidentalCatchFileResult.setImported(true);
423 accidentalCatchFileResult.setLinesCount(importRequest.getArchive().getAccidentalCatchPathLineCount());
424 return new CsvConsumerForAccidentalCatch(importRequest.getArchive().getAccidentalCatchPath(), importRequest.getCsvSeparator(), importEntityParserFactory, failFast);
425 }
426
427 public CsvConsumerForAttachment loadAttachments(boolean failFast) {
428 attachmentFileResult.setImported(true);
429 attachmentFileResult.setLinesCount(importRequest.getArchive().getAttachemntsPathLineCount());
430 return new CsvConsumerForAttachment(importRequest.getArchive().getAttachmentFilePath(), importRequest.getCsvSeparator(), importEntityParserFactory, failFast);
431 }
432
433 public CsvConsumerForTemporaryGear loadTemporaryGears(boolean failFast) {
434 referentialTemporaryGearFileResult.setImported(true);
435 referentialTemporaryGearFileResult.setLinesCount(importRequest.getArchive().getTemporaryReferentialGearLineCount());
436 return new CsvConsumerForTemporaryGear(importRequest.getArchive().getTemporaryReferentialGearsPath(), importRequest.getCsvSeparator(), failFast);
437 }
438
439 public CsvConsumerForTemporaryPerson loadTemporaryPersons(boolean failFast) {
440 referentialTemporaryPersonFileResult.setImported(true);
441 referentialTemporaryPersonFileResult.setLinesCount(importRequest.getArchive().getTemporaryReferentialPersonLineCount());
442 return new CsvConsumerForTemporaryPerson(importRequest.getArchive().getTemporaryReferentialPersonsPath(), importRequest.getCsvSeparator(), failFast);
443 }
444
445 public CsvConsumerForTemporarySpecies loadTemporarySpecies(boolean failFast) {
446 referentialTemporarySpeciesFileResult.setImported(true);
447 referentialTemporarySpeciesFileResult.setLinesCount(importRequest.getArchive().getTemporaryReferentialSpeciesLineCount());
448 return new CsvConsumerForTemporarySpecies(importRequest.getArchive().getTemporaryReferentialSpeciesPath(), importRequest.getCsvSeparator(), true, failFast);
449 }
450
451 public CsvConsumerForTemporaryVessel loadTemporaryVessels(boolean failFast) {
452 referentialTemporaryVesselFileResult.setImported(true);
453 referentialTemporaryVesselFileResult.setLinesCount(importRequest.getArchive().getTemporaryReferentialVesselLineCount());
454 return new CsvConsumerForTemporaryVessel(importRequest.getArchive().getTemporaryReferentialVesselsPath(), importRequest.getCsvSeparator(), failFast);
455 }
456
457 public Serializable parseCaracteristicValue(Caracteristic caracteristic, String value) throws CaracteristicValueParseException {
458
459 CaracteristicValueParserFormatter parser = CaracteristicValueParserFormatter.newParser(caracteristic);
460 try {
461
462 return parser.parse(value);
463
464 } catch (ParseException e) {
465 throw new CaracteristicValueParseException(caracteristic, value, e.getMessage());
466 }
467
468 }
469
470 public void increments(String message) {
471 progressionModel.increments(message);
472 }
473
474 public GenericFormatImportValidationHelper getValidationHelper() {
475 return validationHelper;
476 }
477
478 public void doActionOnCruiseContexts(CruiseContextAction action) {
479
480 for (GenericFormatImportCruiseContext cruiseContext : cruiseContexts.values()) {
481
482 action.onCruise(cruiseContext, progressionModel);
483
484 }
485 }
486
487 public Iterable<GenericFormatImportCruiseContext> orderedCruiseContexts() {
488
489 return Ordering.from(Cruises.CRUISE_COMPARATOR).onResultOf(new Function<GenericFormatImportCruiseContext, Cruise>() {
490
491 @Override
492 public Cruise apply(GenericFormatImportCruiseContext input) {
493 return input.getCruise();
494 }
495 }).sortedCopy(cruiseContexts.values());
496
497 }
498
499 public void doActionOnSortedCruiseContexts(CruiseContextAction action) {
500
501 for (GenericFormatImportCruiseContext cruiseContext : orderedCruiseContexts()) {
502
503 action.onCruise(cruiseContext, progressionModel);
504
505 }
506 }
507
508
509 public boolean isTechnicalFilesValid() {
510 return isArchiveLayoutValid()
511 && sampleCategoryFileResult.isValid()
512 && referentialTemporaryGearFileResult.isValid()
513 && referentialTemporaryPersonFileResult.isValid()
514 && referentialTemporarySpeciesFileResult.isValid()
515 && referentialTemporaryVesselFileResult.isValid()
516 && protocolFileResult.isValid();
517 }
518
519 public String getProtocolOriginalName() {
520 return protocolOriginalName;
521 }
522
523 public void setProtocolOriginalName(String protocolOriginalName) {
524 this.protocolOriginalName = protocolOriginalName;
525 }
526
527 public void setAttachmentRows(Multimap<String, AttachmentRow> attachmentRows) {
528 this.attachmentRows.putAll(attachmentRows);
529 }
530
531 public Collection<AttachmentRow> popAttachmentRows(ObjectTypeCode objectTypeCode, Integer objectId) {
532 return objectId == null ? null : attachmentRows.removeAll(objectTypeCode + "_" + objectId);
533 }
534
535 public interface CruiseContextAction {
536
537 void onCruise(GenericFormatImportCruiseContext cruiseContext, ProgressionModel progressionModel);
538
539 }
540
541 protected GenericFormatCsvFileResult createFileResult(Path path, boolean mandatory) {
542
543 File file = path.toFile();
544 return new GenericFormatCsvFileResult(file.getName(), mandatory, file.exists());
545
546 }
547
548 protected <E extends TuttiReferentialEntity, K extends Comparable<K>> GenericFormatReferentialImportResult<E, K> createReferentialFileResult(Path path) {
549
550 File file = path.toFile();
551 return new GenericFormatReferentialImportResult<>(file.getName(), file.exists());
552
553 }
554
555 public String decorate(Cruise cruise) {
556 return cruiseDecorator.toString(cruise);
557 }
558
559 public String decorate(FishingOperation fishingOperation) {
560 return fishingOperationDecorator.toString(fishingOperation);
561 }
562
563 }