View Javadoc
1   package fr.ifremer.tutti.service;
2   
3   /*
4    * #%L
5    * Tutti :: Service
6    * %%
7    * Copyright (C) 2012 - 2014 Ifremer
8    * %%
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU General Public License as
11   * published by the Free Software Foundation, either version 3 of the 
12   * License, or (at your option) any later version.
13   * 
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Public License for more details.
18   * 
19   * You should have received a copy of the GNU General Public 
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/gpl-3.0.html>.
22   * #L%
23   */
24  
25  import com.google.common.base.Function;
26  import com.google.common.base.Preconditions;
27  import com.google.common.base.Predicate;
28  import com.google.common.collect.ImmutableSet;
29  import com.google.common.collect.Lists;
30  import com.google.common.collect.Multimap;
31  import fr.ifremer.adagio.core.dao.referential.ObjectTypeCode;
32  import fr.ifremer.tutti.TuttiConfiguration;
33  import fr.ifremer.tutti.persistence.InvalidBatchModelException;
34  import fr.ifremer.tutti.persistence.TuttiPersistence;
35  import fr.ifremer.tutti.persistence.TuttiPersistenceNoDbImpl;
36  import fr.ifremer.tutti.persistence.entities.CaracteristicMap;
37  import fr.ifremer.tutti.persistence.entities.TuttiEntities;
38  import fr.ifremer.tutti.persistence.entities.TuttiEntity;
39  import fr.ifremer.tutti.persistence.entities.data.AccidentalBatch;
40  import fr.ifremer.tutti.persistence.entities.data.Attachment;
41  import fr.ifremer.tutti.persistence.entities.data.BatchContainer;
42  import fr.ifremer.tutti.persistence.entities.data.CatchBatch;
43  import fr.ifremer.tutti.persistence.entities.data.Cruise;
44  import fr.ifremer.tutti.persistence.entities.data.FishingOperation;
45  import fr.ifremer.tutti.persistence.entities.data.IndividualObservationBatch;
46  import fr.ifremer.tutti.persistence.entities.data.MarineLitterBatch;
47  import fr.ifremer.tutti.persistence.entities.data.Program;
48  import fr.ifremer.tutti.persistence.entities.data.SampleCategoryModel;
49  import fr.ifremer.tutti.persistence.entities.data.SpeciesBatch;
50  import fr.ifremer.tutti.persistence.entities.data.SpeciesBatchFrequency;
51  import fr.ifremer.tutti.persistence.entities.protocol.MaturityCaracteristic;
52  import fr.ifremer.tutti.persistence.entities.protocol.TuttiProtocol;
53  import fr.ifremer.tutti.persistence.entities.protocol.Zones;
54  import fr.ifremer.tutti.persistence.entities.referential.Caracteristic;
55  import fr.ifremer.tutti.persistence.entities.referential.Gear;
56  import fr.ifremer.tutti.persistence.entities.referential.Gears;
57  import fr.ifremer.tutti.persistence.entities.referential.ObjectType;
58  import fr.ifremer.tutti.persistence.entities.referential.Person;
59  import fr.ifremer.tutti.persistence.entities.referential.Persons;
60  import fr.ifremer.tutti.persistence.entities.referential.Species;
61  import fr.ifremer.tutti.persistence.entities.referential.Speciess;
62  import fr.ifremer.tutti.persistence.entities.referential.TuttiLocation;
63  import fr.ifremer.tutti.persistence.entities.referential.TuttiReferentialEntity;
64  import fr.ifremer.tutti.persistence.entities.referential.Vessel;
65  import fr.ifremer.tutti.persistence.entities.referential.Vessels;
66  import fr.ifremer.tutti.persistence.model.ProgramDataModel;
67  import fr.ifremer.tutti.persistence.service.TuttiPersistenceServiceLocator;
68  import fr.ifremer.tutti.persistence.service.UpdateSchemaContextSupport;
69  import fr.ifremer.tutti.service.cruise.CruiseCache;
70  import fr.ifremer.tutti.service.cruise.CruiseCacheLoader;
71  import fr.ifremer.tutti.service.sampling.CruiseSamplingCache;
72  import org.apache.commons.collections4.CollectionUtils;
73  import org.apache.commons.io.IOUtils;
74  import org.apache.commons.logging.Log;
75  import org.apache.commons.logging.LogFactory;
76  import org.apache.commons.vfs2.AllFileSelector;
77  import org.apache.commons.vfs2.FileName;
78  import org.apache.commons.vfs2.FileObject;
79  import org.apache.commons.vfs2.FileType;
80  import org.nuiton.jaxx.application.ApplicationBusinessException;
81  import org.nuiton.jaxx.application.ApplicationIOUtil;
82  import org.nuiton.util.TimeLog;
83  import org.nuiton.version.Version;
84  
85  import java.io.File;
86  import java.io.IOException;
87  import java.text.DateFormat;
88  import java.text.SimpleDateFormat;
89  import java.util.ArrayList;
90  import java.util.Collection;
91  import java.util.Collections;
92  import java.util.Iterator;
93  import java.util.LinkedHashSet;
94  import java.util.List;
95  import java.util.Map;
96  import java.util.Objects;
97  import java.util.Optional;
98  import java.util.Set;
99  import java.util.concurrent.Callable;
100 
101 import static org.nuiton.i18n.I18n.t;
102 
103 /**
104  * Persistence service.
105  *
106  * @author Tony Chemit - chemit@codelutin.com
107  * @since 0.1
108  */
109 public class PersistenceService extends AbstractTuttiService implements TuttiPersistence {
110 
111     /** Logger. */
112     private static final Log log = LogFactory.getLog(PersistenceService.class);
113 
114     protected TuttiPersistence driver;
115 
116     @Override
117     public void setServiceContext(TuttiServiceContext context) {
118         super.setServiceContext(context);
119 
120         init();
121     }
122 
123     public void setSampleCategoryModel(SampleCategoryModel sampleCategoryModel) {
124         context.getDataContext().setSampleCategoryModel(sampleCategoryModel);
125     }
126 
127     public List<Gear> retainTemporaryGearList(List<Gear> targetList) {
128 
129         return retainTemporaryList(Gears.IS_TEMPORARY, targetList);
130 
131     }
132 
133     public List<Person> retainTemporaryPersonList(List<Person> targetList) {
134 
135         return retainTemporaryList(Persons.IS_TEMPORARY, targetList);
136 
137     }
138 
139     public List<Species> retainTemporarySpeciesList(List<Species> targetList) {
140 
141         return retainTemporaryList(Speciess.IS_TEMPORARY, targetList);
142 
143     }
144 
145     public List<Vessel> retainTemporaryVesselList(List<Vessel> targetList) {
146 
147         return retainTemporaryList(Vessels.IS_TEMPORARY, targetList);
148 
149     }
150 
151 
152     public <E extends TuttiEntity> List<E> retainTemporaryList(Predicate<E> isTemporaryPredicate, List<E> targetList) {
153         List<E> sourceList = new ArrayList<>();
154         Iterator<E> iterator = targetList.iterator();
155         while (iterator.hasNext()) {
156             E next = iterator.next();
157             if (isTemporaryPredicate.apply(next)) {
158                 iterator.remove();
159                 sourceList.add(next);
160             }
161         }
162         return sourceList;
163     }
164 
165     public interface FrequencyFunction extends Function<SpeciesBatch, List<SpeciesBatchFrequency>> {
166     }
167 
168     public FrequencyFunction newSpeciesFrequenciesFunction() {
169         return input -> getAllSpeciesBatchFrequency(input.getIdAsInt());
170     }
171 
172     public FrequencyFunction newBenthosFrequenciesFunction() {
173         return input -> getAllBenthosBatchFrequency(input.getIdAsInt());
174     }
175 
176     public Float countFrequenciesWeight(List<SpeciesBatchFrequency> frequencies, boolean stopIfNullFound) {
177         Float result = null;
178         for (SpeciesBatchFrequency frequency : frequencies) {
179             Float w = frequency.getWeight();
180             if (w == null) {
181 
182                 if (stopIfNullFound) {
183                     break;
184                 }
185                 continue;
186             }
187             if (result == null) {
188                 result = 0f;
189             }
190             result += w;
191         }
192         return result;
193     }
194 
195     public Integer countFrequenciesNumber(List<SpeciesBatchFrequency> frequencies, boolean stopIfNullFound) {
196         Integer result = null;
197         for (SpeciesBatchFrequency frequency : frequencies) {
198             Integer number = frequency.getNumber();
199             if (number == null) {
200 
201                 if (stopIfNullFound) {
202                     break;
203                 }
204                 continue;
205             }
206             if (result == null) {
207                 result = 0;
208             }
209             result += number;
210         }
211         return result;
212     }
213 
214     //------------------------------------------------------------------------//
215     //-- Technical methods                                                  --//
216     //------------------------------------------------------------------------//
217 
218     @Override
219     public String getImplementationName() {
220         return "Tutti Persistence Service";
221     }
222 
223     @Override
224     public void setSkipShutdownDbWhenClosing() {
225         driver.setSkipShutdownDbWhenClosing();
226     }
227 
228     @Override
229     public ProgramDataModel loadProgram(String programId, boolean loadFishingOperation) {
230         return driver.loadProgram(programId, loadFishingOperation);
231     }
232 
233     @Override
234     public ProgramDataModel loadCruises(String programId, boolean loadFishingOperation, Integer... cruiseIds) {
235         return driver.loadCruises(programId, loadFishingOperation, cruiseIds);
236     }
237 
238     @Override
239     public ProgramDataModel loadCruise(String programId, Integer cruiseId, Integer... fishingOperationIds) {
240         return driver.loadCruise(programId, cruiseId, fishingOperationIds);
241     }
242 
243     @Override
244     public void lazyInit() {
245         // this service does not used lazy init
246     }
247 
248     @Override
249     public void clearAllCaches() {
250         driver.clearAllCaches();
251     }
252 
253     @Override
254     public <V> V invoke(Callable<V> call) {
255         return driver.invoke(call);
256     }
257 
258     @Override
259     public <U extends UpdateSchemaContextSupport> void prepareUpdateSchemaContext(U context) {
260         driver.prepareUpdateSchemaContext(context);
261     }
262 
263     @Override
264     public Version getSchemaVersion() {
265         return driver.getSchemaVersion();
266     }
267 
268     @Override
269     public Version getSchemaVersionIfUpdate() {
270         return driver.getSchemaVersionIfUpdate();
271     }
272 
273     @Override
274     public void updateSchema() {
275         driver.updateSchema();
276     }
277 
278     @Override
279     public void sanityDb() {
280         driver.sanityDb();
281     }
282 
283     public static final DateFormat EXPORT_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
284 
285     public static final String EXPORT_DIRECTORY_FORMAT = "tutti-%s-%s";
286 
287     /**
288      * Export db as a zip archive (including the attachments and protocols).
289      *
290      * @param file archive file where to store
291      * @since 1.0.2
292      */
293     public void exportDb(File file) {
294 
295         // can not do this operation on a opnened bd
296         Preconditions.checkState(!isDbLoaded());
297 
298         // need a file to export
299         Preconditions.checkNotNull(file);
300 
301         // create zip structure
302 
303         TuttiConfiguration config = context.getConfig();
304 
305         String directoryName = String.format(
306                 EXPORT_DIRECTORY_FORMAT,
307                 config.getVersion(),
308                 EXPORT_DATE_FORMAT.format(context.currentDate()));
309 
310         File structureDirectory = new File(config.newTempFile("exportdb"),
311                                            directoryName);
312 
313         try {
314             ApplicationIOUtil.forceMkdir(structureDirectory,
315                                          t("tutti.io.mkDir.error", structureDirectory));
316 
317             if (log.isInfoEnabled()) {
318                 log.info("Export directory: " + structureDirectory);
319             }
320 
321             ApplicationIOUtil.copyDirectory(config.getDbDirectory(),
322                                             new File(structureDirectory, "db"),
323                                             t("tutti.service.persistence.copyDirectory.db.error"));
324 
325             ApplicationIOUtil.copyDirectory(config.getDbAttachmentDirectory(),
326                                             new File(structureDirectory, "meas_files"),
327                                             t("tutti.service.persistence.copyDirectory.attachment.error"));
328 
329             // create zip
330             ApplicationIOUtil.zip(structureDirectory, file,
331                                   t("tutti.service.persistence.exportDb.zip.error", file));
332 
333         } finally {
334 
335             // delete temp files
336             ApplicationIOUtil.forceDeleteOnExit(
337                     structureDirectory,
338                     t("tutti.service.persistence.exportDb.deleteTempDir.error", structureDirectory));
339         }
340     }
341 
342     public enum ImportStructureType {
343         NORMAL, // normal structure with a db directory + optional meas_file directory
344         INLINE
345     }
346 
347     public ImportStructureType checkImportStructure(File file) {
348 
349         if (!file.exists()) {
350             throw new ApplicationBusinessException(t("tutti.service.persistence.checkImportstructure.fileNotExist", file));
351         }
352 
353         // check zip structure
354         FileObject fileObject = ApplicationIOUtil.resolveFile(
355                 "zip:" + file.getAbsolutePath(), t("tutti.service.persistence.getArchive.error", file));
356 
357 
358         FileObject[] children = ApplicationIOUtil.getChildren(fileObject, t("tutti.service.persistence.openArchive.error", file));
359 
360         if (children.length != 1) {
361             throw new ApplicationBusinessException(t("tutti.service.persistence.checkImportstructure.tooManyChildren", file));
362         }
363 
364         ImportStructureType result;
365 
366         fileObject = children[0];
367         children = ApplicationIOUtil.getChildren(fileObject, t("tutti.service.persistence.openArchive.error", file));
368 
369         // try to detect a db directory
370         boolean dbDirectoyDetected = false;
371         for (FileObject child : children) {
372             FileName name = child.getName();
373             if (name.getBaseName().equals("db")) {
374                 dbDirectoyDetected = true;
375                 break;
376             }
377         }
378 
379         if (dbDirectoyDetected) {
380 
381             // NORMAL type (two directories)
382             result = ImportStructureType.NORMAL;
383 
384             checkArchiveDb(file, fileObject, "db", true);
385             checkArchiveDb(file, fileObject, "meas_files", false);
386         } else {
387 
388             // INLINE type
389             result = ImportStructureType.INLINE;
390 
391             // should have no directory
392             for (FileObject child : children) {
393                 FileType type = ApplicationIOUtil.getType(child, "Could not get type of " + child);
394                 if (FileType.FOLDER.equals(type)) {
395                     throw new ApplicationBusinessException(t("tutti.service.persistence.checkImportstructure.inlineForbidDirectory"));
396                 }
397             }
398         }
399 
400         if (log.isInfoEnabled()) {
401             log.info("Database import type: " + result);
402         }
403 
404         return result;
405     }
406 
407     protected void checkArchiveDb(File file,
408                                   FileObject fileObject,
409                                   String dir,
410                                   boolean required) {
411         FileObject directory = ApplicationIOUtil.getChild(fileObject, dir, t("tutti.service.persistence.getChild.error", dir));
412         if (directory == null) {
413 
414             String message = t("tutti.service.persistence.checkArchiveDb.error", file, dir);
415             if (required) {
416                 throw new ApplicationBusinessException(message);
417             }
418 
419             if (log.isWarnEnabled()) {
420                 log.warn(message);
421             }
422         }
423     }
424 
425     /**
426      * Import a db from a zip archive (including the attachments and protocols).
427      *
428      * @param importStructureType type of structure of import
429      * @param file                archive file where to store
430      * @since 1.0.2
431      */
432     public void importDb(ImportStructureType importStructureType, File file) {
433 
434         // can not do this operation on a opened db
435         Preconditions.checkState(!isDbLoaded());
436 
437         // need a file to export
438         Preconditions.checkNotNull(file);
439 
440         TuttiConfiguration config = context.getConfig();
441 
442         File target = config.getDataDirectory();
443 
444         if (log.isInfoEnabled()) {
445             log.info("Import db to " + target);
446         }
447         FileObject fileObject = ApplicationIOUtil.resolveFile(
448                 "zip:" + file.getAbsolutePath(),
449                 t("tutti.service.persistence.getArchive.error", file));
450 
451         FileObject[] children = ApplicationIOUtil.getChildren(
452                 fileObject,
453                 t("tutti.service.persistence.openArchive.error", file));
454 
455         fileObject = children[0];
456 
457         switch (importStructureType) {
458 
459             case NORMAL:
460                 // nothing special to do
461                 break;
462 
463             case INLINE:
464                 target = new File(target, "db");
465                 ApplicationIOUtil.forceMkdir(
466                         target,
467                         t("tutti.service.persistence.createDbDirectory.error", file));
468 
469 
470                 break;
471         }
472 
473         ApplicationIOUtil.explode(fileObject,
474                                   target,
475                                   new AllFileSelector(),
476                                   t("tutti.service.persistence.extractArchive.error", file));
477     }
478 
479     public boolean isDbLoaded() {
480         return !(driver instanceof TuttiPersistenceNoDbImpl);
481     }
482 
483     public List<Caracteristic> getDefaultIndividualObservationCaracteristics() {
484 
485         TuttiProtocol protocol = getProtocol();
486 
487         List<Caracteristic> result;
488         if (protocol != null) {
489             List<String> individualObservationPmfmId = getProtocol().getIndividualObservationPmfmId();
490             if (CollectionUtils.isEmpty(individualObservationPmfmId)) {
491 
492                 // no conf
493                 result = Lists.newArrayList();
494 
495             } else {
496                 result = Lists.newArrayListWithCapacity(individualObservationPmfmId.size());
497                 for (String id : individualObservationPmfmId) {
498                     Caracteristic caracteristic = getCaracteristic(Integer.valueOf(id));
499                     result.add(caracteristic);
500                 }
501             }
502 
503         } else {
504             // no default caracteristics to use
505             result = Lists.newArrayList();
506         }
507 
508         return result;
509     }
510 
511     public List<Caracteristic> getLengthStepCaracteristics(List<Caracteristic> caracteristics) {
512 
513         // get loaded protocol
514         TuttiProtocol protocol = getProtocol();
515 
516         List<Caracteristic> result;
517         if (protocol != null) {
518 
519             result = Lists.newArrayListWithCapacity(
520                     protocol.sizeLengthClassesPmfmId());
521 
522             Map<String, Caracteristic> allCaractericsById =
523                     TuttiEntities.splitById(caracteristics);
524 
525             if (!protocol.isLengthClassesPmfmIdEmpty()) {
526                 for (String id : protocol.getLengthClassesPmfmId()) {
527                     result.add(allCaractericsById.get(id));
528                 }
529             }
530         } else {
531             // no default caracteristics to use
532             result = Lists.newArrayList();
533         }
534 
535 
536         result = Collections.unmodifiableList(result);
537         return result;
538     }
539 
540     public List<Caracteristic> getMaturityCaracteristics(List<Caracteristic> caracteristics) {
541 
542         // get loaded protocol
543         TuttiProtocol protocol = getProtocol();
544 
545         List<Caracteristic> result;
546         if (protocol != null) {
547 
548             result = Lists.newArrayListWithCapacity(
549                     protocol.sizeMaturityCaracteristics());
550 
551             Map<String, Caracteristic> allCaractericsById =
552                     TuttiEntities.splitById(caracteristics);
553 
554             if (!protocol.isMaturityCaracteristicsEmpty()) {
555                 for (MaturityCaracteristic caracteristic : protocol.getMaturityCaracteristics()) {
556                     result.add(allCaractericsById.get(caracteristic.getId()));
557                 }
558             }
559         } else {
560             // no default caracteristics to use
561             result = Lists.newArrayList();
562         }
563 
564 
565         result = Collections.unmodifiableList(result);
566         return result;
567     }
568 
569 //    /**
570 //     * Return the speciesProtocol corresponding to the species of the given protocol.
571 //     *
572 //     * @param species the species to filter
573 //     * @return the speciesProtocol corresponding to the species of the given protocol.
574 //     * @since 2.6
575 //     */
576 //    public SpeciesProtocol getSpeciesProtocol(Species species) {
577 //        return TuttiProtocols.getSpeciesProtocol(species, getProtocol().getSpecies());
578 //    }
579 
580 //    /**
581 //     * Return the benthosProtocol corresponding to the species of the given protocol.
582 //     *
583 //     * @param species the species to filter
584 //     * @return the benthosProtocol corresponding to the species of the given protocol.
585 //     * @since 2.6
586 //     */
587 //    public SpeciesProtocol getBenthosProtocol(Species species) {
588 //        return TuttiProtocols.getSpeciesProtocol(species, getProtocol().getBenthos());
589 //    }
590 
591     public static final TimeLog TIME_LOG = new TimeLog(PersistenceService.class);
592 
593     @Override
594     public void init() {
595 
596         long t0 = TimeLog.getTime();
597 
598         if (log.isDebugEnabled()) {
599             log.debug("Opening persistence service...");
600         }
601 
602         TuttiConfiguration config = context.getConfig();
603         TuttiConfiguration.setInstance(config);
604         if (config.isDbExists()) {
605 
606             String jdbcUrl = config.getJdbcUrl();
607             if (log.isInfoEnabled()) {
608                 log.info("Using database at " + jdbcUrl);
609             }
610             // can use adagio driver
611             driver = TuttiPersistenceServiceLocator.getPersistenceService();
612 
613             if (config.isSanityDb()) {
614 
615                 driver.sanityDb();
616             }
617 
618         } else {
619 
620             driver = new TuttiPersistenceNoDbImpl();
621 
622             driver.init();
623         }
624 
625         TIME_LOG.log(t0, "Persistence driver *" + driver.getImplementationName() + "* opened.");
626     }
627 
628     @Override
629     public void close() throws IOException {
630 
631         long t0 = TimeLog.getTime();
632 
633         String driverName = driver.getImplementationName();
634 
635         if (log.isDebugEnabled()) {
636             log.debug("Closing persistence Service *" + driverName + "*...");
637         }
638 
639         IOUtils.closeQuietly(driver);
640 
641         TIME_LOG.log(t0, "Persistence driver *" + driverName + "* closed.");
642     }
643 
644     //------------------------------------------------------------------------//
645     //-- Referential methods                                                --//
646     //------------------------------------------------------------------------//
647 
648     public List<Vessel> getAllVessel() {
649         List<Vessel> targetList = Lists.newArrayList(getAllFishingVessel());
650         targetList.addAll(getAllScientificVessel());
651         return targetList;
652     }
653 
654     @Override
655     public List<Vessel> getAllScientificVessel() {
656         return driver.getAllScientificVessel();
657     }
658 
659     @Override
660     public List<Vessel> getAllFishingVessel() {
661         return driver.getAllFishingVessel();
662     }
663 
664     @Override
665     public List<Vessel> getAllVesselWithObsoletes() {
666         return driver.getAllVesselWithObsoletes();
667     }
668 
669     @Override
670     public List<Species> getAllSpecies() {
671         return driver.getAllSpecies();
672     }
673 
674     @Override
675     public List<Species> getAllReferentSpecies() {
676         return driver.getAllReferentSpecies();
677     }
678 
679     @Override
680     public List<Species> getAllReferentSpeciesWithObsoletes() {
681         return driver.getAllReferentSpeciesWithObsoletes();
682     }
683 
684     @Override
685     public Species getSpeciesByReferenceTaxonId(Integer referenceTaxonId) {
686         return driver.getSpeciesByReferenceTaxonId(referenceTaxonId);
687     }
688 
689     @Override
690     public Species getSpeciesByReferenceTaxonIdWithVernacularCode(Integer referenceTaxonId) {
691         return driver.getSpeciesByReferenceTaxonIdWithVernacularCode(referenceTaxonId);
692     }
693 
694     @Override
695     public Map<Integer, Integer> getAllObsoleteReferentTaxons() {
696         return driver.getAllObsoleteReferentTaxons();
697     }
698 
699     @Override
700     public List<Caracteristic> getAllCaracteristic() {
701         return driver.getAllCaracteristic();
702     }
703 
704     @Override
705     public List<Caracteristic> getAllCaracteristicWithProtected() {
706         return driver.getAllCaracteristicWithProtected();
707     }
708 
709     @Override
710     public List<Caracteristic> getAllCaracteristicForSampleCategory() {
711         return driver.getAllCaracteristicForSampleCategory();
712     }
713 
714     @Override
715     public List<Caracteristic> getAllNumericCaracteristic() {
716         return driver.getAllNumericCaracteristic();
717     }
718 
719     @Override
720     public List<TuttiLocation> getAllProgramZone() {
721         return driver.getAllProgramZone();
722     }
723 
724     @Override
725     public List<TuttiLocation> getAllCountry() {
726         return driver.getAllCountry();
727     }
728 
729     @Override
730     public List<TuttiLocation> getAllHarbour() {
731         return driver.getAllHarbour();
732     }
733 
734     @Override
735     public List<TuttiLocation> getAllHarbourWithObsoletes() {
736         return driver.getAllHarbourWithObsoletes();
737     }
738 
739     @Override
740     public TuttiLocation getLocation(String id) {
741         return driver.getLocation(id);
742     }
743 
744     public List<Gear> getAllGear() {
745         List<Gear> targetList = Lists.newArrayList(getAllScientificGear());
746         targetList.addAll(getAllFishingGear());
747         return targetList;
748     }
749 
750     @Override
751     public List<Gear> getAllScientificGear() {
752         return driver.getAllScientificGear();
753     }
754 
755     @Override
756     public List<Gear> getAllFishingGear() {
757         return driver.getAllFishingGear();
758     }
759 
760     @Override
761     public List<Gear> getAllGearWithObsoletes() {
762         return driver.getAllGearWithObsoletes();
763     }
764 
765     @Override
766     public List<Person> getAllPerson() {
767         return driver.getAllPerson();
768     }
769 
770     @Override
771     public List<Person> getAllPersonWithObsoletes() {
772         return driver.getAllPersonWithObsoletes();
773     }
774 
775     @Override
776     public List<ObjectType> getAllObjectType() {
777         return driver.getAllObjectType();
778     }
779 
780     @Override
781     public ImmutableSet<Integer> getAllFishingOperationStratasAndSubstratasIdsForProgram(String zoneId) {
782         return driver.getAllFishingOperationStratasAndSubstratasIdsForProgram(zoneId);
783     }
784 
785     @Override
786     public Multimap<TuttiLocation, TuttiLocation> getAllFishingOperationStratasAndSubstratas(String zoneId) {
787         return driver.getAllFishingOperationStratasAndSubstratas(zoneId);
788     }
789 
790     @Override
791     public List<TuttiLocation> getAllFishingOperationStrata(String zoneId) {
792         return driver.getAllFishingOperationStrata(zoneId);
793     }
794 
795     @Override
796     public List<TuttiLocation> getAllFishingOperationStrataWithObsoletes(String zoneId) {
797         return driver.getAllFishingOperationStrataWithObsoletes(zoneId);
798     }
799 
800     @Override
801     public List<TuttiLocation> getAllFishingOperationSubStrata(String zoneId, String strataId) {
802         return driver.getAllFishingOperationSubStrata(zoneId, strataId);
803     }
804 
805     @Override
806     public List<TuttiLocation> getAllFishingOperationSubStrataWithObsoletes(String zoneId, String strataId) {
807         return driver.getAllFishingOperationSubStrataWithObsoletes(zoneId, strataId);
808     }
809 
810     @Override
811     public List<TuttiLocation> getAllFishingOperationLocation(String zoneId, String strataId, String subStrataId) {
812         return driver.getAllFishingOperationLocation(zoneId, strataId, subStrataId);
813     }
814 
815     @Override
816     public List<TuttiLocation> getAllFishingOperationLocationWithObsoletes(String zoneId, String strataId, String subStrataId) {
817         return driver.getAllFishingOperationLocationWithObsoletes(zoneId, strataId, subStrataId);
818     }
819 
820     @Override
821     public Caracteristic getSizeCategoryCaracteristic() {
822         return driver.getSizeCategoryCaracteristic();
823     }
824 
825     @Override
826     public Caracteristic getSexCaracteristic() {
827         return driver.getSexCaracteristic();
828     }
829 
830     @Override
831     public Caracteristic getSortedUnsortedCaracteristic() {
832         return driver.getSortedUnsortedCaracteristic();
833     }
834 
835     @Override
836     public Caracteristic getMaturityCaracteristic() {
837         return driver.getMaturityCaracteristic();
838     }
839 
840     @Override
841     public Caracteristic getAgeCaracteristic() {
842         return driver.getAgeCaracteristic();
843     }
844 
845     @Override
846     public Caracteristic getMarineLitterCategoryCaracteristic() {
847         return driver.getMarineLitterCategoryCaracteristic();
848     }
849 
850     @Override
851     public Caracteristic getMarineLitterSizeCategoryCaracteristic() {
852         return driver.getMarineLitterSizeCategoryCaracteristic();
853     }
854 
855     @Override
856     public Caracteristic getVerticalOpeningCaracteristic() {
857         return driver.getVerticalOpeningCaracteristic();
858     }
859 
860     @Override
861     public Caracteristic getHorizontalOpeningWingsCaracteristic() {
862         return driver.getHorizontalOpeningWingsCaracteristic();
863     }
864 
865     @Override
866     public Caracteristic getHorizontalOpeningDoorCaracteristic() {
867         return driver.getHorizontalOpeningDoorCaracteristic();
868     }
869 
870     @Override
871     public Caracteristic getDeadOrAliveCaracteristic() {
872         return driver.getDeadOrAliveCaracteristic();
873     }
874 
875     @Override
876     public Caracteristic getCalcifiedStructureCaracteristic() {
877         return driver.getCalcifiedStructureCaracteristic();
878     }
879 
880     @Override
881     public Caracteristic getPmfmIdCaracteristic() {
882         return driver.getPmfmIdCaracteristic();
883     }
884 
885     @Override
886     public Caracteristic getWeightMeasuredCaracteristic() {
887         return driver.getWeightMeasuredCaracteristic();
888     }
889 
890     @Override
891     public Caracteristic getCopyIndividualObservationModeCaracteristic() {
892         return driver.getCopyIndividualObservationModeCaracteristic();
893     }
894 
895     @Override
896     public Caracteristic getSampleCodeCaracteristic() {
897         return driver.getSampleCodeCaracteristic();
898     }
899 
900     @Override
901     public Caracteristic getCaracteristic(Integer pmfmId) {
902         return driver.getCaracteristic(pmfmId);
903     }
904 
905     @Override
906     public boolean isVracBatch(SpeciesBatch speciesBatch) {
907         return driver.isVracBatch(speciesBatch);
908     }
909 
910     @Override
911     public boolean isHorsVracBatch(SpeciesBatch speciesBatch) {
912         return driver.isHorsVracBatch(speciesBatch);
913     }
914 
915     @Override
916     public Predicate<SpeciesBatch> getVracBatchPredicate() {
917         return driver.getVracBatchPredicate();
918     }
919 
920     @Override
921     public boolean isTemporary(TuttiReferentialEntity entity) {
922         return driver.isTemporary(entity);
923     }
924 
925     @Override
926     public Vessel getVessel(String vesselCode) {
927         return driver.getVessel(vesselCode);
928     }
929 
930     @Override
931     public Person getPerson(Integer personId) {
932         return driver.getPerson(personId);
933     }
934 
935     @Override
936     public Gear getGear(Integer gearCode) {
937         return driver.getGear(gearCode);
938     }
939 
940     @Override
941     public ObjectType getObjectType(String objectTypeCode) {
942         return driver.getObjectType(objectTypeCode);
943     }
944 
945     @Override
946     public List<Gear> addTemporaryGears(List<Gear> gears) {
947         return driver.addTemporaryGears(gears);
948     }
949 
950     @Override
951     public List<Person> addTemporaryPersons(List<Person> persons) {
952         return driver.addTemporaryPersons(persons);
953     }
954 
955     @Override
956     public List<Species> addTemporarySpecies(List<Species> species) {
957         return driver.addTemporarySpecies(species);
958     }
959 
960     @Override
961     public List<Vessel> addTemporaryVessels(List<Vessel> vessels) {
962         return driver.addTemporaryVessels(vessels);
963     }
964 
965     @Override
966     public List<Gear> updateTemporaryGears(List<Gear> gears) {
967         return driver.updateTemporaryGears(gears);
968     }
969 
970     @Override
971     public List<Person> updateTemporaryPersons(List<Person> persons) {
972         return driver.updateTemporaryPersons(persons);
973     }
974 
975     @Override
976     public List<Species> updateTemporarySpecies(List<Species> species) {
977         return driver.updateTemporarySpecies(species);
978     }
979 
980     @Override
981     public List<Vessel> updateTemporaryVessels(List<Vessel> vessels) {
982         return driver.updateTemporaryVessels(vessels);
983     }
984 
985     @Override
986     public List<Gear> linkTemporaryGears(List<Gear> gears) {
987         return driver.linkTemporaryGears(gears);
988     }
989 
990     @Override
991     public List<Person> linkTemporaryPersons(List<Person> persons) {
992         return driver.linkTemporaryPersons(persons);
993     }
994 
995     @Override
996     public List<Species> linkTemporarySpecies(List<Species> specieses) {
997         return driver.linkTemporarySpecies(specieses);
998     }
999 
1000     @Override
1001     public List<Vessel> linkTemporaryVessels(List<Vessel> vessels) {
1002         return driver.linkTemporaryVessels(vessels);
1003     }
1004 
1005     @Override
1006     public void replaceGear(Gear source, Gear target, boolean delete) {
1007         driver.replaceGear(source, target, delete);
1008     }
1009 
1010     @Override
1011     public void replacePerson(Person source, Person target, boolean delete) {
1012         driver.replacePerson(source, target, delete);
1013     }
1014 
1015     @Override
1016     public void replaceSpecies(Species source, Species target, boolean delete) {
1017         driver.replaceSpecies(source, target, delete);
1018     }
1019 
1020     @Override
1021     public void replaceVessel(Vessel source, Vessel target, boolean delete) {
1022         driver.replaceVessel(source, target, delete);
1023     }
1024 
1025     @Override
1026     public void deleteTemporaryGear(Integer id) {
1027         driver.deleteTemporaryGear(id);
1028     }
1029 
1030     @Override
1031     public void deleteTemporaryGears(Collection<Integer> id) {
1032         driver.deleteTemporaryGears(id);
1033     }
1034 
1035     @Override
1036     public void deleteTemporarySpecies(Integer referenceTaxonId) {
1037         driver.deleteTemporarySpecies(referenceTaxonId);
1038     }
1039 
1040     @Override
1041     public void deleteTemporarySpecies(Collection<Integer> referenceTaxonIds) {
1042         driver.deleteTemporarySpecies(referenceTaxonIds);
1043     }
1044 
1045     @Override
1046     public void deleteTemporaryPerson(Integer id) {
1047         driver.deleteTemporaryPerson(id);
1048     }
1049 
1050     @Override
1051     public void deleteTemporaryPersons(Collection<Integer> ids) {
1052         driver.deleteTemporaryPersons(ids);
1053     }
1054 
1055     @Override
1056     public void deleteTemporaryVessel(String code) {
1057         driver.deleteTemporaryVessel(code);
1058     }
1059 
1060     @Override
1061     public void deleteTemporaryVessels(Collection<String> codes) {
1062         driver.deleteTemporaryVessels(codes);
1063     }
1064 
1065     @Override
1066     public boolean isTemporaryPersonUsed(Integer id) {
1067         return driver.isTemporaryPersonUsed(id);
1068     }
1069 
1070     @Override
1071     public boolean isTemporarySpeciesUsed(Integer referenceTaxonId) {
1072         return driver.isTemporarySpeciesUsed(referenceTaxonId);
1073     }
1074 
1075     @Override
1076     public boolean isTemporaryGearUsed(Integer id) {
1077         return driver.isTemporaryGearUsed(id);
1078     }
1079 
1080     @Override
1081     public boolean isTemporaryVesselUsed(String code) {
1082         return driver.isTemporaryVesselUsed(code);
1083     }
1084 
1085     @Override
1086     public String getLocationLabelByLatLong(Float latitude, Float longitude) {
1087         return driver.getLocationLabelByLatLong(latitude, longitude);
1088     }
1089 
1090     @Override
1091     public Integer getLocationIdByLatLong(Float latitude, Float longitude) {
1092         return driver.getLocationIdByLatLong(latitude, longitude);
1093     }
1094 
1095     //------------------------------------------------------------------------//
1096     //-- Attachment methods                                                 --//
1097     //------------------------------------------------------------------------//
1098 
1099     @Override
1100     public List<Attachment> getAllAttachments(ObjectTypeCode objectType, Integer objectId) {
1101         return driver.getAllAttachments(objectType, objectId);
1102     }
1103 
1104     @Override
1105     public File getAttachmentFile(String attachmentId) {
1106         return driver.getAttachmentFile(attachmentId);
1107     }
1108 
1109     @Override
1110     public Attachment createAttachment(Attachment attachment, File file) {
1111         return driver.createAttachment(attachment, file);
1112     }
1113 
1114     @Override
1115     public Attachment saveAttachment(Attachment attachment) {
1116         return driver.saveAttachment(attachment);
1117     }
1118 
1119     @Override
1120     public void deleteAttachment(String attachmentId) {
1121         driver.deleteAttachment(attachmentId);
1122     }
1123 
1124     @Override
1125     public void deleteAllAttachment(ObjectTypeCode objectType, Set<Integer> objectIds) {
1126         driver.deleteAllAttachment(objectType, objectIds);
1127     }
1128 
1129     @Override
1130     public void deleteAllAttachment(ObjectTypeCode objectType, Integer objectId) {
1131         driver.deleteAllAttachment(objectType, objectId);
1132     }
1133 
1134     //------------------------------------------------------------------------//
1135     //-- Program methods                                                    --//
1136     //------------------------------------------------------------------------//
1137 
1138     @Override
1139     public List<Program> getAllProgram() {
1140         return driver.getAllProgram();
1141     }
1142 
1143     @Override
1144     public Program getProgram(String id) {
1145         return driver.getProgram(id);
1146     }
1147 
1148     @Override
1149     public Program createProgram(Program bean) {
1150         return driver.createProgram(bean);
1151     }
1152 
1153     @Override
1154     public Program saveProgram(Program bean) {
1155         return driver.saveProgram(bean);
1156     }
1157 
1158     //------------------------------------------------------------------------//
1159     //-- Cruise methods                                                     --//
1160     //------------------------------------------------------------------------//
1161 
1162     @Override
1163     public List<Integer> getAllCruiseId(String programId) {
1164         return driver.getAllCruiseId(programId);
1165     }
1166 
1167     @Override
1168     public List<Cruise> getAllCruise(String programId) {
1169         return driver.getAllCruise(programId);
1170     }
1171 
1172     @Override
1173     public Cruise getCruise(Integer id) {
1174         return driver.getCruise(id);
1175     }
1176 
1177     @Override
1178     public Cruise createCruise(Cruise bean) {
1179         return driver.createCruise(bean);
1180     }
1181 
1182     @Override
1183     public Cruise saveCruise(Cruise bean, boolean updateVessel, boolean updateGear) {
1184         return driver.saveCruise(bean, updateVessel, updateGear);
1185     }
1186 
1187     @Override
1188     public void setCruiseReadyToSynch(Integer cruiseId) {
1189         driver.setCruiseReadyToSynch(cruiseId);
1190     }
1191 
1192     @Override
1193     public CaracteristicMap getGearCaracteristics(Integer cruiseId, Integer gearId, short rankOrder) {
1194         return driver.getGearCaracteristics(cruiseId, gearId, rankOrder);
1195     }
1196 
1197     @Override
1198     public boolean isOperationUseGears(Integer cruiseId, Collection<Gear> gears) {
1199         return driver.isOperationUseGears(cruiseId, gears);
1200     }
1201 
1202     @Override
1203     public void saveGearCaracteristics(Gear gear, Cruise cruise) {
1204         driver.saveGearCaracteristics(gear, cruise);
1205     }
1206 
1207     //------------------------------------------------------------------------//
1208     //-- Protocol methods                                                   --//
1209     //------------------------------------------------------------------------//
1210 
1211 
1212     @Override
1213     public TuttiProtocol getProtocol() {
1214         return driver.getProtocol();
1215     }
1216 
1217     @Override
1218     public void setProtocol(TuttiProtocol protocol) {
1219         driver.setProtocol(protocol);
1220     }
1221 
1222     @Override
1223     public boolean isProtocolExist(String id) {
1224         return driver.isProtocolExist(id);
1225     }
1226 
1227     @Override
1228     public List<String> getAllProtocolNames() {
1229         return driver.getAllProtocolNames();
1230     }
1231 
1232     @Override
1233     public String getFirstAvailableName(String protocolName) {
1234         return driver.getFirstAvailableName(protocolName);
1235     }
1236 
1237     @Override
1238     public List<TuttiProtocol> getAllProtocol() {
1239         return driver.getAllProtocol();
1240     }
1241 
1242     @Override
1243     public List<TuttiProtocol> getAllProtocol(String programId) {
1244         return driver.getAllProtocol(programId);
1245     }
1246 
1247     @Override
1248     public List<String> getAllProtocolId() {
1249         return driver.getAllProtocolId();
1250     }
1251 
1252     @Override
1253     public TuttiProtocol getProtocol(String id) {
1254         TuttiProtocol protocol = driver.getProtocol(id);
1255 
1256         if (protocol.isUseCalcifiedPieceSampling() && context.getDataContext().isProgramFilled()) {
1257 
1258             // on vérifie que les zones sont valident
1259             Program program = context.getDataContext().getProgram();
1260 
1261             String programZoneId = program.getZone().getId();
1262 
1263             ImmutableSet<Integer> availableLocationIds = getAllFishingOperationStratasAndSubstratasIdsForProgram(programZoneId);
1264 
1265             if (protocol.isUseCalcifiedPieceSampling() && !protocol.isZoneEmpty()) {
1266 
1267                 protocol.getZone().forEach(zone -> {
1268 
1269                     ImmutableSet<Integer> allLocationIds = Zones.getAllLocationIds(zone);
1270 
1271                     for (Integer locationId : allLocationIds) {
1272 
1273                         if (!availableLocationIds.contains(locationId)) {
1274 
1275                             throw new ApplicationBusinessException("Le protocole utilise une strate d'identifiant " + locationId + " non reconnue dans le système.");
1276 
1277                         }
1278                     }
1279                 });
1280             }
1281 
1282         }
1283 
1284         return protocol;
1285     }
1286 
1287     @Override
1288     public TuttiProtocol getProtocolByName(String protocolName) {
1289         return driver.getProtocolByName(protocolName);
1290     }
1291 
1292     @Override
1293     public TuttiProtocol createProtocol(TuttiProtocol bean) {
1294         return driver.createProtocol(bean);
1295     }
1296 
1297     @Override
1298     public TuttiProtocol saveProtocol(TuttiProtocol bean) {
1299         return driver.saveProtocol(bean);
1300     }
1301 
1302     @Override
1303     public void deleteProtocol(String id) {
1304         driver.deleteProtocol(id);
1305     }
1306 
1307     //------------------------------------------------------------------------//
1308     //-- FishingOperation methods                                           --//
1309     //------------------------------------------------------------------------//
1310 
1311     @Override
1312     public int getFishingOperationCount(Integer cruiseId) {
1313         return driver.getFishingOperationCount(cruiseId);
1314     }
1315 
1316     @Override
1317     public List<Integer> getAllFishingOperationIds(Integer cruiseId) {
1318         return driver.getAllFishingOperationIds(cruiseId);
1319     }
1320 
1321     @Override
1322     public List<FishingOperation> getAllFishingOperation(Integer cruiseId) {
1323         return driver.getAllFishingOperation(cruiseId);
1324     }
1325 
1326     @Override
1327     public FishingOperation getFishingOperation(Integer id) {
1328         FishingOperation bean = driver.getFishingOperation(id);
1329         // see http://forge.codelutin.com/issues/2014
1330         if (bean.getGearShootingEndDate() == null) {
1331             bean.setGearShootingEndDate(bean.getGearShootingStartDate());
1332         }
1333         return bean;
1334     }
1335 
1336     @Override
1337     public List<Vessel> getFishingOperationSecondaryVessel(Integer fishingOperationId) {
1338         return driver.getFishingOperationSecondaryVessel(fishingOperationId);
1339     }
1340 
1341     @Override
1342     public FishingOperation createFishingOperation(FishingOperation bean) {
1343 
1344         // see http://forge.codelutin.com/issues/2014
1345         if (Objects.equals(bean.getGearShootingStartDate(), bean.getGearShootingEndDate())) {
1346             bean.setGearShootingEndDate(null);
1347         }
1348         return driver.createFishingOperation(bean);
1349     }
1350 
1351     @Override
1352     public FishingOperation saveFishingOperation(FishingOperation bean) {
1353         // see http://forge.codelutin.com/issues/2014
1354         if (Objects.equals(bean.getGearShootingStartDate(), bean.getGearShootingEndDate())) {
1355             bean.setGearShootingEndDate(null);
1356         }
1357 
1358         Optional<CruiseCache> optionalCruiseCache = getOptionalCruiseCache();
1359 
1360         boolean reloadSamplingCache = false;
1361 
1362         if (optionalCruiseCache.isPresent()) {
1363 
1364             CruiseCache cruiseCache = optionalCruiseCache.get();
1365 
1366             if (optionalCruiseCache.isPresent()) {
1367 
1368                 Optional<CruiseSamplingCache> optionalSamplingCruiseCache = cruiseCache.getSamplingCruiseCache();
1369 
1370                 if (optionalSamplingCruiseCache.isPresent()) {
1371 
1372                     // on doit vérifier si l'opération n'a pas changée de zone
1373                     CruiseSamplingCache cruiseSamplingCache = optionalSamplingCruiseCache.get();
1374 
1375                     FishingOperation oldFishingOperation = getFishingOperation(bean.getIdAsInt());
1376 
1377                     boolean zoneChanged = cruiseSamplingCache.isZoneChanged(oldFishingOperation, bean);
1378 
1379                     if (zoneChanged) {
1380 
1381                         // les strates ou sous-strates ont changées, il faut recalculer le cache des échantillons
1382                         if (log.isInfoEnabled()) {
1383                             log.info("Zone has changed for fishingOperation: " + bean + ", remove fishing operation from cruise cache.");
1384                         }
1385                         reloadSamplingCache = true;
1386 
1387                         cruiseSamplingCache.printInfos("Before removing fishing operation");
1388 
1389                         List<IndividualObservationBatch> individualObservations = getAllIndividualObservationBatchsForFishingOperation(bean.getIdAsInt());
1390                         cruiseCache.removeFishingOperation(oldFishingOperation, individualObservations);
1391 
1392                     }
1393 
1394                 }
1395 
1396             }
1397 
1398         }
1399 
1400         FishingOperation fishingOperation = driver.saveFishingOperation(bean);
1401 
1402         if (optionalCruiseCache.isPresent() && reloadSamplingCache) {
1403 
1404             if (log.isInfoEnabled()) {
1405                 log.info("Zone has changed for fishingOperation: " + bean + ", recompute fishing operation from cruise cache.");
1406             }
1407 
1408             CruiseCache cruiseCache = optionalCruiseCache.get();
1409 
1410             CruiseSamplingCache cruiseSamplingCache = cruiseCache.getSamplingCruiseCache().orElseGet(null);
1411 
1412             cruiseSamplingCache.printInfos("Before loading " + fishingOperation);
1413 
1414             CruiseCacheLoader cruiseCacheLoader = CruiseCacheLoader.newCacheLoader(this, context.getService(DecoratorService.class), null, cruiseCache);
1415             cruiseCacheLoader.loadCruiseCacheForFishingOperation(fishingOperation);
1416 
1417             cruiseSamplingCache.printInfos("After  loading " + fishingOperation);
1418 
1419         }
1420 
1421         return fishingOperation;
1422     }
1423 
1424     //FIXME Remove this ? can't find where it is used...
1425     @Override
1426     public Collection<FishingOperation> saveFishingOperations(Collection<FishingOperation> beans) {
1427         return driver.saveFishingOperations(beans);
1428     }
1429 
1430     @Override
1431     public void deleteFishingOperation(Integer id) {
1432         Optional<CruiseCache> optionalCruiseCache = getOptionalCruiseCache();
1433         if (optionalCruiseCache.isPresent()) {
1434 
1435             CruiseCache cruiseCache = optionalCruiseCache.get();
1436             if (log.isInfoEnabled()) {
1437                 log.info("Remove fishing operation: " + id + " from cruiseSamplingCache: " + cruiseCache);
1438             }
1439             FishingOperation fishingOperation = getFishingOperation(id);
1440 
1441             List<IndividualObservationBatch> individualObservations = getAllIndividualObservationBatchsForFishingOperation(id);
1442 
1443             optionalCruiseCache.get().removeFishingOperation(fishingOperation, individualObservations);
1444         }
1445         driver.deleteFishingOperation(id);
1446     }
1447 
1448     //------------------------------------------------------------------------//
1449     //-- CatchBatch methods                                                 --//
1450     //------------------------------------------------------------------------//
1451 
1452     @Override
1453     public boolean isFishingOperationWithCatchBatch(Integer operationId) {
1454         return driver.isFishingOperationWithCatchBatch(operationId);
1455     }
1456 
1457     @Override
1458     public CatchBatch getCatchBatchFromFishingOperation(Integer id) throws InvalidBatchModelException {
1459         return driver.getCatchBatchFromFishingOperation(id);
1460 
1461     }
1462 
1463     @Override
1464     public CatchBatch createCatchBatch(CatchBatch bean) {
1465         return driver.createCatchBatch(bean);
1466     }
1467 
1468     @Override
1469     public CatchBatch saveCatchBatch(CatchBatch bean) {
1470         return driver.saveCatchBatch(bean);
1471     }
1472 
1473     @Override
1474     public void deleteCatchBatch(Integer fishingOperationId) {
1475         driver.deleteCatchBatch(fishingOperationId);
1476     }
1477 
1478     @Override
1479     public void recomputeCatchBatchSampleRatios(Integer fishingOperationId) {
1480         driver.recomputeCatchBatchSampleRatios(fishingOperationId);
1481     }
1482 
1483     @Override
1484     public Map getPrevOperationNameAndBatchId(int operationId, int taxonId) {
1485         return driver.getPrevOperationNameAndBatchId(operationId, taxonId);
1486     }
1487 
1488     @Override
1489     public Map getNextOperationNameAndBatchId(int operationId, int taxonId) {
1490         return driver.getNextOperationNameAndBatchId(operationId, taxonId);
1491     }
1492 
1493     //------------------------------------------------------------------------//
1494     //-- Species Batch methods                                              --//
1495     //------------------------------------------------------------------------//
1496 
1497     @Override
1498     public BatchContainer<SpeciesBatch> getRootSpeciesBatch(Integer fishingOperationId, boolean validateTree) {
1499         return driver.getRootSpeciesBatch(fishingOperationId, validateTree);
1500     }
1501 
1502     @Override
1503     public Set<Integer> getBatchChildIds(Integer id) {
1504         return driver.getBatchChildIds(id);
1505     }
1506 
1507     @Override
1508     public SpeciesBatch createSpeciesBatch(SpeciesBatch bean, Integer parentBatchId, boolean computeRankOrder) {
1509         return driver.createSpeciesBatch(bean, parentBatchId, computeRankOrder);
1510     }
1511 
1512     @Override
1513     public Collection<SpeciesBatch> createSpeciesBatches(Integer fishingOperationId, Collection<SpeciesBatch> beans) {
1514         return driver.createSpeciesBatches(fishingOperationId, beans);
1515     }
1516 
1517     @Override
1518     public SpeciesBatch saveSpeciesBatch(SpeciesBatch bean) {
1519         return driver.saveSpeciesBatch(bean);
1520     }
1521 
1522     @Override
1523     public void deleteSpeciesBatch(Integer id) {
1524         beforeDeleteBatch(id, true);
1525         driver.deleteSpeciesBatch(id);
1526     }
1527 
1528     @Override
1529     public void deleteSpeciesSubBatch(Integer id) {
1530         beforeDeleteBatch(id, false);
1531         driver.deleteSpeciesSubBatch(id);
1532     }
1533 
1534     @Override
1535     public void changeSpeciesBatchSpecies(Integer batchId, Species species) {
1536         driver.changeSpeciesBatchSpecies(batchId, species);
1537     }
1538 
1539     @Override
1540     public List<SpeciesBatch> getAllSpeciesBatchToConfirm(Integer fishingOperationId) throws InvalidBatchModelException {
1541         return driver.getAllSpeciesBatchToConfirm(fishingOperationId);
1542     }
1543 
1544     @Override
1545     public List<SpeciesBatchFrequency> getAllSpeciesBatchFrequency(Integer speciesBatchId) {
1546         return driver.getAllSpeciesBatchFrequency(speciesBatchId);
1547     }
1548 
1549     @Override
1550     public Multimap<Species, SpeciesBatchFrequency> getAllSpeciesBatchFrequencyForBatch(BatchContainer<SpeciesBatch> batchContainer) {
1551         return driver.getAllSpeciesBatchFrequencyForBatch(batchContainer);
1552     }
1553 
1554     @Override
1555     public List<SpeciesBatchFrequency> saveSpeciesBatchFrequency(Integer speciesBatchId,
1556                                                                  List<SpeciesBatchFrequency> frequencies) {
1557         return driver.saveSpeciesBatchFrequency(speciesBatchId, frequencies);
1558     }
1559 
1560     //------------------------------------------------------------------------//
1561     //-- Benthos Batch methods                                              --//
1562     //------------------------------------------------------------------------//
1563 
1564     @Override
1565     public BatchContainer<SpeciesBatch> getRootBenthosBatch(Integer fishingOperationId, boolean validateTree) throws InvalidBatchModelException {
1566         return driver.getRootBenthosBatch(fishingOperationId, validateTree);
1567     }
1568 
1569     @Override
1570     public SpeciesBatch createBenthosBatch(SpeciesBatch bean, Integer parentBatchId, boolean computeRankOrder) {
1571         return driver.createBenthosBatch(bean, parentBatchId, computeRankOrder);
1572     }
1573 
1574     @Override
1575     public Collection<SpeciesBatch> createBenthosBatches(Integer fishingOperationId, Collection<SpeciesBatch> beans) {
1576         return driver.createBenthosBatches(fishingOperationId, beans);
1577     }
1578 
1579     @Override
1580     public SpeciesBatch saveBenthosBatch(SpeciesBatch bean) {
1581         return driver.saveBenthosBatch(bean);
1582     }
1583 
1584     @Override
1585     public void deleteBenthosBatch(Integer id) {
1586         beforeDeleteBatch(id, true);
1587         driver.deleteBenthosBatch(id);
1588     }
1589 
1590     @Override
1591     public void deleteBenthosSubBatch(Integer id) {
1592         beforeDeleteBatch(id, false);
1593         driver.deleteBenthosSubBatch(id);
1594     }
1595 
1596     @Override
1597     public void changeBenthosBatchSpecies(Integer batchId, Species species) {
1598         driver.changeBenthosBatchSpecies(batchId, species);
1599     }
1600 
1601     @Override
1602     public List<SpeciesBatch> getAllBenthosBatchToConfirm(Integer fishingOperationId) throws InvalidBatchModelException {
1603         return driver.getAllBenthosBatchToConfirm(fishingOperationId);
1604     }
1605 
1606     @Override
1607     public List<SpeciesBatchFrequency> getAllBenthosBatchFrequency(Integer benthosBatchId) {
1608         return driver.getAllBenthosBatchFrequency(benthosBatchId);
1609     }
1610 
1611     @Override
1612     public Multimap<Species, SpeciesBatchFrequency> getAllBenthosBatchFrequencyForBatch(BatchContainer<SpeciesBatch> batchContainer) {
1613         return driver.getAllBenthosBatchFrequencyForBatch(batchContainer);
1614     }
1615 
1616     @Override
1617     public List<SpeciesBatchFrequency> saveBenthosBatchFrequency(Integer benthosBatchId, List<SpeciesBatchFrequency> frequencies) {
1618         return driver.saveBenthosBatchFrequency(benthosBatchId, frequencies);
1619     }
1620 
1621     //------------------------------------------------------------------------//
1622     //-- MarineLitter Batch methods                                         --//
1623     //------------------------------------------------------------------------//
1624 
1625     @Override
1626     public BatchContainer<MarineLitterBatch> getRootMarineLitterBatch(Integer fishingOperationId) {
1627         return driver.getRootMarineLitterBatch(fishingOperationId);
1628     }
1629 
1630     @Override
1631     public MarineLitterBatch createMarineLitterBatch(MarineLitterBatch bean) {
1632         return driver.createMarineLitterBatch(bean);
1633     }
1634 
1635     @Override
1636     public Collection<MarineLitterBatch> createMarineLitterBatches(Integer fishingOperationId, Collection<MarineLitterBatch> beans) {
1637         return driver.createMarineLitterBatches(fishingOperationId, beans);
1638     }
1639 
1640     @Override
1641     public MarineLitterBatch saveMarineLitterBatch(MarineLitterBatch bean) {
1642         return driver.saveMarineLitterBatch(bean);
1643     }
1644 
1645     @Override
1646     public void deleteMarineLitterBatch(Integer id) {
1647         driver.deleteMarineLitterBatch(id);
1648     }
1649 
1650     //------------------------------------------------------------------------//
1651     //-- Accidental Batch methods                                           --//
1652     //------------------------------------------------------------------------//
1653 
1654     @Override
1655     public List<AccidentalBatch> getAllAccidentalBatch(Integer fishingOperationId) {
1656         return driver.getAllAccidentalBatch(fishingOperationId);
1657     }
1658 
1659     @Override
1660     public Collection<AccidentalBatch> createAccidentalBatches(Collection<AccidentalBatch> beans) {
1661         return driver.createAccidentalBatches(beans);
1662     }
1663 
1664     @Override
1665     public AccidentalBatch createAccidentalBatch(AccidentalBatch bean) {
1666         return driver.createAccidentalBatch(bean);
1667     }
1668 
1669     @Override
1670     public AccidentalBatch saveAccidentalBatch(AccidentalBatch bean) {
1671         return driver.saveAccidentalBatch(bean);
1672     }
1673 
1674     @Override
1675     public void deleteAccidentalBatch(String id) {
1676         driver.deleteAccidentalBatch(id);
1677     }
1678 
1679     @Override
1680     public void deleteAccidentalBatchForFishingOperation(Integer fishingOperationId) {
1681         driver.deleteAccidentalBatchForFishingOperation(fishingOperationId);
1682     }
1683 
1684     //------------------------------------------------------------------------//
1685     //-- IndividualObservation Batch methods                                --//
1686     //------------------------------------------------------------------------//
1687 
1688     @Override
1689     public List<IndividualObservationBatch> getAllIndividualObservationBatchsForBatch(Integer batchId) {
1690         return driver.getAllIndividualObservationBatchsForBatch(batchId);
1691     }
1692 
1693     @Override
1694     public List<IndividualObservationBatch> getAllIndividualObservationBatchsForFishingOperation(Integer fishingOperationId) {
1695         return driver.getAllIndividualObservationBatchsForFishingOperation(fishingOperationId);
1696     }
1697 
1698     @Override
1699     public List<IndividualObservationBatch> getAllIndividualObservationBatchsForCruise(Integer cruiseId) {
1700         return driver.getAllIndividualObservationBatchsForCruise(cruiseId);
1701     }
1702 
1703     @Override
1704     public boolean isSamplingCodeAvailable(Integer cruiseId, Integer referenceTaxonId, String samplingCodeSuffix) {
1705         return driver.isSamplingCodeAvailable(cruiseId, referenceTaxonId, samplingCodeSuffix);
1706     }
1707 
1708     @Override
1709     public List<IndividualObservationBatch> createIndividualObservationBatches(FishingOperation fishingOperation, Collection<IndividualObservationBatch> individualObservations) {
1710 
1711         Optional<CruiseCache> optionalCruiseCache = getOptionalCruiseCache();
1712 
1713         if (optionalCruiseCache.isPresent()) {
1714 
1715             // on supprime du cache les observation individuelles de l'opération
1716             CruiseCache cruiseCache = optionalCruiseCache.get();
1717 
1718             List<IndividualObservationBatch> individualObservationsToRemove = getAllIndividualObservationBatchsForFishingOperation(fishingOperation.getIdAsInt());
1719 
1720             if (log.isInfoEnabled()) {
1721                 log.info("Remove from cruise sampling cache: " + fishingOperation + " with " + individualObservationsToRemove.size() + " individual observations.");
1722             }
1723             cruiseCache.removeFishingOperation(fishingOperation, individualObservationsToRemove);
1724 
1725         }
1726 
1727         List<IndividualObservationBatch> individualObservationBatches = driver.createIndividualObservationBatches(fishingOperation, individualObservations);
1728 
1729         if (optionalCruiseCache.isPresent()) {
1730 
1731             // on ajoute les observation individuelles de l'opération du cache
1732             CruiseCache cruiseCache = optionalCruiseCache.get();
1733 
1734             List<IndividualObservationBatch> individualObservationsToAdd = getAllIndividualObservationBatchsForFishingOperation(fishingOperation.getIdAsInt());
1735             if (log.isInfoEnabled()) {
1736                 log.info("Add to cruise sampling cache: " + fishingOperation + " with " + individualObservationsToAdd.size() + " individual observations.");
1737             }
1738             cruiseCache.addFishingOperation(fishingOperation, individualObservationsToAdd);
1739 
1740         }
1741 
1742         return individualObservationBatches;
1743     }
1744 
1745     @Override
1746     public List<IndividualObservationBatch> saveBatchIndividualObservation(Integer batchId, List<IndividualObservationBatch> individualObservation) {
1747         return driver.saveBatchIndividualObservation(batchId, individualObservation);
1748     }
1749 
1750     @Override
1751     public void deleteAllIndividualObservationsForFishingOperation(Integer fishingOperationId) {
1752         driver.deleteAllIndividualObservationsForFishingOperation(fishingOperationId);
1753     }
1754 
1755     @Override
1756     public void deleteAllIndividualObservationsForBatch(Integer speciesBatchId) {
1757         driver.deleteAllIndividualObservationsForBatch(speciesBatchId);
1758     }
1759 
1760     protected void beforeDeleteBatch(Integer id, boolean addBatchId) {
1761 
1762         Optional<CruiseCache> optionalCruiseCache = getOptionalCruiseCache();
1763         if (optionalCruiseCache.isPresent()) {
1764 
1765             CruiseCache cruiseCache = optionalCruiseCache.get();
1766 
1767             FishingOperation fishingOperation = context.getDataContext().getFishingOperation();
1768 
1769             Set<Integer> batchIds = new LinkedHashSet<>();
1770             if (addBatchId) {
1771                 batchIds.add(id);
1772             }
1773             batchIds.addAll(getBatchChildIds(id));
1774 
1775             batchIds.forEach(speciesBatchId -> {
1776 
1777                 List<IndividualObservationBatch> individualObservations = getAllIndividualObservationBatchsForBatch(speciesBatchId);
1778 
1779                 if (!individualObservations.isEmpty()) {
1780 
1781                     if (log.isInfoEnabled()) {
1782                         log.info("Remove for species or benthos batch: " + speciesBatchId + " - " + individualObservations.size() + " individual observations from cruiseSamplingCache: " + cruiseCache);
1783                     }
1784 
1785                     cruiseCache.removeIndividualObservations(fishingOperation, individualObservations);
1786 
1787                 }
1788 
1789             });
1790 
1791         }
1792 
1793     }
1794 
1795     private Optional<CruiseCache> getOptionalCruiseCache() {
1796         return context.getDataContext().getOptionalCruiseCache();
1797     }
1798 
1799 }