View Javadoc
1   package fr.ifremer.tutti.persistence.service.util;
2   
3   /*
4    * #%L
5    * Tutti :: Persistence
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.Joiner;
26  import com.google.common.base.Preconditions;
27  import com.google.common.collect.Lists;
28  import com.google.common.collect.Sets;
29  import fr.ifremer.adagio.core.dao.data.batch.Batch;
30  import fr.ifremer.adagio.core.dao.data.batch.CatchBatch;
31  import fr.ifremer.adagio.core.dao.data.batch.CatchBatchExtendDao;
32  import fr.ifremer.adagio.core.dao.data.batch.SortingBatch;
33  import fr.ifremer.adagio.core.dao.data.batch.SortingBatchDao;
34  import fr.ifremer.adagio.core.dao.data.batch.validator.CatchBatchValidationError;
35  import fr.ifremer.adagio.core.dao.data.batch.validator.CatchBatchValidationException;
36  import fr.ifremer.adagio.core.dao.data.operation.FishingOperation;
37  import fr.ifremer.adagio.core.dao.data.operation.FishingOperationDao;
38  import fr.ifremer.adagio.core.dao.referential.ObjectTypeCode;
39  import fr.ifremer.adagio.core.dao.referential.pmfm.PmfmId;
40  import fr.ifremer.tutti.persistence.InvalidBatchModelException;
41  import fr.ifremer.tutti.persistence.entities.TuttiEntity;
42  import fr.ifremer.tutti.persistence.entities.data.BatchContainer;
43  import fr.ifremer.tutti.persistence.entities.data.SampleCategoryModel;
44  import fr.ifremer.tutti.persistence.entities.data.SpeciesBatch;
45  import fr.ifremer.tutti.persistence.entities.referential.Species;
46  import fr.ifremer.tutti.persistence.service.AbstractPersistenceService;
47  import fr.ifremer.tutti.persistence.service.AccidentalBatchPersistenceService;
48  import fr.ifremer.tutti.persistence.service.AttachmentPersistenceService;
49  import fr.ifremer.tutti.persistence.service.IndividualObservationBatchPersistenceService;
50  import fr.ifremer.tutti.persistence.service.batch.TuttiCatchBatchValidator;
51  import org.apache.commons.collections4.CollectionUtils;
52  import org.springframework.dao.DataRetrievalFailureException;
53  import org.springframework.stereotype.Component;
54  
55  import javax.annotation.Resource;
56  import java.util.List;
57  import java.util.Set;
58  import java.util.stream.Collectors;
59  
60  import static org.nuiton.i18n.I18n.t;
61  
62  /**
63   * Helper around batches.
64   *
65   * @author Tony Chemit - chemit@codelutin.com
66   * @since 1.2
67   */
68  @Component("batchPersistenceHelper")
69  public class BatchPersistenceHelper extends AbstractPersistenceService {
70  
71  //    /** Logger. */
72  //    private static final Log log =
73  //            LogFactory.getLog(BatchPersistenceHelper.class);
74  
75  //    @Resource(name = "caracteristicPersistenceService")
76  //    private CaracteristicPersistenceService caracteristicService;
77  
78      @Resource(name = "attachmentPersistenceService")
79      protected AttachmentPersistenceService attachmentPersistenceService;
80  
81      @Resource(name = "individualObservationBatchPersistenceService")
82      protected IndividualObservationBatchPersistenceService individualObservationBatchPersistenceService;
83  
84      @Resource(name = "accidentalBatchPersistenceService")
85      protected AccidentalBatchPersistenceService accidentalBatchService;
86  
87      @Resource(name = "catchBatchDao")
88      protected CatchBatchExtendDao catchBatchDao;
89  
90      @Resource(name = "sortingBatchDao")
91      protected SortingBatchDao sortingBatchDao;
92  
93      @Resource(name = "fishingOperationDao")
94      protected FishingOperationDao fishingOperationDao;
95  
96      @Resource(name = "scientificCruiseCatchBatchValidator")
97      protected TuttiCatchBatchValidator catchBatchValidator;
98  
99      @Resource(name = "measurementPersistenceHelper")
100     protected MeasurementPersistenceHelper measurementPersistenceHelper;
101 
102 //    @Resource(name = "batchTreeHelper")
103 //    protected BatchTreeHelper batchTreeHelper;
104 
105     @Resource(name = "synchronizationStatusHelper")
106     protected SynchronizationStatusHelper synchronizationStatusHelper;
107 
108     @Override
109     public void init() {
110         super.init();
111         catchBatchDao.registerCatchBatchValidator(catchBatchValidator);
112     }
113 
114     @Override
115     public void close() {
116         catchBatchDao.unregisterCatchBatchValidator(catchBatchValidator);
117         super.close();
118     }
119 
120     public fr.ifremer.tutti.persistence.entities.data.CatchBatch createCatchBatch(fr.ifremer.tutti.persistence.entities.data.CatchBatch bean, CatchBatch catchBatch) {
121         catchBatch = catchBatchDao.create(catchBatch);
122         bean.setId(catchBatch.getId());
123         return bean;
124     }
125 
126     public void validateSpecies(SampleCategoryModel sampleCategoryModel,
127                                 BatchContainer<SpeciesBatch> species) throws InvalidBatchModelException {
128         List<CatchBatchValidationError> errors = catchBatchValidator.validateSpecies(sampleCategoryModel, species);
129         List<String> errorsStr = Lists.newArrayList();
130         errorsStr.addAll(errors.stream()
131                                .filter(error -> error.getGravity() == CatchBatchValidationError.GRAVITY_ERROR)
132                                .map(CatchBatchValidationError::getMessage)
133                                .collect(Collectors.toList()));
134         if (!errorsStr.isEmpty()) {
135             String join = Joiner.on("<br/>").join(errorsStr);
136             throw new InvalidBatchModelException(t("tutti.persistence.batch.validation.bad.sample.categories", join));
137         }
138     }
139 
140     public void validateBenthos(SampleCategoryModel sampleCategoryModel,
141                                 BatchContainer<SpeciesBatch> benthos) throws InvalidBatchModelException {
142         List<CatchBatchValidationError> errors = catchBatchValidator.validateBenthos(sampleCategoryModel, benthos);
143 
144         if (CollectionUtils.isNotEmpty(errors)) {
145             List<String> errorsStr = Lists.newArrayList();
146             errorsStr.addAll(errors.stream()
147                                    .filter(error -> error.getGravity() == CatchBatchValidationError.GRAVITY_ERROR)
148                                    .map(CatchBatchValidationError::getMessage)
149                                    .collect(Collectors.toList()));
150             if (!errorsStr.isEmpty()) {
151                 String join = Joiner.on("<br/>").join(errorsStr);
152                 throw new InvalidBatchModelException(t("tutti.persistence.batch.validation.bad.sample.categories", join));
153             }
154         }
155     }
156 
157     public void deleteCatchBatch(Integer fishingOperationId, Integer catchBatchId) {
158 
159         // delete accidental batchs
160         accidentalBatchService.deleteAccidentalBatchForFishingOperation(fishingOperationId);
161         getCurrentSession().flush();
162 
163         // delete all samples
164         individualObservationBatchPersistenceService.deleteAllIndividualObservationsForFishingOperation(fishingOperationId);
165         getCurrentSession().flush();
166 
167         // SynchronizationStatus on fishingTrip
168         FishingOperation fishingOperation = fishingOperationDao.load(fishingOperationId);
169         synchronizationStatusHelper.setDirty(fishingOperation.getFishingTrip());
170 
171         // get all catch batch children ids (to delete attachments)
172         Set<Integer> ids = getBatchIds(catchBatchId);
173         ids.remove(catchBatchId);
174 
175         catchBatchDao.remove(catchBatchId);
176         attachmentPersistenceService.deleteAllAttachment(ObjectTypeCode.CATCH_BATCH, catchBatchId);
177 
178         getCurrentSession().flush();
179 
180         attachmentPersistenceService.deleteAllAttachment(ObjectTypeCode.BATCH, ids);
181 
182     }
183 
184     public <D extends TuttiEntity> D createSortingBatch(D bean, CatchBatch catchBatch, SortingBatch batch) {
185         // Synchronization status
186         synchronizationStatusHelper.setDirty(catchBatch);
187         batch = catchBatchDao.createSortingBatch(batch, catchBatch);
188         bean.setId(batch.getId());
189         return bean;
190     }
191 
192     public Set<Integer> getBatchIds(Integer batchId) {
193         Set<Integer> ids = Sets.newHashSet(catchBatchDao.getAllChildrenIds(batchId));
194         ids.add(batchId);
195         return ids;
196     }
197 
198     public void removeWithChildren(Integer batchId) {
199 
200         individualObservationBatchPersistenceService.deleteAllIndividualObservationsForBatch(batchId);
201 
202         Set<Integer> ids = getBatchIds(batchId);
203 
204         catchBatchDao.removeWithChildren(batchId);
205 
206         attachmentPersistenceService.deleteAllAttachment(ObjectTypeCode.BATCH, ids);
207 
208     }
209 
210     public void removeWithChildren(Integer batchId, CatchBatch parentCatchBatch) {
211 
212         individualObservationBatchPersistenceService.deleteAllIndividualObservationsForBatch(batchId);
213 
214         Set<Integer> ids = getBatchIds(batchId);
215 
216         catchBatchDao.removeWithChildren(batchId, parentCatchBatch);
217 
218         attachmentPersistenceService.deleteAllAttachment(ObjectTypeCode.BATCH, ids);
219     }
220 
221     public void updateSortingBatch(List<SortingBatch> sortingBatchs, CatchBatch parentCatchBatch) {
222         catchBatchDao.updateSortingBatch(sortingBatchs, parentCatchBatch);
223     }
224 
225     public SortingBatch loadSortingBatch(Integer sortingBatchId, CatchBatch parentCatchBatch) {
226         return catchBatchDao.loadSortingBatch(sortingBatchId, parentCatchBatch);
227     }
228 
229     public void update(CatchBatch catchBatch) {
230         catchBatchDao.update(catchBatch);
231     }
232 
233     public SortingBatch getSortingBatchById(CatchBatch catchBatch, Integer sortingBatchId) {
234         return catchBatchDao.getSortingBatchById(catchBatch, sortingBatchId);
235     }
236 
237     public void updateSortingBatch(SortingBatch sortingBatch, CatchBatch parentCatchBatch) {
238         // Synchronization status
239         synchronizationStatusHelper.setDirty(parentCatchBatch);
240         catchBatchDao.updateSortingBatch(sortingBatch, parentCatchBatch);
241     }
242 
243 //    public List<SortingBatch> getFrequencyChilds(SortingBatch sortingBatch) {
244 //        List<SortingBatch> result = Lists.newArrayList();
245 //
246 //        SampleCategoryModel sampleCategoryModel = getSampleCategoryModel();
247 //
248 //        for (Batch batch : sortingBatch.getChildBatchs()) {
249 //            SortingBatch child = (SortingBatch) batch;
250 //            if (isFrequencyBatch(sampleCategoryModel, child)) {
251 //                result.add(child);
252 //            }
253 //        }
254 //        return result;
255 //    }
256 
257 //    public List<SortingBatch> getFrequencies(Integer batchId) {
258 //        Preconditions.checkNotNull(batchId);
259 //        CatchBatch catchBatch = getRootCatchBatchByBatchId(batchId);
260 //        SortingBatch sortingBatch = catchBatchDao.getSortingBatchById(
261 //                catchBatch, batchId);
262 //
263 //        return getFrequencyChilds(sortingBatch);
264 //    }
265 
266     public fr.ifremer.adagio.core.dao.data.batch.CatchBatch getRootCatchBatchByFishingOperationId(Integer fishingOperationId, boolean validate) {
267         Preconditions.checkNotNull(fishingOperationId);
268 
269         Integer catchBatchId = catchBatchDao.getIdByFishingOperationId(fishingOperationId);
270         Preconditions.checkNotNull(catchBatchId);
271 
272         // whenever want to repair anything from Tutti
273         fr.ifremer.adagio.core.dao.data.batch.CatchBatch result;
274 
275         if (validate) {
276 
277             try {
278                 result = catchBatchDao.loadFullTree(catchBatchId, PmfmId.WEIGHT_MEASURED.getValue(), true, false);
279             } catch (CatchBatchValidationException e) {
280                 throw new InvalidBatchModelException(
281                         "L'arbre d'échantillonage n'est pas compatible avec celui de Tutti.", e);
282             }
283         } else {
284             result = catchBatchDao.loadFullTree(catchBatchId, PmfmId.WEIGHT_MEASURED.getValue());
285         }
286         Preconditions.checkNotNull(result);
287         return result;
288     }
289 
290     public boolean isCatchBatchExistsForFishingOperation(Integer fishingOperationId) {
291         return catchBatchDao.isCatchBatchExistsForFishingOperation(fishingOperationId);
292     }
293 
294     public Integer getCatchBatchIdByFishingOperationId(Integer fishingOperationId) throws DataRetrievalFailureException {
295         return catchBatchDao.getIdByFishingOperationId(fishingOperationId);
296     }
297 
298     public fr.ifremer.adagio.core.dao.data.batch.CatchBatch getRootCatchBatchByBatchId(Integer batchId) {
299         Preconditions.checkNotNull(batchId);
300 
301         Integer catchBatchId = catchBatchDao.getIdBySortingBatchId(batchId);
302         Preconditions.checkNotNull(catchBatchId);
303 
304         // whenever want to repair anything from Tutti
305         fr.ifremer.adagio.core.dao.data.batch.CatchBatch result;
306 
307         result = catchBatchDao.loadFullTree(catchBatchId, PmfmId.WEIGHT_MEASURED.getValue());
308 
309         Preconditions.checkNotNull(result);
310         return result;
311     }
312 
313     public void setSortingBatchReferenceTaxon(Integer batchId, Species species) {
314         catchBatchDao.setSortingBatchReferenceTaxon(String.valueOf(batchId), species.getReferenceTaxonId());
315     }
316 
317 //    public void setSpeciesBatchParents(Integer sampleCategoryId,
318 //                                       Serializable sampleCategoryValue,
319 //                                       SortingBatch target,
320 //                                       Integer parentBatchId,
321 //                                       CatchBatch catchBatch) {
322 //
323 //        Preconditions.checkNotNull(target);
324 //        Preconditions.checkNotNull(catchBatch);
325 //
326 //        target.setRootBatch(catchBatch);
327 //
328 //        SortingBatch parentBatch;
329 //        if (parentBatchId != null) {
330 //
331 //            // Load existing parent and root
332 //            parentBatch = catchBatchDao.getSortingBatchById(catchBatch, parentBatchId);
333 //        } else {
334 //
335 //            // Or retrieve parent batch, from pmfm id
336 //            // Retrieve category type
337 //            if (!sampleCategoryId.equals(PmfmId.SORTED_UNSORTED.getValue())) {
338 //                throw new DataIntegrityViolationException(MessageFormat.format(
339 //                        "A species or benthos batch with no parent should have a sampleCategoryType {0} (PMFM.ID={1})",
340 //                        PmfmId.SORTED_UNSORTED.getValue(),
341 //                        sampleCategoryId));
342 //            }
343 //
344 //            Integer qualitativeValueId = convertSampleCategoryValueIntoQualitativeId(sampleCategoryValue);
345 //
346 //            if (QualitativeValueId.SORTED_VRAC.getValue().equals(qualitativeValueId)) {
347 //
348 //                // -- Vrac > Species > Alive itemized
349 //                parentBatch = batchTreeHelper.getSpeciesVracAliveItemizedRootBatch(catchBatch);
350 //
351 //                if (parentBatch == null) {
352 //
353 //                    // -- Vrac
354 //                    SortingBatch vracBatch = batchTreeHelper.getVracBatch(catchBatch);
355 //
356 //                    if (vracBatch == null) {
357 //                        vracBatch = batchTreeHelper.getOrCreateVracBatch(catchBatch, null, null);
358 //                    }
359 //
360 //                    // -- Vrac > Species
361 //                    SortingBatch vracSpeciesBatch = batchTreeHelper.getSpeciesVracRootBatch(vracBatch);
362 //
363 //                    if (vracSpeciesBatch == null) {
364 //                        vracSpeciesBatch = batchTreeHelper.getOrCreateSpeciesVracRootBatch(catchBatch, vracBatch, null);
365 //                    }
366 //
367 //                    // -- Vrac > Species > Alive itemized
368 //                    parentBatch = batchTreeHelper.getOrCreateSpeciesVracAliveItemizedRootBatch(catchBatch, vracSpeciesBatch);
369 //
370 //                }
371 //            } else if (QualitativeValueId.SORTED_HORS_VRAC.getValue().equals(qualitativeValueId)) {
372 //
373 //                // -- Hors Vrac > Species
374 //                parentBatch = batchTreeHelper.getSpeciesHorsVracRootBatch(catchBatch);
375 //
376 //                if (parentBatch == null) {
377 //
378 //                    // -- Hors Vrac
379 //                    SortingBatch horsVracBatch = batchTreeHelper.getOrCreateHorsVracBatch(catchBatch);
380 //
381 //                    // -- Hors Vrac > Species
382 //                    parentBatch = batchTreeHelper.getOrCreateSpeciesHorsVracRootBatch(catchBatch, horsVracBatch);
383 //                }
384 //            } else {
385 //
386 //                // not possible
387 //                throw new DataIntegrityViolationException("Should have Vrac / Hors Vrac qualitative value, but had: " + qualitativeValueId);
388 //            }
389 //
390 //        }
391 //
392 //        Preconditions.checkNotNull(parentBatch);
393 //        target.setParentBatch(parentBatch);
394 //    }
395 
396 //    public void setBenthosBatchParents(Integer sampleCategoryType,
397 //                                       Serializable sampleCategoryValue,
398 //                                       SortingBatch target,
399 //                                       Integer parentBatchId,
400 //                                       CatchBatch catchBatch) {
401 //
402 //        Preconditions.checkNotNull(target);
403 //        Preconditions.checkNotNull(catchBatch);
404 //
405 //        target.setRootBatch(catchBatch);
406 //
407 //        SortingBatch parentBatch;
408 //        if (parentBatchId != null) {
409 //
410 //            // Load existing parent and root
411 //            parentBatch = catchBatchDao.getSortingBatchById(catchBatch, parentBatchId);
412 //        } else {
413 //
414 //            // Or retrieve parent batch, from pmfm id
415 //            // Retrieve category type
416 //            if (!sampleCategoryType.equals(PmfmId.SORTED_UNSORTED.getValue())) {
417 //                throw new DataIntegrityViolationException(MessageFormat.format(
418 //                        "A species or benthos batch with no parent should have a sampleCategoryType {0} (PMFM.ID={1})",
419 //                        sampleCategoryType,
420 //                        PmfmId.SORTED_UNSORTED.getValue()));
421 //            }
422 //
423 //            Integer qualitativeValueId = convertSampleCategoryValueIntoQualitativeId(sampleCategoryValue);
424 //
425 //            if (QualitativeValueId.SORTED_VRAC.getValue().equals(qualitativeValueId)) {
426 //
427 //                // -- Vrac > Benthos > Alive Itemized
428 //                parentBatch = batchTreeHelper.getBenthosVracAliveItemizedRootBatch(catchBatch);
429 //
430 //                if (parentBatch == null) {
431 //
432 //                    // -- Vrac
433 //                    SortingBatch vracBatch = batchTreeHelper.getVracBatch(catchBatch);
434 //
435 //                    if (vracBatch == null) {
436 //                        vracBatch = batchTreeHelper.getOrCreateVracBatch(catchBatch, null, null);
437 //                    }
438 //
439 //                    // -- Vrac > Benthos
440 //                    SortingBatch vracBenthosBatch = batchTreeHelper.getBenthosVracRootBatch(vracBatch);
441 //
442 //                    if (vracBenthosBatch == null) {
443 //                        vracBenthosBatch = batchTreeHelper.getOrCreateBenthosVracRootBatch(catchBatch, vracBatch, null);
444 //                    }
445 //
446 //                    // -- Vrac > Benthos > Alive itemized
447 //                    parentBatch = batchTreeHelper.getOrCreateBenthosVracAliveItemizedRootBatch(catchBatch, vracBenthosBatch);
448 //
449 //                }
450 //            } else if (QualitativeValueId.SORTED_HORS_VRAC.getValue().equals(qualitativeValueId)) {
451 //
452 //                // -- Hors Vrac > Benthos
453 //                parentBatch = batchTreeHelper.getBenthosHorsVracRootBatch(catchBatch);
454 //
455 //                if (parentBatch == null) {
456 //
457 //                    // -- Hors Vrac
458 //                    SortingBatch horsVracBatch = batchTreeHelper.getOrCreateHorsVracBatch(catchBatch);
459 //
460 //                    // -- Hors Vrac > Benthos
461 //                    parentBatch = batchTreeHelper.getOrCreateBenthosHorsVracRootBatch(catchBatch, horsVracBatch);
462 //                }
463 //            } else {
464 //
465 //                // not possible
466 //                throw new DataIntegrityViolationException("Should have Vrac / Hors Vrac qualitative value, but had: " + qualitativeValueId);
467 //            }
468 //        }
469 //
470 //        Preconditions.checkNotNull(parentBatch);
471 //        target.setParentBatch(parentBatch);
472 //    }
473 
474 //    public void setMarineLitterBatchParents(SortingBatch target, CatchBatch catchBatch) {
475 //
476 //        Preconditions.checkNotNull(target);
477 //
478 //        // -- Hors Vrac > Marine Litter
479 //        SortingBatch parentBatch = batchTreeHelper.getMarineLitterRootBatch(catchBatch);
480 //
481 //        if (parentBatch == null) {
482 //
483 //            // -- Hors Vrac
484 //            SortingBatch horsVracBatch = batchTreeHelper.getOrCreateHorsVracBatch(catchBatch);
485 //
486 //            // -- Hors Vrac > Marine Litter
487 //            parentBatch = batchTreeHelper.getOrCreateMarineLitterRootBatch(catchBatch, horsVracBatch, null);
488 //        }
489 //
490 //        target.setParentBatch(parentBatch);
491 //        target.setRootBatch(catchBatch);
492 //    }
493 
494 //    public void beanToEntity(Integer parentBatchId,
495 //                             SpeciesBatch source,
496 //                             SortingBatch target,
497 //                             boolean computeRankOrder) {
498 //
499 //        // --- RankOrder (initialize once, at creation) --- //
500 //        {
501 //            if (target.getRankOrder() == null) {
502 //
503 //                short rankOrder;
504 //
505 //                if (computeRankOrder) {
506 //
507 //                    // Start rank order at 1
508 //                    rankOrder = (short) 1;
509 //                    //FIXME : tchemit-2015-04-04 This code can not be used to save multiple batches at the same time, since it will always give the
510 //                    //FIXME : tchemit-2015-04-04 same values for all batches
511 //                    if (source.getParentBatch() != null && CollectionUtils.isNotEmpty(source.getParentBatch().getChildBatchs())) {
512 //                        int maxRankOrder = 0;
513 //                        for (SpeciesBatch batch : source.getParentBatch().getChildBatchs()) {
514 //                            Integer r = batch.getRankOrder();
515 //                            if (r != null && r > maxRankOrder) {
516 //                                maxRankOrder = r;
517 //                            }
518 //                        }
519 //                        rankOrder += (short) maxRankOrder;
520 //
521 //                    } else {
522 //
523 //                        rankOrder = computeRankOrder(target);
524 //
525 //                    }
526 //
527 //                } else {
528 //
529 //                    Preconditions.checkState(source.getRankOrder() != null, "Not using computeRankOrder requires source rankOrder to be not null, but was on batch: " + source);
530 //                    rankOrder = (short) (int) source.getRankOrder();
531 //
532 //                }
533 //
534 //                target.setRankOrder(rankOrder);
535 //
536 //            }
537 //        }
538 //
539 //        // --- Force subgroup count to '1', as Allegro --- //
540 //        target.setSubgroupCount(1f);
541 //
542 //        // --- Individual count --- //
543 //        target.setIndividualCount(source.getNumber());
544 //
545 //        // --- Comments --- //
546 //        target.setComments(source.getComment());
547 //
548 //        // --- Exhaustive inventory (always true under a species batch) --- //
549 //        target.setExhaustiveInventory(true);
550 //
551 //        // --- Species --- //
552 //        {
553 //            ReferenceTaxon referenceTaxon;
554 //            if (source.getSpecies() == null || parentBatchId != null) {
555 //                referenceTaxon = null;
556 //            } else {
557 //                referenceTaxon = load(ReferenceTaxonImpl.class, source.getSpecies().getReferenceTaxonId());
558 //            }
559 //            target.setReferenceTaxon(referenceTaxon);
560 //        }
561 //
562 //        // --- QualityFlag --- //
563 //        {
564 //            String qualityFlag;
565 //            if (source.isSpeciesToConfirm()) {
566 //                qualityFlag = QualityFlagCode.DOUBTFUL.getValue();
567 //            } else {
568 //                qualityFlag = QualityFlagCode.NOTQUALIFIED.getValue();
569 //            }
570 //            target.setQualityFlag(load(QualityFlagImpl.class, qualityFlag));
571 //        }
572 //
573 //        Float weight = source.getWeight();
574 //        Float sampleCategoryWeight = source.getSampleCategoryWeight();
575 //
576 //        // --- Sampling Ratio + QuantificationMeasurement --- //
577 //        batchTreeHelper.setWeightAndSampleRatio(target, weight, sampleCategoryWeight);
578 //
579 //        // --- Sorting measurement --- //
580 //        {
581 //            Collection<SortingMeasurement> sortingMeasurements = target.getSortingMeasurements();
582 //            Set<SortingMeasurement> notChangedSortingMeasurements = Sets.newHashSet();
583 //            if (sortingMeasurements != null) {
584 //                notChangedSortingMeasurements.addAll(sortingMeasurements);
585 //            }
586 //
587 //            if (source.getSampleCategoryId() != null && source.getSampleCategoryValue() != null) {
588 //                Integer pmfmId = source.getSampleCategoryId();
589 //                // Do not store sorting measurement if pmfm = SORTED (already store in an ancestor batch)
590 //                if (!pmfmId.equals(PmfmId.SORTED_UNSORTED.getValue())) {
591 //                    SortingMeasurement sortingMeasurement = measurementPersistenceHelper.setSortingMeasurement(
592 //                            target,
593 //                            pmfmId,
594 //                            source.getSampleCategoryValue());
595 //                    notChangedSortingMeasurements.remove(sortingMeasurement);
596 //                }
597 //            }
598 //            if (sortingMeasurements != null) {
599 //                sortingMeasurements.removeAll(notChangedSortingMeasurements);
600 //            }
601 //        }
602 //
603 //    }
604 
605 //    public void beanToEntity(SpeciesBatchFrequency source,
606 //                             SortingBatch target,
607 //                             SortingBatch parentBatch,
608 //                             short rankOrder) {
609 //        Preconditions.checkNotNull(source.getBatch());
610 //        Preconditions.checkNotNull(source.getBatch().getId());
611 //
612 //        // If parent and root need to be set
613 //        if (target.getId() == null
614 //                || target.getRootBatch() == null
615 //                || (target.getParentBatch() != null && !target.getParentBatch().getId().equals(parentBatch.getId()))) {
616 //
617 //            target.setParentBatch(parentBatch);
618 //            target.setRootBatch(parentBatch.getRootBatch());
619 //        }
620 //
621 //        // --- RankOrder --- //
622 //        target.setRankOrder(rankOrder);
623 //
624 //        // --- Individual count --- //
625 //        target.setIndividualCount(source.getNumber());
626 //
627 //        // --- Species --- //
628 //        target.setReferenceTaxon(null);
629 //
630 //        // --- QualityFlag --- //
631 //        target.setQualityFlag(parentBatch.getQualityFlag());
632 //
633 //        // --- Exhaustive inventory (always true under a species batch) --- //
634 //        target.setExhaustiveInventory(true);
635 //
636 //        // --- Sampling Ratio + QuantificationMeasurement --- //
637 //        batchTreeHelper.setWeightAndSampleRatio(target, source.getWeight(), null);
638 //
639 //        // --- Sorting measurement --- //
640 //        {
641 //            Collection<SortingMeasurement> sortingMeasurements = target.getSortingMeasurements();
642 //            Set<SortingMeasurement> notChangedSortingMeasurements = Sets.newHashSet();
643 //            if (sortingMeasurements != null) {
644 //                notChangedSortingMeasurements.addAll(sortingMeasurements);
645 //            }
646 //            if ((source.getLengthStepCaracteristic() != null && source.getLengthStep() != null)) {
647 //                Integer pmfmId = source.getLengthStepCaracteristic().getIdAsInt();
648 //                SortingMeasurement sortingMeasurement = measurementPersistenceHelper.setSortingMeasurement(target, pmfmId,
649 //                                                                                                           source.getLengthStep());
650 //                notChangedSortingMeasurements.remove(sortingMeasurement);
651 //            }
652 //            if (sortingMeasurements != null) {
653 //                sortingMeasurements.removeAll(notChangedSortingMeasurements);
654 //            }
655 //        }
656 //
657 //    }
658 
659 //    public SpeciesBatch entityToBean(SampleCategoryModel sampleCategoryModel,
660 //                                     SortingBatch source,
661 //                                     SpeciesBatch target) {
662 //
663 //        Preconditions.checkNotNull(target.getSpecies());
664 //
665 //        target.setId(source.getId().toString());
666 //
667 //        // Rank order
668 //        target.setRankOrder(Integer.valueOf(source.getRankOrder()));
669 //
670 //        // Individual count
671 //        target.setNumber(source.getIndividualCount());
672 //
673 //        // Convert database weight (and sampling ratio) into UI weight and sampleCategoryWeight
674 //        if (source.getWeight() != null && source.getWeightBeforeSampling() == null) {
675 //            target.setSampleCategoryWeight(source.getWeight());
676 //        } else {
677 //            target.setWeight(source.getWeight());
678 //            target.setSampleCategoryWeight(source.getWeightBeforeSampling());
679 //
680 ////            if (Objects.equals(source.getWeight(), source.getWeightBeforeSampling())) {
681 ////
682 ////                // after a allegro synchronize, can happen, we do not use quantification measurement on a not leaf node
683 ////                // the weight comes from sampleRatioText, but in facts there only one weight...
684 ////                target.setWeight(null);
685 ////
686 ////            }
687 //        }
688 //
689 ////        if (CollectionUtils.isNotEmpty(source.getChildBatchs()) && target.getWeight() != null) {
690 ////
691 ////            // can't use this sample weight on a node
692 ////            // the weight comes from sampleRatioText, but must NOT be used here
693 ////            target.setWeight(null);
694 ////
695 ////        }
696 //
697 //
698 //        // Comments
699 //        target.setComment(source.getComments());
700 //
701 //        // Sample category type (only one is applied)
702 //        SortingMeasurement sm = null;
703 //        if (source.getSortingMeasurements().size() == 1) {
704 //            sm = source.getSortingMeasurements().iterator().next();
705 //        } else if (source.getReferenceTaxon() != null && source.getReferenceTaxon().getId() != null) {
706 //            sm = measurementPersistenceHelper.getInheritedSortingMeasurement(source);
707 //        }
708 //        if (sm != null) {
709 //
710 //            boolean isFrequency = isFrequencyBatch(sampleCategoryModel, source);
711 //
712 //            if (!isFrequency) {
713 //                Integer qualitativeId = null;
714 //                if (sm.getQualitativeValue() != null) {
715 //                    qualitativeId = sm.getQualitativeValue().getId();
716 //                }
717 //                setSampleCategoryQualitative(
718 //                        target,
719 //                        sm.getPmfm().getId(),
720 //                        sm.getNumericalValue(),
721 //                        sm.getAlphanumericalValue(),
722 //                        qualitativeId);
723 //            }
724 //        }
725 //
726 //        if (target.getSampleCategoryId() != null) {
727 //            List<SpeciesBatch> targetChilds = Lists.newArrayList();
728 //            for (Batch batch : source.getChildBatchs()) {
729 //                SortingBatch sourceChild = (SortingBatch) batch;
730 //                SpeciesBatch targetChild = SpeciesBatchs.newInstance(target);
731 //                targetChild.setSpecies(target.getSpecies());
732 //                entityToBean(sampleCategoryModel, sourceChild, targetChild);
733 //                if (log.isDebugEnabled()) {
734 //                    log.debug("Loaded CatchBatch (Vrac|Hors Vrac) > Species > " + targetChild.getSpecies().getReferenceTaxonId() + " : " + target.getId());
735 //                }
736 //                if (targetChild.getSampleCategoryValue() != null) {
737 //                    targetChilds.add(targetChild);
738 //                    targetChild.setParentBatch(target);
739 //                }
740 //            }
741 //            target.setChildBatchs(targetChilds);
742 //
743 //        }
744 //
745 //        //FIXME tchemit-2014-08-29 We can only do this if not an a leaf node (means with no frequencies...)
746 //        //FIXME tchemit-2014-08-29 But need to see if this is really need to do that .
747 //        // see https://forge.codelutin.com/issues/5698
748 //
749 //        if (CollectionUtils.isNotEmpty(source.getChildBatchs()) && target.getWeight() != null) {
750 //
751 //            SortingBatch childBatch = (SortingBatch) Iterables.get(source.getChildBatchs(), 0);
752 //
753 //            boolean isFrequency = isFrequencyBatch(sampleCategoryModel, childBatch);
754 //
755 //            if (!isFrequency) {
756 //
757 //                // can't use this sample weight on a node
758 //                // the weight comes from sampleRatioText, but must NOT be used here
759 //                // but we can only do this if childs are not frequencies
760 //
761 //                target.setWeight(null);
762 //
763 //            }
764 //
765 //        }
766 //
767 //        QualityFlag qualityFlag = source.getQualityFlag();
768 //        target.setSpeciesToConfirm(qualityFlag != null && QualityFlagCode.DOUBTFUL.getValue().equals(qualityFlag.getCode()));
769 //
770 //        return target;
771 //
772 //    }
773 
774     public short computeRankOrder(SortingBatch target) {
775 
776         // Start rank order at 1, nothing before it
777         short rankOrder = (short) 1;
778         if (target.getParentBatch() != null && target.getParentBatch().getChildBatchs() != null) {
779             int maxRankOrder = 0;
780             for (Batch batch : target.getParentBatch().getChildBatchs()) {
781                 Short r = batch.getRankOrder();
782                 if (r != null && r > maxRankOrder) {
783                     maxRankOrder = r;
784                 }
785             }
786             rankOrder += maxRankOrder;
787         }
788         return rankOrder;
789 
790     }
791 
792 //    public Integer convertSampleCategoryValueIntoQualitativeId(Serializable value) {
793 //        if (value == null) {
794 //            return null;
795 //        }
796 //        Integer qualitativeValueId = null;
797 //        if (value instanceof CaracteristicQualitativeValue) {
798 //            CaracteristicQualitativeValue cqValue = (CaracteristicQualitativeValue) value;
799 //            qualitativeValueId = cqValue.getIdAsInt();
800 //        } else if (value instanceof String) {
801 //            qualitativeValueId = Integer.valueOf((String) value);
802 //        }
803 //        return qualitativeValueId;
804 //    }
805 
806     public void deleteBatch(Integer batchId) {
807         Preconditions.checkNotNull(batchId);
808 
809         CatchBatch catchBatch = getRootCatchBatchByBatchId(batchId);
810         synchronizationStatusHelper.setDirty(catchBatch);
811 
812         removeWithChildren(batchId);
813     }
814 
815 //    public void deleteSpeciesSubBatch(Integer speciesBatchId) {
816 //        Preconditions.checkNotNull(speciesBatchId);
817 //
818 //        CatchBatch catchBatch = getRootCatchBatchByBatchId(speciesBatchId);
819 //        synchronizationStatusHelper.setDirty(catchBatch);
820 //
821 //        SortingBatch sortingBatch = getSortingBatchById(catchBatch, speciesBatchId);
822 //
823 //        // get his children
824 //        Collection<Batch> childBatchs = sortingBatch.getChildBatchs();
825 //
826 //        if (CollectionUtils.isNotEmpty(childBatchs)) {
827 //
828 //            for (Batch childBatch : childBatchs) {
829 //
830 //                // delete this child and all his children
831 //                Integer childBatchId = childBatch.getId();
832 //
833 //                if (log.isDebugEnabled()) {
834 //                    log.debug("Delete child [" + childBatchId + "] of species batch: " + speciesBatchId);
835 //                }
836 //                removeWithChildren(childBatchId);
837 //            }
838 //        }
839 //    }
840 
841 //    public void changeBatchSpecies(Integer batchId, Species species) {
842 //
843 //        Preconditions.checkNotNull(batchId);
844 //        Preconditions.checkNotNull(species);
845 //        Preconditions.checkNotNull(species.getReferenceTaxonId());
846 //
847 //        CatchBatch catchBatch = getRootCatchBatchByBatchId(batchId);
848 //        synchronizationStatusHelper.setDirty(catchBatch);
849 //
850 //        catchBatchDao.setSortingBatchReferenceTaxon(String.valueOf(batchId), species.getReferenceTaxonId());
851 //    }
852 
853 //    public void setSampleCategoryQualitative(SpeciesBatch target,
854 //                                             Integer pmfmId,
855 //                                             Float numericalvalue,
856 //                                             String alphanumericalValue,
857 //                                             Integer qualitativeValueId) {
858 //        // skip if null or corresponding to the SORTING_TYPE PMFM (Espèce, Benthos, Plancton, etc.)
859 //        if (pmfmId == null || pmfmId.equals(BatchTreeHelper.SORTING_TYPE_ID)) {
860 //            return;
861 //        }
862 //        SampleCategoryModel sampleCategoryModel = getSampleCategoryModel();
863 //
864 //        boolean isSamplingCategory = sampleCategoryModel.containsCategoryId(pmfmId);
865 //        Preconditions.checkNotNull(isSamplingCategory, "Unable to find corresponding SampleCategoryEnum for PMFM.ID : " + pmfmId);
866 //
867 //        target.setSampleCategoryId(pmfmId);
868 //        Serializable categoryValue = getSampleCategoryQualitative(
869 //                pmfmId,
870 //                numericalvalue,
871 //                alphanumericalValue,
872 //                qualitativeValueId);
873 //        target.setSampleCategoryValue(categoryValue);
874 //    }
875 
876 //    public void entityToBatchFrequency(SortingBatch source,
877 //                                       SpeciesBatchFrequency target) {
878 //
879 //        target.setId(source.getId());
880 //
881 //        // Rank order
882 //        target.setRankOrder(Integer.valueOf(source.getRankOrder()));
883 //
884 //        target.setNumber(source.getIndividualCount());
885 //        target.setWeight(source.getWeight());
886 //
887 //        Preconditions.checkState(source.getSortingMeasurements().size() == 1, "SortingBatch [" + source.getId() + "] need exactly one sortingMeasurement (to store the length step category), but had " + source.getSortingMeasurements().size());
888 //        SortingMeasurement sm = source.getSortingMeasurements().iterator().next();
889 //        Preconditions.checkNotNull(sm.getPmfm(), "SortingMeasurement [" + sm.getId() + "] can not have a null pmfm");
890 //        Preconditions.checkNotNull(sm.getPmfm().getId(), "SortingMeasurement [" + sm.getId() + "] can not have a pmfm with null id");
891 //
892 //        // Length step category
893 //        Caracteristic lengthStepCaracteristic = caracteristicService.getCaracteristic(sm.getPmfm().getId());
894 //        target.setLengthStepCaracteristic(lengthStepCaracteristic);
895 //
896 //        // Length
897 //        target.setLengthStep(sm.getNumericalValue());
898 //    }
899 
900 //    public Serializable getSampleCategoryQualitative(Integer pmfmId,
901 //                                                     Float numericalvalue,
902 //                                                     String alphanumericalValue,
903 //                                                     Integer qualitativeValueId) {
904 //
905 //        if (numericalvalue != null) {
906 //            return numericalvalue;
907 //        }
908 //        if (alphanumericalValue != null) {
909 //            return alphanumericalValue;
910 //        }
911 //
912 //        Caracteristic caracteristic = caracteristicService.getCaracteristic(pmfmId);
913 //        if (caracteristic == null || caracteristic.getCaracteristicType() != CaracteristicType.QUALITATIVE) {
914 //            return null;
915 //        }
916 //        CaracteristicQualitativeValue value = null;
917 //        for (CaracteristicQualitativeValue qv : caracteristic.getQualitativeValue()) {
918 //            if (qualitativeValueId.equals(qv.getIdAsInt())) {
919 //                value = qv;
920 //                break;
921 //            }
922 //        }
923 //
924 //        return value;
925 //    }
926 
927 //    /**
928 //     * Check if the given {@code sortingBatch} is a frequency one.
929 //     *
930 //     * We test that:
931 //     * <ul>
932 //     * <li>batch has exactly one measurement</li>
933 //     * <li>the measurement pmfm is not a sample category</li>
934 //     * </ul>
935 //     *
936 //     * @param sampleCategoryModel model of authorized sample categories
937 //     * @param sortingBatch        batch to check
938 //     * @return {@code true} if given batch is a frequency batch,
939 //     * {@code false} otherwise.
940 //     */
941 //    public boolean isFrequencyBatch(SampleCategoryModel sampleCategoryModel,
942 //                                    SortingBatch sortingBatch) {
943 //        boolean result = false;
944 //        if (sortingBatch.getSortingMeasurements().size() == 1) {
945 //            SortingMeasurement sm
946 //                    = sortingBatch.getSortingMeasurements().iterator().next();
947 //            Pmfm pmfm = sm.getPmfm();
948 //
949 //            result = sortingBatch.getIndividualCount() != null &&
950 //                    !sampleCategoryModel.containsCategoryId(pmfm.getId());
951 //        }
952 //        return result;
953 //    }
954 
955 }