View Javadoc
1   package fr.ifremer.tutti.service.bigfin;
2   
3   /*
4    * #%L
5    * Tutti :: Service
6    * $Id:$
7    * $HeadURL:$
8    * %%
9    * Copyright (C) 2012 - 2015 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 com.google.common.base.Preconditions;
28  import com.google.common.collect.Multimap;
29  import com.google.common.collect.Multimaps;
30  import fr.ifremer.tutti.persistence.entities.data.BatchContainer;
31  import fr.ifremer.tutti.persistence.entities.data.CatchBatch;
32  import fr.ifremer.tutti.persistence.entities.data.FishingOperation;
33  import fr.ifremer.tutti.persistence.entities.data.SpeciesBatch;
34  import fr.ifremer.tutti.persistence.entities.data.SpeciesBatchs;
35  import fr.ifremer.tutti.persistence.entities.protocol.SpeciesProtocol;
36  import fr.ifremer.tutti.persistence.entities.referential.Caracteristic;
37  import fr.ifremer.tutti.persistence.entities.referential.CaracteristicQualitativeValue;
38  import fr.ifremer.tutti.persistence.entities.referential.Species;
39  import fr.ifremer.tutti.service.PersistenceService;
40  import fr.ifremer.tutti.service.bigfin.csv.BigfinDataRow;
41  import fr.ifremer.tutti.service.bigfin.csv.SpeciesOrSpeciesBatch;
42  import fr.ifremer.tutti.service.bigfin.signs.Sign;
43  import org.apache.commons.lang3.StringUtils;
44  import org.apache.commons.lang3.time.DateUtils;
45  import org.apache.commons.logging.Log;
46  import org.apache.commons.logging.LogFactory;
47  
48  import java.io.File;
49  import java.util.ArrayList;
50  import java.util.Date;
51  import java.util.HashMap;
52  import java.util.HashSet;
53  import java.util.List;
54  import java.util.Map;
55  import java.util.Set;
56  
57  import static org.nuiton.i18n.I18n.t;
58  
59  /**
60   * Created on 2/3/15.
61   *
62   * @author Tony Chemit - chemit@codelutin.com
63   * @since 3.13
64   */
65  public class BigfinImportContext {
66  
67      /** Logger. */
68      private static final Log log = LogFactory.getLog(BigfinImportContext.class);
69  
70      protected final FishingOperation operation;
71  
72      protected final CatchBatch catchBatch;
73  
74      protected final Map<Sign, CaracteristicQualitativeValue> signsToCaracteristicValue;
75  
76      protected final Map<String, Species> speciesBySurveyCode;
77  
78      protected final Map<String, SpeciesProtocol> speciesProtocolBySurveyCode;
79  
80      // set of not found species already added in the errors
81      protected final Set<Species> speciesNotRecognized = new HashSet<>();
82  
83      //set of species not in the protocol
84      protected final Set<Species> speciesNotInProtocol = new HashSet<>();
85  
86      // set of species without lengthstep already added in the errors
87      protected final Set<Species> speciesInProtocolButWithoutLengthStepPmfmId = new HashSet<>();
88  
89      private final List<BigfinDataRow> speciesRows = new ArrayList<>();
90  
91      private final List<BigfinDataRow> speciesBatchRows = new ArrayList<>();
92  
93      private final BigfinImportResult bigfinImportResult;
94  
95      private final BatchContainer<SpeciesBatch> rootSpeciesBatch;
96  
97      private final Map<Species, Caracteristic> lengthStepPmfmBySpecies;
98  
99      public BigfinImportContext(File importFile,
100                                FishingOperation operation,
101                                CatchBatch catchBatch,
102                                Map<Sign, CaracteristicQualitativeValue> signsToCaracteristicValue,
103                                Map<String, Species> speciesBySurveyCode,
104                                Map<String, SpeciesProtocol> speciesProtocolBySurveyCode,
105                                BatchContainer<SpeciesBatch> rootSpeciesBatch) {
106         this.rootSpeciesBatch = rootSpeciesBatch;
107         this.bigfinImportResult = new BigfinImportResult(importFile);
108         this.operation = operation;
109         this.catchBatch = catchBatch;
110         this.signsToCaracteristicValue = signsToCaracteristicValue;
111         this.speciesBySurveyCode = speciesBySurveyCode;
112         this.speciesProtocolBySurveyCode = speciesProtocolBySurveyCode;
113         this.lengthStepPmfmBySpecies = new HashMap<>();
114     }
115 
116     public Caracteristic getLengthStepPmfm(Species species, PersistenceService persistenceService) {
117         Caracteristic caracteristic = lengthStepPmfmBySpecies.get(species);
118         if (caracteristic == null) {
119 
120             SpeciesProtocol speciesProtocol = getSpeciesProtocol(species);
121             caracteristic = persistenceService.getCaracteristic(Integer.parseInt(speciesProtocol.getLengthStepPmfmId()));
122             lengthStepPmfmBySpecies.put(species, caracteristic);
123 
124         }
125         return caracteristic;
126     }
127 
128     public boolean isNoError() {
129         return bigfinImportResult.getErrors().isEmpty();
130     }
131 
132     public void addRowToProcess(BigfinDataRow bigfinDataRow) {
133 
134         if (bigfinDataRow.getSpeciesOrSpeciesBatch().isSpecies()) {
135             speciesRows.add(bigfinDataRow);
136         } else {
137             speciesBatchRows.add(bigfinDataRow);
138         }
139 
140     }
141 
142     public Map<Integer, SpeciesBatch> getSpeciesBatchesById() {
143         return SpeciesBatchs.getAllSpeciesBatchesById(this.rootSpeciesBatch);
144     }
145 
146     public Multimap<Species, SpeciesBatch> getRootSpeciesBatchBySpecies() {
147         return Multimaps.index(rootSpeciesBatch.getChildren(), SpeciesBatch::getSpecies);
148     }
149 
150     public Multimap<Species, BigfinDataRow> getSpeciesRowsBySpecies() {
151 
152         // separate the imported rows by species
153 
154         return Multimaps.index(speciesRows, bigfinDataRow -> {
155             return bigfinDataRow.getSpeciesOrSpeciesBatch().getSpecies();
156         });
157     }
158 
159     public Multimap<SpeciesBatch, BigfinDataRow> getSpeciesBatchRowsBySpeciesBatch() {
160 
161         return Multimaps.index(speciesBatchRows, input -> {
162             return input.getSpeciesOrSpeciesBatch().getBatch();
163         });
164 
165     }
166 
167     public boolean isStationFound(BigfinDataRow bean) {
168 
169         String station = bean.getStation();
170         Date date = bean.getDate();
171         return station != null
172                          && station.equals(operation.getStationNumber())
173                          && date != null
174                          && DateUtils.isSameDay(date, operation.getGearShootingStartDate());
175 
176     }
177 
178     public SpeciesProtocol getSpeciesProtocol(Species species) {
179 
180         String code = species.getSurveyCode();
181         if (StringUtils.isBlank(code)) {
182             code = species.getReferenceTaxonId().toString();
183         }
184         return speciesProtocolBySurveyCode.get(code);
185 
186     }
187 
188     public boolean checkRow(BigfinDataRow bigfinDataRow) {
189 
190         // check if the station is the one of the operation
191         // and do not check again a species that has not been recognized before
192         boolean stationFound = isStationFound(bigfinDataRow);
193 
194         boolean canBeAdd = false;
195 
196         if (stationFound) {
197 
198             String recordId = bigfinDataRow.getRecordId();
199 
200             SpeciesOrSpeciesBatch speciesOrspeciesBatch = bigfinDataRow.getSpeciesOrSpeciesBatch();
201 
202             if (speciesOrspeciesBatch.isSpecies()) {
203 
204                 // do some checks on the given species
205 
206                 checkSizeIsDefined(bigfinDataRow);
207 
208                 Species species = speciesOrspeciesBatch.getSpecies();
209 
210                 boolean speciesIsKnown = checkSpeciesIsKnown(recordId, species);
211 
212                 if (speciesIsKnown) {
213 
214                     boolean speciesProtocoleIsSafe = checkSpeciesProtocol(recordId, species);
215 
216                     if (speciesProtocoleIsSafe) {
217 
218                         canBeAdd = true;
219 
220                     }
221                 }
222 
223             } else {
224 
225                 // do some checks on the given species batch
226 
227                 SpeciesBatch speciesBatch = speciesOrspeciesBatch.getBatch();
228 
229                 // Check Species batch is a leaf
230                 boolean speciesBatchIsLeaf = checkSpeciesBatchIsLeaf(recordId, speciesBatch);
231 
232                 if (speciesBatchIsLeaf) {
233 
234                     // Check Species protocol is safe
235 
236                     boolean speciesProtocoleIsSafe = checkSpeciesProtocol(recordId, speciesBatch.getSpecies());
237 
238                     if (speciesProtocoleIsSafe) {
239 
240                         canBeAdd = true;
241 
242                     }
243 
244                 }
245 
246             }
247 
248         } else {
249             if (log.isInfoEnabled()) {
250                 log.info("Station is not matching for record: " + bigfinDataRow.getRecordId());
251             }
252         }
253 
254         return canBeAdd;
255     }
256 
257     public boolean checkSpeciesBatchIsLeaf(String recordId, SpeciesBatch batch) {
258 
259         boolean speciesBatchIsLeaf = batch.isChildBatchsEmpty();
260 
261         if (!speciesBatchIsLeaf) {
262 
263             String warning = t("tutti.service.bigfinImport.warning.speciesBatch.tooCategorized", recordId, batch.getId());
264             if (log.isWarnEnabled()) {
265                 log.warn(warning);
266             }
267             bigfinImportResult.addWarning(warning);
268         }
269 
270         return speciesBatchIsLeaf;
271 
272     }
273 
274     public void checkSizeIsDefined(BigfinDataRow bigfinDataRow) {
275 
276         Preconditions.checkArgument(bigfinDataRow.getSpeciesOrSpeciesBatch().isSpecies());
277 
278         if (bigfinDataRow.getSize() == null) {
279             String error = t("tutti.service.bigfinImport.error.szClass.unknwon", bigfinDataRow.getRecordId());
280             if (log.isErrorEnabled()) {
281                 log.error(error);
282             }
283             bigfinImportResult.addError(error);
284         }
285 
286     }
287 
288     public boolean checkSpeciesIsKnown(String recordId, Species species) {
289 
290         boolean speciesIsKnown = true;
291 
292         if (species.getId() == null) {
293 
294             // bloquer tout si un "species" ne match pas le référentiel de Tutti : lister dans ce cas les codes non reconnus
295             if (speciesNotRecognized.add(species)) {
296                 String error = t("tutti.service.bigfinImport.error.species.not.found", recordId, species.getExternalCode());
297                 if (log.isErrorEnabled()) {
298                     log.error(error);
299                 }
300                 bigfinImportResult.addError(error);
301             }
302 
303             speciesIsKnown = false;
304 
305         }
306 
307         return speciesIsKnown;
308 
309     }
310 
311     public boolean checkSpeciesProtocol(String recordId, Species species) {
312 
313         boolean speciesProtocoleIsSafe = true;
314 
315         String speciesLabel = getSpeciesLabel(species);
316 
317         SpeciesProtocol speciesProtocol = getSpeciesProtocol(species);
318 
319         // On n'importe pas les espèces non présentes dans le protocole et
320         // on liste les espèces/catégorisées non importées pour aider l'utilisateur
321         // à identifier le problème et on fait l'import des autres
322         if (speciesProtocol == null) {
323 
324             speciesProtocoleIsSafe = false;
325 
326             if (speciesNotInProtocol.add(species)) {
327 
328                 String error = t("tutti.service.bigfinImport.warning.species.notInProtocol",  recordId, speciesLabel);
329                 if (log.isWarnEnabled()) {
330                     log.warn(error);
331                 }
332                 bigfinImportResult.addWarning(error);
333             }
334 
335         } else {
336 
337             if (speciesProtocol.getLengthStepPmfmId() == null) {
338 
339                 speciesProtocoleIsSafe = false;
340 
341                 if (speciesInProtocolButWithoutLengthStepPmfmId.add(species)) {
342                     // bloquer toute espèce reconnue du protocole mais qui n'a pas de méthode de mesure
343                     String error = t("tutti.service.bigfinImport.error.species.without.lengthstep", recordId, speciesLabel);
344                     if (log.isErrorEnabled()) {
345                         log.error(error);
346                     }
347                     bigfinImportResult.addError(error);
348                 }
349             }
350         }
351 
352         return speciesProtocoleIsSafe;
353 
354     }
355 
356     public BigfinImportResult getResult() {
357         return bigfinImportResult;
358     }
359 
360     protected String getSpeciesLabel(Species species) {
361         String speciesLabel = species.getSurveyCode();
362         if (StringUtils.isBlank(speciesLabel)) {
363             speciesLabel = species.getRefTaxCode();
364         }
365         return speciesLabel;
366     }
367 
368     public Species getSpeciesWithSurveyCode(Species species) {
369         String refTaxCode = species.getRefTaxCode();
370         return speciesBySurveyCode.get(refTaxCode);
371     }
372 }