001// license-header java merge-point
002//
003// Attention: Generated code! Do not modify by hand!
004// Generated by: SpringHibernateDaoImpl.vsl in andromda-spring-cartridge.
005//
006package fr.ifremer.adagio.core.dao.data.batch;
007
008/*
009 * #%L
010 * SIH-Adagio Core for Allegro
011 * $Id: CatchBatchDaoImpl.java 12089 2014-05-20 19:37:05Z bl05b3e $
012 * $HeadURL: https://forge.ifremer.fr/svn/sih-adagio/tags/adagio-3.5.6/core/src/main/java/fr/ifremer/adagio/core/dao/data/batch/CatchBatchDaoImpl.java $
013 * %%
014 * Copyright (C) 2012 - 2013 Ifremer
015 * %%
016 * This program is free software: you can redistribute it and/or modify
017 * it under the terms of the GNU Affero General Public License as published by
018 * the Free Software Foundation, either version 3 of the License, or
019 * (at your option) any later version.
020 * 
021 * This program is distributed in the hope that it will be useful,
022 * but WITHOUT ANY WARRANTY; without even the implied warranty of
023 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
024 * GNU General Public License for more details.
025 * 
026 * You should have received a copy of the GNU Affero General Public License
027 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
028 * #L%
029 */
030
031import java.util.Arrays;
032import java.util.Collection;
033import java.util.Comparator;
034import java.util.HashMap;
035import java.util.HashSet;
036import java.util.Iterator;
037import java.util.List;
038import java.util.Map;
039import java.util.TreeSet;
040
041import javax.annotation.Resource;
042
043import org.hibernate.Session;
044import org.hibernate.type.IntegerType;
045import org.springframework.dao.DataRetrievalFailureException;
046
047import com.google.common.base.Preconditions;
048import com.google.common.collect.Lists;
049import com.google.common.collect.Sets;
050
051import fr.ifremer.adagio.core.config.AdagioConfiguration;
052import fr.ifremer.adagio.core.dao.administration.user.DepartmentImpl;
053import fr.ifremer.adagio.core.dao.data.batch.validator.CatchBatchQuickFix;
054import fr.ifremer.adagio.core.dao.data.batch.validator.CatchBatchValidationError;
055import fr.ifremer.adagio.core.dao.data.batch.validator.CatchBatchValidationException;
056import fr.ifremer.adagio.core.dao.data.batch.validator.CatchBatchValidator;
057import fr.ifremer.adagio.core.dao.data.measure.QuantificationMeasurement;
058import fr.ifremer.adagio.core.dao.data.measure.SortingMeasurement;
059import fr.ifremer.adagio.core.dao.referential.QualityFlagCode;
060import fr.ifremer.adagio.core.dao.referential.QualityFlagImpl;
061import fr.ifremer.adagio.core.dao.referential.pmfm.PmfmImpl;
062
063/**
064 * @see fr.ifremer.adagio.core.dao.data.batch.CatchBatch
065 */
066@org.springframework.stereotype.Repository("catchBatchDao")
067@org.springframework.context.annotation.Lazy
068public class CatchBatchDaoImpl
069        extends fr.ifremer.adagio.core.dao.data.batch.CatchBatchDaoBase
070        implements CatchBatchExtendDao {
071
072    protected List<CatchBatchValidator> validators = Lists.newArrayList();
073
074    @Resource(name = "sortingBatchDao")
075    protected SortingBatchDao sortingBatchDao;
076
077    @Resource(name = "catchBatchDao")
078    protected CatchBatchExtendDao catchBatchDao;
079
080    /**
081     * Constructor used by Spring
082     */
083    @org.springframework.beans.factory.annotation.Autowired
084    public CatchBatchDaoImpl(org.hibernate.SessionFactory sessionFactory) {
085        super();
086        setSessionFactory(sessionFactory);
087    }
088
089    @Override
090    public CatchBatch loadFullTree(Integer catchBatchId) {
091        // Call method throw the interface, to enable cache use
092        return catchBatchDao.loadFullTreeWithCache(catchBatchId, AdagioConfiguration.getInstance().useBacthTreeCache(), false);
093    }
094
095    @Override
096    public CatchBatch loadFullTree(Integer catchBatchId, boolean validate, boolean quickFix) throws CatchBatchValidationException {
097        // Call method throw the interface, to enable cache use
098        CatchBatch catchBatch = catchBatchDao.loadFullTreeWithCache(catchBatchId, AdagioConfiguration.getInstance().useBacthTreeCache(), false);
099
100        // Catch batch validation
101        if (validate) {
102            boolean retryValidation = true;
103            int quickFixCounter = 0;
104            while (retryValidation) {
105                // Applied validation
106                List<CatchBatchValidationError> errors = validate(catchBatch);
107                retryValidation = false;
108
109                // Check if validation results has error with gravity ERROR
110                if (errors != null && errors.size() > 0) {
111                    List<CatchBatchQuickFix> quickFixes = Lists.newArrayList();
112                    boolean hasGravityError = false;
113
114                    for (CatchBatchValidationError error : errors) {
115                        if (error.getGravity() == CatchBatchValidationError.GRAVITY_ERROR) {
116                            hasGravityError = true;
117                            // Store quick fixes if any
118                            if (quickFix && error.getQuickFixes() != null) {
119                                quickFixes.addAll(error.getQuickFixes());
120                            }
121                        }
122                    }
123
124                    // If errors found but one quick fix could be apply
125                    if (hasGravityError && quickFix && quickFixes.size() == 1 && quickFixCounter < 2) {
126                        // applied the quick fix :
127                        catchBatch = quickFixes.get(0).repair(catchBatch);
128                        retryValidation = true;
129                        quickFixCounter++;
130                    }
131                    // Error found, and could not be repaired
132                    else if (hasGravityError) {
133                        throw new CatchBatchValidationException(errors);
134                    }
135                }
136
137            }
138        }
139        return catchBatch;
140    }
141
142    @Override
143    public List<CatchBatchValidationError> validate(CatchBatch catchBatch) {
144        List<CatchBatchValidationError> errors = Lists.newArrayList();
145        for (CatchBatchValidator validator : validators) {
146            if (validator.isEnable(catchBatch)) {
147                List<CatchBatchValidationError> result = validator.validate(catchBatch);
148                if (result != null && result.size() > 0) {
149                    errors.addAll(result);
150                }
151            }
152        }
153        if (errors.size() == 0) {
154            return null;
155        }
156        return errors;
157    }
158
159    @Override
160    public SortingBatch getSortingBatch(Collection<Batch> batchs,
161            Object... params) {
162
163        if (batchs == null || batchs.size() == 0
164                || params == null || params.length == 0) {
165            return null;
166        }
167
168        String propertyName = (String) params[0];
169        Integer expectedPmfmId = null;
170        Integer qualitativeValueId = null;
171        Integer referenceTaxonId = null;
172        Object[] newParams = null;
173        if (PMFM_ID.equals(propertyName)) {
174            Preconditions.checkArgument(
175                    params.length >= 3,
176                    "Params must be tuple (propertyName, [pmfmId,] value)");
177            expectedPmfmId = (Integer) params[1];
178            qualitativeValueId = (Integer) params[2];
179            newParams = Arrays.copyOfRange(params, 3, params.length);
180        } else if (REFERENCE_TAXON_ID.equals(propertyName)) {
181            Preconditions.checkArgument(
182                    params.length >= 2,
183                    "Params must be tuple (propertyName, [referenceTaxonId,] value)");
184            referenceTaxonId = (Integer) params[1];
185            newParams = Arrays.copyOfRange(params, 2, params.length);
186        } else {
187            Preconditions.checkArgument(
188                    false,
189                    "Params must be tuple (propertyName, [id,] value), and propertyName must be 'pmfmId' or 'referenceTaxonId'.");
190        }
191
192        for (Batch batch : batchs) {
193            SortingBatch sortingBatch = (SortingBatch) batch;
194            boolean found = false;
195
196            if (expectedPmfmId != null) {
197                for (SortingMeasurement sm : sortingBatch.getSortingMeasurements()) {
198                    Integer pmfmId = sm.getPmfm().getId();
199                    if (expectedPmfmId.equals(pmfmId)
200                            && sm.getQualitativeValue() != null
201                            && qualitativeValueId.equals(sm.getQualitativeValue().getId())) {
202                        found = true;
203                        break;
204                    }
205                }
206            } else if (referenceTaxonId != null
207                    && sortingBatch.getReferenceTaxon() != null
208                    && referenceTaxonId.equals(sortingBatch.getReferenceTaxon().getId())) {
209                found = true;
210            }
211
212            if (found) {
213                if (newParams != null && newParams.length > 0) {
214                    return getSortingBatch(sortingBatch.getChildBatchs(), newParams);
215                }
216                return sortingBatch;
217            }
218        }
219        return null;
220    }
221
222    @Override
223    public void registerCatchBatchValidator(CatchBatchValidator validator) {
224        if (!validators.contains(validator)) {
225            validators.add(validator);
226        }
227    }
228
229    @Override
230    public void unregisterCatchBatchValidator(CatchBatchValidator validator) {
231        validators.remove(validator);
232    }
233
234    @Override
235    public void update(CatchBatch catchBatch) {
236        super.update(catchBatch);
237    }
238
239    @Override
240    public void removeWithChildren(Integer batchId) {
241        removeWithChildren(batchId, null);
242    }
243
244    @Override
245    public List<Integer> getAllChildrenIds(Integer batchId) {
246        List<Integer> result = Lists.newArrayList();
247        getAllChildrenIds(batchId, result);
248        // don't keep the top node id
249        result.remove(batchId);
250        return result;
251    }
252
253    @Override
254    public void remove(Integer id) {
255
256        Preconditions.checkNotNull(id);
257
258        List<Integer> childrenIds = getAllChildrenIds(id);
259
260        for (Integer childrenId : childrenIds) {
261            SortingBatch sortingBatch = load(SortingBatchImpl.class, childrenId);
262            sortingBatch.getSortingMeasurements().clear();
263            sortingBatch.getQuantificationMeasurements().clear();
264            getSession().delete(sortingBatch);
265        }
266        CatchBatch catchBatch = load(CatchBatchImpl.class, id);
267        catchBatch.getQuantificationMeasurements().clear();
268        catchBatch.getFishingOperation().setCatchBatch(null);
269        super.remove(catchBatch);
270    }
271
272    @Override
273    public void removeWithChildren(Integer batchId, CatchBatch parentCatchBatch) {
274        Iterator<Object[]> childRows = queryIteratorTyped("childBatchIds",
275                "parentBatchId", IntegerType.INSTANCE, batchId);
276
277        boolean isCatchBatch = false;
278
279        // First remove all children
280        while (childRows.hasNext()) {
281            Object[] childRow = childRows.next();
282            Integer childBatchId = (Integer) childRow[0];
283            Integer rootBatchId = (Integer) childRow[1];
284            if (batchId.equals(rootBatchId)) {
285                isCatchBatch = true;
286            }
287
288            // Recursive call
289            removeWithChildren(childBatchId, parentCatchBatch);
290        }
291
292        // Then remove the current batch
293        if (isCatchBatch) {
294            CatchBatch catchBatch = load(CatchBatchImpl.class, batchId);
295
296            catchBatch.getQuantificationMeasurements().clear();
297            getSession().delete(catchBatch);
298        } else {
299            SortingBatch sortingBatch = load(SortingBatchImpl.class, batchId);
300            sortingBatch.getSortingMeasurements().clear();
301            sortingBatch.getQuantificationMeasurements().clear();
302            getSession().delete(sortingBatch);
303
304            // If possible, update the batch tree :
305            if (parentCatchBatch != null) {
306                SortingBatch existingSortingBatch = parentCatchBatch.getSortingBatchById().get(batchId);
307                if (existingSortingBatch != null) {
308                    Batch parentBatch = existingSortingBatch.getParentBatch();
309                    parentCatchBatch.getSortingBatchById().remove(batchId);
310                    if (parentBatch != null) {
311                        parentBatch.getChildBatchs().remove(existingSortingBatch);
312                    }
313                }
314            }
315        }
316    }
317
318    @Override
319    public CatchBatch loadFullTreeWithCache(Integer catchBatchId, boolean useCache, boolean forceReload) {
320        long time1 = 0;
321        if (logger.isDebugEnabled()) {
322            logger.debug("call loadFullTreeWithCache()");
323            time1 = System.currentTimeMillis();
324        }
325        Session session = getSession();
326
327        CatchBatch catchBatch = queryUniqueTyped("catchBatchOnly",
328                "catchBatchId", IntegerType.INSTANCE, catchBatchId);
329
330        if (catchBatch == null) {
331            return null;
332        }
333
334        Map<Integer, SortingBatch> sortingBatchById = catchBatch.getSortingBatchById();
335
336        session.evict(catchBatch);
337        catchBatch.setChildBatchs(new HashSet<Batch>());
338        // error de all-delete-orphan ?? catchBatch.getChildBatchs().clear();
339        computeTechnicalWeights(catchBatch);
340
341        Map<Integer, Integer> parentBatchMapById = new HashMap<Integer, Integer>();
342
343        List<SortingBatch> list = queryListTyped("allBatch",
344                "rootBatchId", IntegerType.INSTANCE, catchBatch.getId());
345        Comparator<Batch> batchComparator = new Comparator<Batch>() {
346            @Override
347            public int compare(Batch b1, Batch b2) {
348                return (b1.getRankOrder() == null) ? 0 : b1.getRankOrder().compareTo(b2.getRankOrder());
349            }
350        };
351
352        for (SortingBatch source : list) {
353            session.evict(source);
354
355            // compute weights
356            computeTechnicalWeights(source);
357
358            // source.setChildBatchs(new TreeSet<Batch>(batchComparator));
359            source.setChildBatchs(new TreeSet<Batch>(batchComparator));
360            // error de all-delete-orphan ?? source.getChildBatchs().clear();
361            Integer parentBatchId = source.getParentBatch().getId();
362            // Add result into a maps
363            sortingBatchById.put(source.getId(), source);
364            if (parentBatchId != null) {
365                parentBatchMapById.put(source.getId(), parentBatchId);
366            }
367        }
368
369        // Retrieve the parent links for all batchs
370        for (SortingBatch batch : sortingBatchById.values()) {
371            // If retrieve the parent from the parent map
372            Integer parentbatchId = parentBatchMapById.get(batch.getId());
373            if (parentbatchId != null) {
374                SortingBatch parentBatch = sortingBatchById.get(parentbatchId);
375
376                // If found, link the batch with its parent :
377                if (parentBatch != null) {
378                    batch.setParentBatch(parentBatch);
379                    parentBatch.getChildBatchs().add(batch);
380                }
381
382                // If no parent found, the batch should be a direct child of the catch batch
383                else if (parentbatchId.equals(catchBatch.getId())) {
384                    catchBatch.getChildBatchs().add(batch);
385                }
386            }
387        }
388
389        // Apply inheritance, starting with the catch batch children
390        applyInheritance(catchBatch.getChildBatchs(), null, null, null, false, 1);
391
392        if (logger.isDebugEnabled()) {
393            logger.debug("end of loadFullTreeWithCache() - loading in "
394                    + (System.currentTimeMillis() - time1)
395                    + " ms.");
396        }
397
398        return catchBatch;
399    }
400
401    @Override
402    public boolean isCatchBatchExistsForFishingOperation(Integer fishingOperationId) {
403        Preconditions.checkNotNull(fishingOperationId);
404
405        Integer catchBatchId = queryUniqueTyped("fishingOperationCatchBatchId",
406                "fishingOperationId", IntegerType.INSTANCE, fishingOperationId);
407        return catchBatchId != null;
408    }
409
410    @Override
411    public Integer getIdByFishingOperationId(Integer fishingOperationId) {
412        Preconditions.checkNotNull(fishingOperationId);
413
414        Integer catchBatchId = queryUniqueTyped("fishingOperationCatchBatchId",
415                "fishingOperationId", IntegerType.INSTANCE, fishingOperationId);
416        if (catchBatchId == null) {
417            throw new DataRetrievalFailureException("Unable to retrieve catch batch for fishing operation id=" + fishingOperationId);
418        }
419        return catchBatchId;
420    }
421
422    @Override
423    public Integer getIdBySortingBatchId(Integer batchId) {
424        Preconditions.checkNotNull(batchId);
425
426        Integer catchBatchId = queryUniqueTyped("rootBatchId",
427                "sortingBatchId", IntegerType.INSTANCE, batchId);
428        if (catchBatchId == null) {
429            throw new DataRetrievalFailureException("Unable to retrieve root catch batch for batch id=" + batchId);
430        }
431        return catchBatchId;
432    }
433
434    @Override
435    public SortingBatch getSortingBatchById(CatchBatch catchBatch, Integer sortingBatchId) {
436        Preconditions.checkNotNull(catchBatch);
437        Preconditions.checkNotNull(sortingBatchId);
438        Preconditions.checkNotNull(catchBatch.getSortingBatchById());
439
440        SortingBatch sortingBatch = catchBatch.getSortingBatchById().get(sortingBatchId);
441        if (sortingBatch == null) {
442            throw new DataRetrievalFailureException(
443                    "Could not found batch with id="
444                            + sortingBatchId
445                            + " in the batch tree elements. Make sure the cache has been cleaned, since the last update of the tree.");
446        }
447        return sortingBatch;
448    }
449
450    @Override
451    public QuantificationMeasurement setQuantificationMeasurement(
452            Batch batch, Integer pmfmId, Integer recorderDepartmentId,
453            Float weightValue, boolean isReferenceQuantitification) {
454        QuantificationMeasurement quantificationMeasurement = getQuantificationMeasurement(
455                batch, pmfmId, recorderDepartmentId, true);
456
457        quantificationMeasurement.setNumericalValue(weightValue);
458        quantificationMeasurement
459                .setIsReferenceQuantification(isReferenceQuantitification);
460        return quantificationMeasurement;
461    }
462
463    @Override
464    public QuantificationMeasurement getQuantificationMeasurement(
465            Batch batch, Integer pmfmId, Integer recorderDepartmentId,
466            boolean createIfNotExists) {
467        QuantificationMeasurement quantificationMeasurement = null;
468        if (batch.getQuantificationMeasurements() != null) {
469            for (QuantificationMeasurement qm : batch
470                    .getQuantificationMeasurements()) {
471                if (pmfmId.equals(qm.getPmfm().getId())) {
472                    quantificationMeasurement = qm;
473                    break;
474                }
475            }
476        }
477        if (quantificationMeasurement == null) {
478            if (!createIfNotExists) {
479                return null;
480            }
481            quantificationMeasurement = QuantificationMeasurement.Factory
482                    .newInstance();
483            quantificationMeasurement.setBatch(batch);
484            if (batch.getQuantificationMeasurements() == null) {
485                batch.setQuantificationMeasurements(Sets
486                        .newHashSet(quantificationMeasurement));
487            } else {
488                batch.getQuantificationMeasurements().add(
489                        quantificationMeasurement);
490            }
491            quantificationMeasurement.setQualityFlag(load(
492                    QualityFlagImpl.class,
493                    QualityFlagCode.NOTQUALIFIED.getValue()));
494            quantificationMeasurement.setDepartment(load(DepartmentImpl.class,
495                    recorderDepartmentId));
496            quantificationMeasurement.setPmfm(load(PmfmImpl.class, pmfmId));
497        }
498
499        return quantificationMeasurement;
500    }
501
502    @Override
503    public SortingMeasurement getSortingMeasurement(
504            SortingBatch sortingBatch, Integer pmfmId, Integer recorderDepartmentId,
505            boolean createIfNotExists) {
506        SortingMeasurement sortingMeasurement = null;
507        if (sortingBatch.getSortingMeasurements() != null) {
508            for (SortingMeasurement qm : sortingBatch
509                    .getSortingMeasurements()) {
510                if (pmfmId.equals(qm.getPmfm().getId())) {
511                    sortingMeasurement = qm;
512                    break;
513                }
514            }
515        }
516        if (sortingMeasurement == null) {
517            if (!createIfNotExists) {
518                return null;
519            }
520            sortingMeasurement = SortingMeasurement.Factory
521                    .newInstance();
522            sortingMeasurement.setSortingBatch(sortingBatch);
523            if (sortingBatch.getSortingMeasurements() == null) {
524                sortingBatch.setSortingMeasurements(Sets
525                        .newHashSet(sortingMeasurement));
526                sortingMeasurement.setRankOrder(1);
527            } else {
528                sortingBatch.getSortingMeasurements().add(
529                        sortingMeasurement);
530                sortingMeasurement.setRankOrder(sortingBatch.getSortingMeasurements().size());
531            }
532            sortingMeasurement.setQualityFlag(load(
533                    QualityFlagImpl.class,
534                    QualityFlagCode.NOTQUALIFIED.getValue()));
535            sortingMeasurement.setDepartment(load(DepartmentImpl.class,
536                    recorderDepartmentId));
537            sortingMeasurement.setPmfm(load(PmfmImpl.class, pmfmId));
538        }
539
540        return sortingMeasurement;
541    }
542
543    @Override
544    public SortingMeasurement getInheritedSortingMeasurement(
545            SortingBatch sortingBatch, Integer pmfmId) {
546        if (sortingBatch.getInheritedSortingMeasurements() != null) {
547            for (SortingMeasurement qm : sortingBatch
548                    .getInheritedSortingMeasurements()) {
549                if (pmfmId.equals(qm.getPmfm().getId())) {
550                    return qm;
551                }
552            }
553        }
554        return null;
555    }
556
557    @Override
558    public SortingBatch createSortingBatch(SortingBatch sortingBatch, CatchBatch parentCatchBatch) {
559        SortingBatch result = sortingBatchDao.create(sortingBatch);
560
561        // Refresh batch tree
562        // refreshSortingBatchInBatchTree(result, parentCatchBatch);
563
564        return result;
565    }
566
567    @Override
568    public SortingBatch loadSortingBatch(Integer sortingBatchId, CatchBatch parentCatchBatch) {
569        SortingBatch result = parentCatchBatch.getSortingBatchById().get(sortingBatchId);
570        if (result == null) {
571            result = sortingBatchDao.load(sortingBatchId);
572            // refreshSortingBatchInBatchTree(result, parentCatchBatch);
573        }
574        return result;
575    }
576
577    @Override
578    public void updateSortingBatch(SortingBatch sortingBatch, CatchBatch parentCatchBatch) {
579        sortingBatchDao.update(sortingBatch);
580        // refreshSortingBatchInBatchTree(sortingBatch, parentCatchBatch);
581    }
582
583    @Override
584    public void updateSortingBatch(List<SortingBatch> sortingBatchs, CatchBatch parentCatchBatch) {
585        sortingBatchDao.update(sortingBatchs);
586        // for (SortingBatch sortingBatch : sortingBatchs) {
587        // refreshSortingBatchInBatchTree(sortingBatch, parentCatchBatch);
588        // }
589    }
590
591    // ------------------------------------------------------------------------//
592    // -- Internal methods --//
593    // ------------------------------------------------------------------------//
594
595    protected void applyInheritance(Collection<Batch> batchs,
596            List<SortingMeasurement> inheritedSortingMeasurements,
597            Integer inheritedTaxonGroupId,
598            Integer inheritedReferenceTaxonId,
599            boolean inheritedExhaustiveInventory,
600            int treeLevel) {
601        if (batchs == null || batchs.size() == 0) {
602            return;
603        }
604        for (Batch notCastedBatch : batchs) {
605            SortingBatch batch = (SortingBatch) notCastedBatch;
606            // Apply sorting measurements inheritance, if need
607            if (inheritedSortingMeasurements != null && inheritedSortingMeasurements.size() > 0) {
608                batch.getInheritedSortingMeasurements().clear();
609                batch.getInheritedSortingMeasurements().addAll(inheritedSortingMeasurements);
610            }
611
612            // Apply taxon group and reference taxon inheritance, if need
613            if (batch.getReferenceTaxon() == null && inheritedReferenceTaxonId != null) {
614                batch.setInheritedReferenceTaxonId(inheritedReferenceTaxonId);
615            }
616            if (batch.getTaxonGroup() == null && inheritedTaxonGroupId != null) {
617                batch.setInheritedTaxonGroupId(inheritedTaxonGroupId);
618            }
619
620            // Exhaustive inventory inheritance, if need
621            if (inheritedExhaustiveInventory) {
622                batch.setExhaustiveInventory(inheritedExhaustiveInventory);
623            } else {
624                batch.setExhaustiveInventory(false);
625            }
626
627            batch.setTreeLevel((short) treeLevel);
628
629            if (batch.getChildBatchs() != null && batch.getChildBatchs().size() > 0) {
630                List<SortingMeasurement> newInheritedSortingMeasurement = Lists.newArrayList();
631                if (inheritedSortingMeasurements != null) {
632                    newInheritedSortingMeasurement.addAll(inheritedSortingMeasurements);
633                }
634                newInheritedSortingMeasurement.addAll(batch.getSortingMeasurements());
635
636                // Recursive call : propagate species and sorted/unsorted value
637                applyInheritance(batch.getChildBatchs(),
638                        newInheritedSortingMeasurement,
639                        batch.getTaxonGroup() == null ? null : batch.getTaxonGroup().getId(),
640                        batch.getReferenceTaxon() == null ? null : batch.getReferenceTaxon().getId(),
641                        batch.isExhaustiveInventory(),
642                        treeLevel + 1);
643            }
644
645        }
646    }
647
648    protected void applyInheritanceOnOneChild(SortingBatch parentBatch, SortingBatch batchToUpdate) {
649        int treeLevel = parentBatch.getTreeLevel();
650
651        if (parentBatch.getChildBatchs() != null && parentBatch.getChildBatchs().size() > 0) {
652            List<SortingMeasurement> newInheritedSortingMeasurement = Lists.newArrayList();
653
654            if (parentBatch.getInheritedSortingMeasurements() != null) {
655                newInheritedSortingMeasurement.addAll(parentBatch.getInheritedSortingMeasurements());
656            }
657            newInheritedSortingMeasurement.addAll(parentBatch.getSortingMeasurements());
658
659            // Recursive call : propagate species and sorted/unsorted value
660            applyInheritance(Lists.newArrayList((Batch) batchToUpdate),
661                    newInheritedSortingMeasurement,
662                    parentBatch.getTaxonGroup() == null ? null : parentBatch.getTaxonGroup().getId(),
663                    parentBatch.getReferenceTaxon() == null ? null : parentBatch.getReferenceTaxon().getId(),
664                    parentBatch.isExhaustiveInventory(),
665                    treeLevel + 1);
666        }
667    }
668
669    protected void computeTechnicalWeights(Batch batch) {
670        Float weight = null;
671        for (QuantificationMeasurement qm : batch.getQuantificationMeasurements()) {
672            if (qm.getIsReferenceQuantification()) {
673                weight = qm.getNumericalValue();
674                batch.setWeightMethodId(qm.getPmfm().getMethod().getId());
675            }
676        }
677
678        if (weight == null) {
679            return;
680        }
681        if (batch instanceof SortingBatch) {
682            SortingBatch sortingBatch = (SortingBatch) batch;
683            String samplingRatioText = sortingBatch.getSamplingRatioText();
684            Float samplingRatio = sortingBatch.getSamplingRatio();
685            String startStr = weight.toString().replace(',', '.') + "/";
686            if (samplingRatioText != null && samplingRatioText.startsWith(startStr)) {
687                String weightStr = samplingRatioText.substring(startStr.length());
688                if (weightStr != null && !weightStr.isEmpty()) {
689                    batch.setWeightBeforeSampling(Float.parseFloat(weightStr));
690                }
691            } else if (samplingRatio != null) {
692                batch.setWeightBeforeSampling(weight / samplingRatio);
693            }
694            batch.setWeight(weight);
695        } else if (batch instanceof fr.ifremer.adagio.core.dao.data.batch.CatchBatch) {
696            fr.ifremer.adagio.core.dao.data.batch.CatchBatch catchBatch = (fr.ifremer.adagio.core.dao.data.batch.CatchBatch) batch;
697            catchBatch.setWeight(weight);
698        }
699
700    }
701
702    protected Integer getCatchBatchIdByBatchId(String batchId) {
703        Preconditions.checkNotNull(batchId);
704
705        Integer catchBatchId = queryUniqueTyped("rootBatchId",
706                "batchId", IntegerType.INSTANCE, Integer.valueOf(batchId));
707        if (catchBatchId == null) {
708            throw new DataRetrievalFailureException("Unable to retrieve root catch batch for batch id=" + batchId);
709        }
710        return catchBatchId;
711    }
712
713    protected void refreshSortingBatchInBatchTree(SortingBatch sortingBatch, CatchBatch parentCatchBatch) {
714        Preconditions.checkNotNull(sortingBatch);
715        Preconditions.checkNotNull(sortingBatch.getId());
716        Preconditions.checkNotNull(sortingBatch.getParentBatch());
717        Preconditions.checkNotNull(sortingBatch.getParentBatch().getId());
718        Preconditions.checkNotNull(parentCatchBatch);
719        Preconditions.checkNotNull(parentCatchBatch.getId());
720
721        // Retrieve parent batch
722        Integer parentBatchId = sortingBatch.getParentBatch().getId();
723        Batch parentBatch;
724        if (parentBatchId.equals(parentCatchBatch.getId()))
725            parentBatch = parentCatchBatch;
726        else {
727            parentBatch = parentCatchBatch.getSortingBatchById().get(parentBatchId);
728        }
729
730        // Update sortingBatch parent if need
731        if (parentBatch == null) {
732            refreshSortingBatchInBatchTree((SortingBatch) sortingBatch.getParentBatch(), parentCatchBatch);
733            parentBatch = sortingBatch.getParentBatch();
734        } else if (sortingBatch.getParentBatch() != parentBatch) {
735            sortingBatch.setParentBatch(parentBatch);
736        }
737
738        // Update child into the parent batch
739        if (!parentBatch.getChildBatchs().contains(sortingBatch)) {
740            parentBatch.getChildBatchs().add(sortingBatch);
741        }
742        if (parentBatch instanceof SortingBatch) {
743            applyInheritanceOnOneChild((SortingBatch) parentBatch, sortingBatch);
744        }
745
746        // Update the batch in the usefull map, stored in catchBatch
747        SortingBatch existingSortingbatch = parentCatchBatch.getSortingBatchById().get(sortingBatch.getId());
748        if (existingSortingbatch == null || existingSortingbatch != sortingBatch) {
749            parentCatchBatch.getSortingBatchById().put(sortingBatch.getId(), existingSortingbatch);
750        }
751
752        // update computed weight
753        computeTechnicalWeights(sortingBatch);
754    }
755
756    @Override
757    public void setSortingBatchReferenceTaxon(String batchId, Integer referenceTaxonId) {
758        Preconditions.checkNotNull(batchId);
759        Preconditions.checkNotNull(referenceTaxonId);
760
761        if (logger.isDebugEnabled()) {
762            logger.debug("Changing reference taxon for batch id=" + batchId);
763        }
764
765        int rowUpdated = queryUpdate("updateSortingBatchReferenceTaxon",
766                "sortingBatchId", IntegerType.INSTANCE, Integer.valueOf(batchId),
767                "referenceTaxonId", IntegerType.INSTANCE, referenceTaxonId);
768        Preconditions.checkArgument(rowUpdated == 1, "Unable to update batch reference taxon.");
769    }
770
771    protected void getAllChildrenIds(Integer batchId, List<Integer> result) {
772        Iterator<Object[]> childRows = queryIteratorTyped("childBatchIds",
773                "parentBatchId", IntegerType.INSTANCE, batchId);
774        while (childRows.hasNext()) {
775            Object[] childRow = childRows.next();
776            Integer childBatchId = (Integer) childRow[0];
777
778            getAllChildrenIds(childBatchId, result);
779        }
780        result.add(batchId);
781    }
782}