View Javadoc
1   package fr.ifremer.tutti.ui.swing.content.operation.catches.species.frequency;
2   
3   /*
4    * #%L
5    * Tutti :: UI
6    * $Id:$
7    * $HeadURL:$
8    * %%
9    * Copyright (C) 2012 - 2016 Ifremer
10   * %%
11   * This program is free software: you can redistribute it and/or modify
12   * it under the terms of the GNU General Public License as
13   * published by the Free Software Foundation, either version 3 of the
14   * License, or (at your option) any later version.
15   * 
16   * This program is distributed in the hope that it will be useful,
17   * but WITHOUT ANY WARRANTY; without even the implied warranty of
18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   * GNU General Public License for more details.
20   * 
21   * You should have received a copy of the GNU General Public
22   * License along with this program.  If not, see
23   * <http://www.gnu.org/licenses/gpl-3.0.html>.
24   * #L%
25   */
26  
27  import fr.ifremer.tutti.persistence.entities.referential.Species;
28  import fr.ifremer.tutti.service.sampling.IndividualObservationSamplingCacheRequest;
29  import fr.ifremer.tutti.service.sampling.SamplingCodeCache;
30  import fr.ifremer.tutti.service.sampling.SamplingCodePrefix;
31  import org.apache.commons.logging.Log;
32  import org.apache.commons.logging.LogFactory;
33  
34  import java.io.Closeable;
35  import java.util.Collection;
36  import java.util.List;
37  import java.util.Objects;
38  import java.util.Set;
39  import java.util.TreeSet;
40  
41  import static fr.ifremer.tutti.persistence.service.TuttiPersistenceServiceLocator.getPersistenceService;
42  
43  /**
44   * Pour gérer le cache des codes de prélèvements.
45   *
46   * Created on 23/04/16.
47   *
48   * @author Tony Chemit - chemit@codelutin.com
49   * @since 4.5
50   */
51  public class SamplingCodeUICache implements Closeable {
52  
53      /** Logger. */
54      private static final Log log = LogFactory.getLog(SamplingCodeUICache.class);
55  
56      private final SpeciesFrequencyUIModel uiModel;
57  
58      private final Integer cruiseId;
59  
60      private final SamplingCodeCache samplingCodeCache;
61  
62      /**
63       * Contient les codes de prélèvements qu'on sait non utilisables.
64       *
65       * Au chargement de l'écran, on remplit cet ensemble avec les codes des observations individuelles du lot.
66       */
67      private final Set<Integer> samplingCodesNotAvailable = new TreeSet<>();
68      /**
69       * Contient les codes de prélèvements qu'on sait utilisables.
70       *
71       * Dès qu'un code de prélèvement est ajouté ou modifié dans l'écran, on l'ajoute ici.
72       */
73      private final Set<Integer> samplingCodesAvailable = new TreeSet<>();
74  
75      /**
76       * La code référent du taxon du lot en cours d'édition.
77       */
78      private Integer speciesReferenceTaxonId;
79  
80      public SamplingCodeUICache(SamplingCodeCache samplingCodeCache, SpeciesFrequencyUIModel uiModel, Integer cruiseId) {
81          this.samplingCodeCache = samplingCodeCache;
82          this.uiModel = uiModel;
83          this.cruiseId = cruiseId;
84      }
85  
86      public void init(Species species, List<IndividualObservationBatchRowModel> individualObservations, boolean addToCache) {
87  
88          Objects.requireNonNull(species);
89          Objects.requireNonNull(individualObservations);
90  
91          this.speciesReferenceTaxonId = species.getReferenceTaxonId();
92  
93          this.samplingCodesAvailable.clear();
94          this.samplingCodesNotAvailable.clear();
95  
96          if (addToCache) {
97  
98              addIndividualObservations(individualObservations);
99  
100         } else {
101 
102             individualObservations.stream()
103                                   .filter(individualObservationRow -> individualObservationRow.getSamplingCode() != null)
104                                   .forEach(individualObservationRow -> addSamplingCodeNotAvailable(individualObservationRow.getSamplingCode()));
105 
106         }
107     }
108 
109     @Override
110     public void close() {
111         this.samplingCodesNotAvailable.clear();
112         this.samplingCodesAvailable.clear();
113         this.speciesReferenceTaxonId = null;
114     }
115 
116     public void addIndividualObservations(Collection<IndividualObservationBatchRowModel> individualObservations) {
117 
118         Objects.requireNonNull(individualObservations);
119 
120         individualObservations.stream()
121                               .filter(IndividualObservationBatchRowModel::withSamplingCode)
122                               .forEach(row -> {
123 
124                                   IndividualObservationSamplingCacheRequest samplingCacheRequest = uiModel.toSamplingCacheRequest(row);
125                                   addSampling(samplingCacheRequest);
126 
127                               });
128 
129     }
130 
131     public void removeIndividualObservations(Collection<IndividualObservationBatchRowModel> individualObservations) {
132 
133         Objects.requireNonNull(individualObservations);
134 
135         individualObservations.stream()
136                               .filter(IndividualObservationBatchRowModel::withSamplingCode)
137                               .forEach(row -> {
138 
139                                   IndividualObservationSamplingCacheRequest samplingCacheRequest = uiModel.toSamplingCacheRequest(row);
140                                   removeSampling(samplingCacheRequest);
141 
142                               });
143 
144     }
145 
146     public boolean canUseSamplingCode(Integer sampleCode) {
147 
148         if (isSamplingCodeNotAvailable(sampleCode)) {
149 
150             // le code n'est pas disponible (on le sait depuis le cache de l'écran)
151             if (log.isDebugEnabled()) {
152                 log.debug("Sampling code " + sampleCode + " is known as not available from cache. Can't use it.");
153             }
154             return false;
155         }
156 
157         if (isSamplingCodeAvailable(sampleCode)) {
158 
159             // le code est pas disponible (on le sait depuis le cache de l'écran)
160             if (log.isDebugEnabled()) {
161                 log.debug("Sampling code " + sampleCode + " is known as available from cache. Can use it.");
162             }
163             return true;
164         }
165 
166         // on demande en base si le code est disponible
167 
168         String samplingCodeSuffix = uiModel.getIndividualObservationModel().getSamplingCodePrefix().toSpeciesOnlySamplingCode(sampleCode);
169         boolean samplingCodeAvailable = getPersistenceService().isSamplingCodeAvailable(cruiseId,
170                                                                                         speciesReferenceTaxonId,
171                                                                                         samplingCodeSuffix);
172 
173         if (log.isDebugEnabled()) {
174             if (samplingCodeAvailable) {
175                 log.debug("Sampling code " + sampleCode + " is known as available from database. Can use it.");
176             } else {
177                 log.debug("Sampling code " + sampleCode + " is known as not available from database. Can't use it.");
178             }
179         }
180 
181         return samplingCodeAvailable;
182 
183     }
184 
185     public int getNextSamplingCodeId() {
186 
187         int nextSamplingCodeId = samplingCodeCache.getNextSamplingCodeId(speciesReferenceTaxonId);
188 
189         if (log.isInfoEnabled()) {
190             log.info("Generated sampling code: " + nextSamplingCodeId);
191         }
192         return nextSamplingCodeId;
193 
194     }
195 
196     public void addSampling(IndividualObservationSamplingCacheRequest samplingCacheRequest) {
197 
198         Objects.requireNonNull(samplingCacheRequest);
199 
200         String samplingCode = samplingCacheRequest.getSamplingCode();
201         Objects.requireNonNull(samplingCode);
202 
203         samplingCodeCache.addSamplingCode(speciesReferenceTaxonId, samplingCode);
204 
205         // Le code n'est plus utilisable
206         addSamplingCodeNotAvailable(samplingCode);
207 
208     }
209 
210     public void removeSampling(IndividualObservationSamplingCacheRequest samplingCacheRequest) {
211 
212         Objects.requireNonNull(samplingCacheRequest);
213 
214         String samplingCode = samplingCacheRequest.getSamplingCode();
215         Objects.requireNonNull(samplingCode);
216 
217         samplingCodeCache.removeSamplingCode(speciesReferenceTaxonId, samplingCode);
218 
219         // Le code est réutilisable
220         addSamplingCodeAvailable(samplingCode);
221 
222     }
223 
224     private boolean isSamplingCodeNotAvailable(int samplingCode) {
225         return samplingCodesNotAvailable.contains(samplingCode);
226     }
227 
228     private boolean isSamplingCodeAvailable(int samplingCode) {
229         return samplingCodesAvailable.contains(samplingCode);
230     }
231 
232     private void addSamplingCodeAvailable(String samplingCode) {
233 
234         int samplingCodeNumber = SamplingCodePrefix.extractSamplingCodeIdFromSamplingCode(samplingCode);
235         if (log.isDebugEnabled()) {
236             log.debug(String.format("Make samplingCode: %s (%d) available", samplingCode, samplingCodeNumber));
237         }
238         samplingCodesNotAvailable.remove(samplingCodeNumber);
239         samplingCodesAvailable.add(samplingCodeNumber);
240 
241     }
242 
243     private void addSamplingCodeNotAvailable(String samplingCode) {
244 
245         int samplingCodeNumber = SamplingCodePrefix.extractSamplingCodeIdFromSamplingCode(samplingCode);
246         if (log.isDebugEnabled()) {
247             log.debug(String.format("Make samplingCode: %s (%d) not available", samplingCode, samplingCodeNumber));
248         }
249         samplingCodesNotAvailable.add(samplingCodeNumber);
250         samplingCodesAvailable.remove(samplingCodeNumber);
251 
252     }
253 
254 }