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.Preconditions;
26  import fr.ifremer.tutti.TuttiConfiguration;
27  import fr.ifremer.tutti.persistence.entities.data.Cruise;
28  import fr.ifremer.tutti.persistence.entities.data.FishingOperation;
29  import fr.ifremer.tutti.persistence.entities.data.Program;
30  import fr.ifremer.tutti.persistence.entities.data.SampleCategoryModel;
31  import fr.ifremer.tutti.persistence.entities.data.SampleCategoryModelEntry;
32  import fr.ifremer.tutti.persistence.entities.protocol.SpeciesProtocol;
33  import fr.ifremer.tutti.persistence.entities.protocol.TuttiProtocol;
34  import fr.ifremer.tutti.persistence.entities.protocol.TuttiProtocols;
35  import fr.ifremer.tutti.persistence.entities.referential.Caracteristic;
36  import fr.ifremer.tutti.persistence.entities.referential.CaracteristicQualitativeValue;
37  import fr.ifremer.tutti.persistence.entities.referential.Gear;
38  import fr.ifremer.tutti.persistence.entities.referential.Person;
39  import fr.ifremer.tutti.persistence.entities.referential.Species;
40  import fr.ifremer.tutti.persistence.entities.referential.TaxonCache;
41  import fr.ifremer.tutti.persistence.entities.referential.TaxonCaches;
42  import fr.ifremer.tutti.persistence.entities.referential.Vessel;
43  import fr.ifremer.tutti.service.cruise.CruiseCache;
44  import fr.ifremer.tutti.service.cruise.CruiseCacheLoader;
45  import org.apache.commons.lang3.StringUtils;
46  import org.apache.commons.logging.Log;
47  import org.apache.commons.logging.LogFactory;
48  import org.jdesktop.beans.AbstractBean;
49  
50  import java.io.Closeable;
51  import java.util.ArrayList;
52  import java.util.List;
53  import java.util.Map;
54  import java.util.Optional;
55  import java.util.stream.Collectors;
56  
57  /**
58   * Data context of ui.
59   *
60   * All shared data must be there to avoid reloading some stuff.
61   *
62   * @author Tony Chemit - chemit@codelutin.com
63   * @since 1.0.2
64   */
65  public class TuttiDataContext extends AbstractBean implements Closeable {
66  
67      /** Logger. */
68      private static final Log log = LogFactory.getLog(TuttiDataContext.class);
69  
70      public static final String PROPERTY_PROGRAM_ID = "programId";
71  
72      public static final String PROPERTY_CRUISE_ID = "cruiseId";
73  
74      public static final String PROPERTY_PROTOCOL_ID = "protocolId";
75  
76      public static final String PROPERTY_FISHING_OPERATION_ID = "fishingOperationId";
77  
78      public static final String PROPERTY_PROGRAM_FILLED = "programFilled";
79  
80      public static final String PROPERTY_CRUISE__FILLED = "cruiseFilled";
81  
82      public static final String PROPERTY_PROTOCOL_FILLED = "protocolFilled";
83  
84      public static final String PROPERTY_FISHING_OPERATION_FILLED = "fishingOperationFilled";
85  
86      /**
87       * Id of last selected program (can be null if none ever selected).
88       *
89       * @since 0.1
90       */
91      protected String programId;
92  
93      /**
94       * Id of last selected cruise (can be null if none ever selected).
95       *
96       * @since 0.1
97       */
98      protected Integer cruiseId;
99  
100     /**
101      * Id of last selected protocol (can be null if none ever selected).
102      *
103      * @since 0.1
104      */
105     protected String protocolId;
106 
107     /**
108      * Id of last selected fishing operation (can be null if none ever selected).
109      *
110      * @since 1.2
111      */
112     protected Integer fishingOperationId;
113 
114     /**
115      * Model of sampling as defined in configuration.
116      *
117      * @since 2.4
118      */
119     protected SampleCategoryModel sampleCategoryModel;
120 
121     /**
122      * Flag to reload sampleCategoryModel in lazy mode.
123      *
124      * @since 3.13
125      */
126     protected boolean dirtySampleCategoryModel;
127 
128     protected Program program;
129 
130     protected Cruise cruise;
131 
132     /**
133      * Le cache des données liées à la campagne sélectionnée.
134      *
135      * @since 4.5
136      */
137     protected CruiseCache cruiseCache;
138 
139     protected FishingOperation fishingOperation;
140 
141     protected List<Caracteristic> caracteristics;
142 
143     protected List<Caracteristic> caracteristicsWithProtected;
144 
145     protected List<Caracteristic> lengthStepCaracteristics;
146 
147     protected List<Caracteristic> maturityCaracteristics;
148 
149     protected List<CaracteristicQualitativeValue> genderValues;
150 
151     protected List<CaracteristicQualitativeValue> deadOrAliveValues;
152 
153     protected List<CaracteristicQualitativeValue> cpsTypeValues;
154 
155     protected List<Person> persons;
156 
157     protected List<Species> species;
158 
159     protected List<Species> referentSpeciesWithSurveyCode;
160 
161     protected List<Species> referentBenthosWithSurveyCode;
162 
163     protected List<Species> referentSpecies;
164 
165     protected List<Vessel> fishingVessels;
166 
167     protected List<Vessel> scientificVessels;
168 
169     protected List<Gear> fishingGears;
170 
171     protected List<Gear> scientificGears;
172 
173     protected List<Caracteristic> defaultIndividualObservationCaracteristics;
174 
175     protected TuttiValidationDataContextSupport validationContext = new TuttiValidationDataContext(this);
176 
177     protected PersistenceService service;
178 
179     TuttiDataContext() {
180         addPropertyChangeListener(PROPERTY_PROGRAM_ID, evt -> resetProgram());
181         addPropertyChangeListener(PROPERTY_CRUISE_ID, evt -> resetCruise());
182         addPropertyChangeListener(PROPERTY_PROTOCOL_ID, evt -> resetProtocol());
183         addPropertyChangeListener(PROPERTY_FISHING_OPERATION_ID, evt -> resetFishingOperation());
184     }
185 
186     public void setPersistenceService(PersistenceService service) {
187         this.service = service;
188     }
189 
190     public void open(TuttiConfiguration config) {
191 
192         PersistenceService persistenceService = this.service;
193 
194         // Check there is a persistence service injected
195         Preconditions.checkNotNull(persistenceService, "Can't have a null persistence service.");
196 
197         // Close data context
198         close();
199 
200         // Reset the persistence service
201         this.service = persistenceService;
202 
203         // load protocol and propagate it to service
204         if (isProtocolFilled()) {
205 
206             if (!persistenceService.isProtocolExist(getProtocolId())) {
207 
208                 if (log.isErrorEnabled()) {
209                     log.error("Could not find protocol with id: " + getProtocolId());
210                 }
211 
212                 setProtocolId(null);
213 
214             } else {
215 
216                 try {
217                     getProtocol();
218                 } catch (Exception e) {
219 
220                     if (log.isErrorEnabled()) {
221                         log.error("Could not use load protocol with id:" + getProtocolId(), e);
222                     }
223                     setProtocolId(null);
224 
225                 }
226 
227             }
228 
229         }
230         setSampleCategoryModel(config.getSampleCategoryModel());
231     }
232 
233     @Override
234     public void close() {
235         clearContext();
236         service = null;
237     }
238 
239     public void clearContext() {
240         resetProgram();
241         dirtySampleCategoryModel = true;
242         resetProtocol();
243         resetVessels();
244         resetGears();
245         resetPersons();
246         resetSpecies();
247         resetValidationDataContext();
248         resetCaracteristics();
249     }
250 
251     public void checkDbContext() {
252 
253         String saneProtocolId = null;
254         String saneProgramId = null;
255         Integer saneCruiseId = null;
256 
257         String oldProtocolId = getProtocolId();
258         String oldProgramId = getProgramId();
259         Integer oldCruiseId = getCruiseId();
260 
261         if (isProtocolFilled()) {
262 
263             if (!service.isProtocolExist(oldProtocolId)) {
264 
265                 // not found in this db
266 
267                 if (log.isWarnEnabled()) {
268                     log.warn("Remove invalid protocolId: " + oldProtocolId);
269                 }
270 
271             } else {
272                 if (log.isInfoEnabled()) {
273                     log.info("protocolId valid: " + oldProtocolId);
274                 }
275 
276                 // can keep this id
277                 saneProtocolId = oldProtocolId;
278             }
279         }
280 
281         if (isProgramFilled()) {
282 
283 
284             Program program = null;
285 
286             try {
287                 program = service.getProgram(oldProgramId);
288             } catch (Exception e) {
289                 // program does not exist
290             }
291             if (program == null) {
292 
293                 // not found in this db
294 
295                 if (log.isWarnEnabled()) {
296                     log.warn("Remove invalid programId: " + oldProgramId);
297                 }
298 
299             } else {
300 
301                 if (log.isInfoEnabled()) {
302                     log.info("ProgramId valid: " + oldProgramId);
303                 }
304 
305                 // can keep this id
306 
307                 saneProgramId = oldProgramId;
308 
309                 // test cruiseId
310                 if (isCruiseFilled()) {
311 
312                     Cruise cruise = null;
313 
314 
315                     try {
316                         cruise = service.getCruise(oldCruiseId);
317                     } catch (Exception e) {
318                         // cruise does not exist
319                     }
320 
321                     if (cruise != null &&
322                             !cruise.getProgram().getId().equals(oldProgramId)) {
323 
324                         // not matchin program, reset cruise id
325                         cruise = null;
326                     }
327 
328                     if (cruise == null) {
329 
330                         // not found in this db
331 
332                         if (log.isWarnEnabled()) {
333                             log.warn("Remove invalid cruiseId: " + oldCruiseId);
334                         }
335                         setCruiseId(null);
336 
337                     } else {
338 
339                         if (log.isInfoEnabled()) {
340                             log.info("CruiseId valid: " + oldCruiseId);
341                         }
342 
343                         // can keep this id
344                         saneCruiseId = oldCruiseId;
345                     }
346                 }
347             }
348         }
349 
350         boolean oldProtocolFilled = isProtocolFilled();
351         boolean oldProgramFilled = isProgramFilled();
352         boolean oldCruiseFilled = isCruiseFilled();
353         this.programId = saneProgramId;
354         this.cruiseId = saneCruiseId;
355         this.protocolId = saneProtocolId;
356 
357         firePropertyChange(PROPERTY_PROGRAM_FILLED, oldProgramFilled, isProgramFilled());
358         firePropertyChange(PROPERTY_PROTOCOL_FILLED, oldProtocolFilled, isProtocolFilled());
359         firePropertyChange(PROPERTY_CRUISE__FILLED, oldCruiseFilled, isCruiseFilled());
360         firePropertyChange(PROPERTY_PROGRAM_ID, oldProgramId, saneProgramId);
361         firePropertyChange(PROPERTY_PROTOCOL_ID, oldProtocolId, saneProtocolId);
362         firePropertyChange(PROPERTY_CRUISE_ID, oldCruiseId, saneCruiseId);
363     }
364 
365     public SampleCategoryModel getSampleCategoryModel() {
366         if (dirtySampleCategoryModel) {
367 
368             try {
369                 if (log.isInfoEnabled()) {
370                     log.info("Loading sampleCategoryModel: " + sampleCategoryModel);
371                 }
372                 sampleCategoryModel.load(service);
373             } finally {
374 
375                 dirtySampleCategoryModel = false;
376             }
377 
378         }
379         return sampleCategoryModel;
380     }
381 
382     public void setSampleCategoryModel(SampleCategoryModel sampleCategoryModel) {
383         Preconditions.checkNotNull(sampleCategoryModel, "Can't get a null sampleCategoryModel");
384         this.sampleCategoryModel = sampleCategoryModel;
385         this.dirtySampleCategoryModel = true;
386     }
387 
388     public String getProgramId() {
389         return programId;
390     }
391 
392     public Integer getCruiseId() {
393         return cruiseId;
394     }
395 
396     public String getProtocolId() {
397         return protocolId;
398     }
399 
400     public Integer getFishingOperationId() {
401         return fishingOperationId;
402     }
403 
404     /**
405      * @return {@code true} si une campache est charfée.
406      */
407     public boolean isCruiseFilled() {
408         return isProgramFilled() && cruiseId != null;
409     }
410 
411     /**
412      * @return {@code true} si un protocol est chargé.
413      */
414     public boolean isProtocolFilled() {
415         return StringUtils.isNotBlank(protocolId);
416     }
417 
418     /**
419      * @return {@code true} si une série de campagne est chargée.
420      */
421     public boolean isProgramFilled() {
422         return StringUtils.isNotBlank(programId);
423     }
424 
425     /**
426      * @return {@code true} si une opérationde pêche est chargée.
427      */
428     public boolean isFishingOperationFilled() {
429         return fishingOperationId != null;
430     }
431 
432     /**
433      * @return {@code true} si on peut utiliser le cache sur la campagne.
434      */
435     public boolean isCanUseCruiseCache() {
436         return isCruiseFilled();
437     }
438 
439     /**
440      * @return {@code true} si le cache de campagne est chargé.
441      */
442     public boolean isCruiseCacheLoaded() {
443         return cruiseCache != null;
444     }
445 
446     /**
447      * @return {@code true} si le cache de campagne est à jour.
448      */
449     public boolean isCruiseCacheUpToDate() {
450         return isCruiseCacheLoaded() && cruiseCache.isCacheUpToDate(getCruiseId(), getProtocolId());
451     }
452 
453     /**
454      * @return {@code true} si on peut utiliser le cache de prélèvement des pièces calcifiées.
455      */
456     public boolean isCanUseCruiseSamplingCache() {
457         return isCanUseCruiseCache() && isProtocolFilled() && getProtocol().isUseCalcifiedPieceSampling();
458     }
459 
460     public void setProgramId(String programId) {
461         boolean oldProgramFilled = isProgramFilled();
462         boolean oldCruiseFilled = isCruiseFilled();
463 
464         this.programId = programId;
465 
466         // always propagate the change
467         firePropertyChange(PROPERTY_PROGRAM_ID, -1, programId);
468         firePropertyChange(PROPERTY_PROGRAM_FILLED, oldProgramFilled, isProgramFilled());
469         firePropertyChange(PROPERTY_CRUISE__FILLED, oldCruiseFilled, isCruiseFilled());
470     }
471 
472     public void setCruiseId(Integer cruiseId) {
473         boolean oldValue = isCruiseFilled();
474 
475         this.cruiseId = cruiseId;
476 
477         // always propagate the change
478         firePropertyChange(PROPERTY_CRUISE_ID, -1, cruiseId);
479         firePropertyChange(PROPERTY_CRUISE__FILLED,
480                            oldValue, isCruiseFilled());
481     }
482 
483     public void setProtocolId(String protocolId) {
484         boolean oldValue = isProtocolFilled();
485         this.protocolId = protocolId;
486 
487         // always propagate the change
488         firePropertyChange(PROPERTY_PROTOCOL_ID, -1, protocolId);
489         firePropertyChange(PROPERTY_PROTOCOL_FILLED,
490                            oldValue, isProtocolFilled());
491 
492         if (getService() != null) {
493             // always reload protocol (as a side-effect push it to protocol service)
494             getProtocol();
495         }
496     }
497 
498     public void setFishingOperationId(Integer fishingOperationId) {
499         boolean oldValue = isFishingOperationFilled();
500         this.fishingOperationId = fishingOperationId;
501 
502         // always propagate the change
503         firePropertyChange(PROPERTY_FISHING_OPERATION_ID, -1, fishingOperationId);
504         firePropertyChange(PROPERTY_FISHING_OPERATION_FILLED, oldValue, isFishingOperationFilled());
505     }
506 
507     public Program getProgram() {
508         checkOpened();
509         if (program == null) {
510             if (isProgramFilled()) {
511                 String id = getProgramId();
512                 if (log.isInfoEnabled()) {
513                     log.info("Loading program: " + id);
514                 }
515                 program = service.getProgram(id);
516             }
517         }
518         return program;
519     }
520 
521     public Cruise getCruise() {
522         checkOpened();
523         if (cruise == null) {
524             if (isCruiseFilled()) {
525                 Integer id = getCruiseId();
526                 if (log.isInfoEnabled()) {
527                     log.info("Loading cruise: " + id);
528                 }
529                 cruise = service.getCruise(id);
530             }
531         }
532         return cruise;
533     }
534 
535     public Cruise reloadCruise() {
536         checkOpened();
537         Preconditions.checkState(isCruiseFilled());
538         Integer id = getCruiseId();
539         if (log.isInfoEnabled()) {
540             log.info("Reloading cruise: " + id);
541         }
542         cruise = service.getCruise(id);
543         return cruise;
544     }
545 
546     public TuttiProtocol getProtocol() {
547         checkOpened();
548         if (isProtocolFilled()) {
549             TuttiProtocol protocol = service.getProtocol();
550             if (protocol == null) {
551                 String id = getProtocolId();
552                 if (log.isInfoEnabled()) {
553                     log.info("Loading protocol: " + id + " for service: " + service);
554                 }
555                 protocol = service.getProtocol(id);
556                 service.setProtocol(protocol);
557             }
558         } else {
559             TuttiProtocol protocol = service.getProtocol();
560             if (protocol != null) {
561                 if (log.isInfoEnabled()) {
562                     log.info("Remove protocol: " + protocol);
563                 }
564                 service.setProtocol(null);
565             }
566         }
567         return service.getProtocol();
568     }
569 
570     public Optional<CruiseCache> getOptionalCruiseCache() {
571         return Optional.ofNullable(isCruiseCacheUpToDate() ? cruiseCache : null);
572     }
573 
574     public void loadCruiseCache(CruiseCacheLoader cruiseCacheLoader) {
575 
576         checkOpened();
577 
578         if (!isCanUseCruiseCache()) {
579             throw new IllegalStateException("Pas autorisé à charger le cache d'échantillons");
580         }
581 
582         if (isCruiseCacheLoaded() && !isCruiseCacheUpToDate()) {
583             closeCruiseCache();
584         }
585 
586         if (log.isInfoEnabled()) {
587             log.info("Loading cruise sampling cache: {cruiseId:" + getCruiseId() + ", protocolId: " + getProtocolId() + "}");
588         }
589 
590         cruiseCache = cruiseCacheLoader.loadCruiseCache();
591 
592         if (log.isInfoEnabled()) {
593             log.info("cruise sampling cache loaded: " + cruiseCache);
594         }
595 
596     }
597 
598     public List<Integer> getCruiseFishingOperationIds() {
599         checkOpened();
600         if (!isCruiseFilled()) {
601             throw new IllegalStateException("Aucune campagne chargée, impossible de récupérer les identifiants de traits");
602         }
603         return service.getAllFishingOperationIds(getCruiseId());
604     }
605 
606     public FishingOperation getFishingOperation() {
607         checkOpened();
608         if (fishingOperation == null) {
609             if (isFishingOperationFilled()) {
610                 Integer id = getFishingOperationId();
611                 if (log.isInfoEnabled()) {
612                     log.info("Loading fishingOperation: " + id);
613                 }
614                 fishingOperation = service.getFishingOperation(id);
615             }
616         }
617         return fishingOperation;
618     }
619 
620     public void reloadFishingOperation() {
621         checkOpened();
622         Preconditions.checkState(isFishingOperationFilled());
623         Integer id = getFishingOperationId();
624         if (log.isInfoEnabled()) {
625             log.info("Reloading fishingOperation: " + id);
626         }
627         resetFishingOperation();
628         firePropertyChange(PROPERTY_FISHING_OPERATION_ID, -1, fishingOperationId);
629     }
630 
631     public List<Caracteristic> getCaracteristics() {
632         checkOpened();
633         if (caracteristics == null) {
634             if (log.isInfoEnabled()) {
635                 log.info("Loading allCaracteristic");
636             }
637             caracteristics = service.getAllCaracteristic();
638         }
639         return caracteristics;
640     }
641 
642     public List<Caracteristic> getCaracteristicWithProtected() {
643         checkOpened();
644         if (caracteristicsWithProtected == null) {
645             if (log.isInfoEnabled()) {
646                 log.info("Loading allCaracteristicWithProtected");
647             }
648             caracteristicsWithProtected = service.getAllCaracteristicWithProtected();
649         }
650         return caracteristicsWithProtected;
651     }
652 
653     public List<Caracteristic> getLengthStepCaracteristics() {
654         checkOpened();
655         if (lengthStepCaracteristics == null) {
656 
657             if (log.isInfoEnabled()) {
658                 log.info("Loading lengthStepCaracteristics");
659             }
660             lengthStepCaracteristics = service.getLengthStepCaracteristics(getCaracteristics());
661         }
662         return lengthStepCaracteristics;
663     }
664 
665     public List<Caracteristic> getMaturityCaracteristics() {
666         checkOpened();
667         if (maturityCaracteristics == null) {
668 
669             if (log.isInfoEnabled()) {
670                 log.info("Loading maturityCaracteristics");
671             }
672             maturityCaracteristics = service.getMaturityCaracteristics(getCaracteristics());
673         }
674         return maturityCaracteristics;
675     }
676 
677     public SampleCategoryModelEntry getBestFirstSampleCategory(List<SampleCategoryModelEntry> categories,
678                                                                SpeciesProtocol speciesProtocol) {
679 
680         SampleCategoryModelEntry selectedCategory = null;
681 
682         if (speciesProtocol != null) {
683 
684             if (!speciesProtocol.isMandatorySampleCategoryIdEmpty()) {
685 
686                 // use the first category
687                 Integer categoryId = speciesProtocol.getMandatorySampleCategoryId().get(0);
688                 selectedCategory = getSampleCategoryModel().getCategoryById(categoryId);
689 
690                 if (categories.contains(selectedCategory)) {
691 
692                     // ok can use this category
693                     if (log.isInfoEnabled()) {
694                         log.info("Use first category from protocol: " + categoryId + " :: " + selectedCategory);
695                     }
696                 } else {
697 
698                     // can't use this category, not in universe
699                     selectedCategory = null;
700                 }
701             }
702         }
703 
704         if (selectedCategory == null) {
705 
706             // by default use the first one
707             if (!categories.isEmpty()) {
708                 selectedCategory = categories.get(0);
709 
710                 if (log.isInfoEnabled()) {
711                     log.info("Use default first category: " + selectedCategory);
712                 }
713             }
714         }
715         return selectedCategory;
716     }
717 
718     public List<CaracteristicQualitativeValue> getGenderValues() {
719         checkOpened();
720         if (genderValues == null) {
721             if (log.isInfoEnabled()) {
722                 log.info("Loading genderValues");
723             }
724             genderValues = service.getSexCaracteristic().getQualitativeValue();
725         }
726         return genderValues;
727     }
728 
729     public List<CaracteristicQualitativeValue> getDeadOrAliveValues() {
730         checkOpened();
731         if (deadOrAliveValues == null) {
732             if (log.isInfoEnabled()) {
733                 log.info("Loading deadOrAliveValues");
734             }
735             deadOrAliveValues = service.getDeadOrAliveCaracteristic().getQualitativeValue();
736         }
737         return deadOrAliveValues;
738     }
739 
740     public List<CaracteristicQualitativeValue> getCpsTypeValues() {
741         checkOpened();
742         if (cpsTypeValues == null) {
743             if (log.isInfoEnabled()) {
744                 log.info("Loading cpsTypeValues");
745             }
746             cpsTypeValues = service.getCalcifiedStructureCaracteristic().getQualitativeValue();
747         }
748         return cpsTypeValues;
749     }
750 
751 //    public List<Species> getReferentSpeciesWithSurveyCode() {
752 //        return getReferentSpeciesWithSurveyCode(false);
753 //    }
754 
755     public List<Species> getReferentSpeciesWithSurveyCode(boolean restrictToProtocol) {
756         checkOpened();
757         if (referentSpeciesWithSurveyCode == null) {
758 
759             if (log.isInfoEnabled()) {
760                 log.info("Loading referentSpecies");
761             }
762 
763             TaxonCache taxonCache = TaxonCaches.createSpeciesCacheWithoutVernacularCode(service, getProtocol());
764             referentSpeciesWithSurveyCode = new ArrayList<>(getReferentSpecies());
765             taxonCache.load(referentSpeciesWithSurveyCode);
766         }
767 
768         List<Species> result;
769         if (restrictToProtocol && isProtocolFilled()) {
770 
771             // On restreint uniquement aux espèces définies dans le protocole
772 
773             result = new ArrayList<>();
774             Map<Integer, SpeciesProtocol> speciesProtocolMap = TuttiProtocols.toSpeciesProtocolMap(getProtocol());
775             result.addAll(referentSpeciesWithSurveyCode
776                                   .stream()
777                                   .filter(aSpecies -> speciesProtocolMap.containsKey(aSpecies.getReferenceTaxonId()))
778                                   .collect(Collectors.toList()));
779 
780         } else {
781 
782             // On utilise la liste complete des espèces référentes
783             result = referentSpeciesWithSurveyCode;
784 
785         }
786         return result;
787 
788     }
789 
790     public List<Species> getReferentBenthosWithSurveyCode(boolean restrictToProtocol) {
791         checkOpened();
792         if (referentBenthosWithSurveyCode == null) {
793 
794             if (log.isInfoEnabled()) {
795                 log.info("Loading referentBenthos");
796             }
797             TaxonCache taxonCache = TaxonCaches.createBenthosCacheWithoutVernacularCode(service, getProtocol());
798             referentBenthosWithSurveyCode = new ArrayList<>(getReferentSpecies());
799             taxonCache.load(referentBenthosWithSurveyCode);
800         }
801 
802         List<Species> result;
803         if (restrictToProtocol && isProtocolFilled()) {
804 
805             // On restreint uniquement aux espèces définies dans le protocole
806 
807             result = new ArrayList<>();
808             Map<Integer, SpeciesProtocol> speciesProtocolMap = TuttiProtocols.toBenthosProtocolMap(getProtocol());
809             result.addAll(referentBenthosWithSurveyCode
810                                   .stream()
811                                   .filter(aSpecies -> speciesProtocolMap.containsKey(aSpecies.getReferenceTaxonId()))
812                                   .collect(Collectors.toList()));
813 
814         } else {
815 
816             // On utilise la liste complete des espèces référentes
817             result = referentBenthosWithSurveyCode;
818 
819         }
820         return result;
821     }
822 
823     public List<Species> getSpecies() {
824         if (species == null) {
825             if (log.isInfoEnabled()) {
826                 log.info("Loading allSpecies");
827             }
828             species = service.getAllSpecies();
829         }
830         return species;
831     }
832 
833     public List<Species> getReferentSpecies() {
834         if (referentSpecies == null) {
835             if (log.isInfoEnabled()) {
836                 log.info("Loading allReferentSpecies");
837             }
838             referentSpecies = service.getAllReferentSpecies();
839         }
840         return referentSpecies;
841     }
842 
843     public List<Person> getPersons() {
844         checkOpened();
845         if (persons == null) {
846             if (log.isInfoEnabled()) {
847                 log.info("Loading allPerson");
848             }
849             persons = service.getAllPerson();
850         }
851         return persons;
852     }
853 
854     public List<Vessel> getFishingVessels() {
855         checkOpened();
856         if (fishingVessels == null) {
857             if (log.isInfoEnabled()) {
858                 log.info("Loading allfishingVessel");
859             }
860             fishingVessels = service.getAllFishingVessel();
861         }
862         return fishingVessels;
863     }
864 
865     public List<Vessel> getScientificVessels() {
866         checkOpened();
867         if (scientificVessels == null) {
868             if (log.isInfoEnabled()) {
869                 log.info("Loading allScientificVessel");
870             }
871             scientificVessels = service.getAllScientificVessel();
872         }
873         return scientificVessels;
874     }
875 
876     public List<Gear> getFishingGears() {
877         checkOpened();
878         if (fishingGears == null) {
879             if (log.isInfoEnabled()) {
880                 log.info("Loading allFishingGear");
881             }
882             fishingGears = service.getAllFishingGear();
883         }
884         return fishingGears;
885     }
886 
887     public List<Gear> getScientificGears() {
888         checkOpened();
889         if (scientificGears == null) {
890             if (log.isInfoEnabled()) {
891                 log.info("Loading allScientificGear");
892             }
893             scientificGears = service.getAllScientificGear();
894         }
895         return scientificGears;
896     }
897 
898     public List<Caracteristic> getDefaultIndividualObservationCaracteristics() {
899         if (defaultIndividualObservationCaracteristics == null) {
900 
901             if (log.isInfoEnabled()) {
902                 log.info("Loading defaultIndividualObservationCaracteristics");
903             }
904             defaultIndividualObservationCaracteristics = service.getDefaultIndividualObservationCaracteristics();
905         }
906         return defaultIndividualObservationCaracteristics;
907     }
908 
909     private void resetProgram() {
910         program = null;
911         resetCruise();
912     }
913 
914     public void resetCruise() {
915         cruise = null;
916         resetFishingOperation();
917         closeCruiseCache();
918     }
919 
920     public void resetFishingOperation() {
921         fishingOperation = null;
922         validationContext.resetExistingFishingOperations();
923     }
924 
925     public void resetProtocol() {
926         if (service != null) {
927             service.setProtocol(null);
928         }
929         lengthStepCaracteristics = null;
930         maturityCaracteristics = null;
931         defaultIndividualObservationCaracteristics = null;
932         // survey code must be refresh
933         resetSpecies();
934         closeCruiseCache();
935     }
936 
937     public void resetGears() {
938         fishingGears = null;
939         scientificGears = null;
940     }
941 
942     public void resetVessels() {
943         fishingVessels = null;
944         scientificVessels = null;
945     }
946 
947     public void resetPersons() {
948         persons = null;
949     }
950 
951     public void resetSpecies() {
952         species = null;
953         referentSpecies = null;
954         referentSpeciesWithSurveyCode = null;
955         referentBenthosWithSurveyCode = null;
956     }
957 
958     public void resetCaracteristics() {
959         caracteristics = null;
960         caracteristicsWithProtected = null;
961         genderValues = null;
962         deadOrAliveValues = null;
963     }
964 
965     public void resetValidationDataContext() {
966         validationContext.reset();
967     }
968 
969     public PersistenceService getService() {
970         return service;
971     }
972 
973     public TuttiValidationDataContextSupport getValidationContext() {
974         return validationContext;
975     }
976 
977     public void setValidationContext(TuttiValidationDataContextSupport validationContext) {
978         Preconditions.checkNotNull(validationContext, "cant set a null validation context");
979         this.validationContext = validationContext;
980     }
981 
982     protected void checkOpened() {
983         Preconditions.checkState(service != null, "No persistence service assigned!");
984     }
985 
986     public void closeCruiseCache() {
987         if (!isCruiseCacheLoaded()) {
988             return;
989         }
990         if (log.isInfoEnabled()) {
991             log.info("Close cruise cache: " + cruiseCache);
992         }
993 
994         cruiseCache.close();
995         cruiseCache = null;
996     }
997 }