Author: blavenier Date: 2013-02-14 16:27:16 +0100 (Thu, 14 Feb 2013) New Revision: 413 Url: http://forge.codelutin.com/projects/tutti/repository/revisions/413 Log: Fix : - saveBatchFrequencies now delete extra batch - store weights for 'inert' and 'livingNotSorted' Add : - ReferentialPersistenceService.getSampleCategoryIds() Improve : - Merge CatchBatchPersistenceService and SpeciesBatchPersistenceService into BatchPersistenceService - batch management now use adagio implementation CatchBatchExtendDao Added: trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/BatchPersistenceService.java trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/BatchPersistenceServiceImpl.java trunk/tutti-persistence/src/test/java/fr/ifremer/tutti/persistence/service/BatchPersistenceServiceReadTest.java trunk/tutti-persistence/src/test/java/fr/ifremer/tutti/persistence/service/BatchPersistenceServiceWriteTest.java Removed: trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/CatchBatchPersistenceServiceImpl.java trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/SpeciesBatchPersistenceServiceImpl.java Modified: trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/AbstractPersistenceService.java trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/ReferentialPersistenceService.java trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/ReferentialPersistenceServiceImpl.java trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/TuttiEnumerationFile.java trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/TuttiPersistenceServiceLocator.java trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/measure/MeasurementPersistenceHelper.java trunk/tutti-persistence/src/main/resources/applicationContext-service-tutti.xml trunk/tutti-persistence/src/main/resources/i18n/tutti-persistence_fr_FR.properties trunk/tutti-persistence/src/main/resources/queries-override.hbm.xml trunk/tutti-persistence/src/main/resources/tutti-db-conf.properties trunk/tutti-persistence/src/main/resources/tutti-db-enumerations.properties Modified: trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/AbstractPersistenceService.java =================================================================== --- trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/AbstractPersistenceService.java 2013-02-14 10:40:25 UTC (rev 412) +++ trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/AbstractPersistenceService.java 2013-02-14 15:27:16 UTC (rev 413) @@ -38,6 +38,7 @@ import java.io.Serializable; import java.util.Iterator; +import java.util.List; /** * TODO @@ -123,6 +124,13 @@ return result; } + protected <T> List<T> queryList2Typed(String queryName, Object... params) { + + Query query = createQuery(queryName, params); + List result = query.list(); + return result; + } + protected Query createQuery(String queryName, Object... params) { Query query = getCurrentSession().getNamedQuery(queryName); Added: trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/BatchPersistenceService.java =================================================================== --- trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/BatchPersistenceService.java (rev 0) +++ trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/BatchPersistenceService.java 2013-02-14 15:27:16 UTC (rev 413) @@ -0,0 +1,8 @@ +package fr.ifremer.tutti.persistence.service; + +import org.springframework.transaction.annotation.Transactional; + +@Transactional(readOnly = true) +public interface BatchPersistenceService extends CatchBatchPersistenceService, SpeciesBatchPersistenceService{ + +} Added: trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/BatchPersistenceServiceImpl.java =================================================================== --- trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/BatchPersistenceServiceImpl.java (rev 0) +++ trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/BatchPersistenceServiceImpl.java 2013-02-14 15:27:16 UTC (rev 413) @@ -0,0 +1,1297 @@ +package fr.ifremer.tutti.persistence.service; + +import static org.nuiton.i18n.I18n._; + +import java.io.Serializable; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.annotation.Resource; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.hibernate.FlushMode; +import org.hibernate.type.IntegerType; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.dao.DataRetrievalFailureException; +import org.springframework.stereotype.Service; + +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; + +import fr.ifremer.adagio.core.dao.data.batch.Batch; +import fr.ifremer.adagio.core.dao.data.batch.CatchBatchExtendDao; +import fr.ifremer.adagio.core.dao.data.batch.SortingBatch; +import fr.ifremer.adagio.core.dao.data.batch.SortingBatchDao; +import fr.ifremer.adagio.core.dao.data.batch.denormalized.DenormalizedBatchDao; +import fr.ifremer.adagio.core.dao.data.batch.validator.CatchBatchValidationError; +import fr.ifremer.adagio.core.dao.data.batch.validator.CatchBatchValidationException; +import fr.ifremer.adagio.core.dao.data.batch.validator.CatchBatchValidator; +import fr.ifremer.adagio.core.dao.data.measure.QuantificationMeasurement; +import fr.ifremer.adagio.core.dao.data.measure.SortingMeasurement; +import fr.ifremer.adagio.core.dao.data.operation.FishingOperationImpl; +import fr.ifremer.adagio.core.dao.referential.QualityFlagImpl; +import fr.ifremer.adagio.core.dao.referential.taxon.ReferenceTaxon; +import fr.ifremer.adagio.core.dao.referential.taxon.ReferenceTaxonImpl; +import fr.ifremer.adagio.core.dao.technical.synchronization.SynchronizationStatus; +import fr.ifremer.tutti.persistence.entities.data.CatchBatch; +import fr.ifremer.tutti.persistence.entities.data.SampleCategoryEnum; +import fr.ifremer.tutti.persistence.entities.data.SpeciesBatch; +import fr.ifremer.tutti.persistence.entities.data.SpeciesBatchFrequency; +import fr.ifremer.tutti.persistence.entities.referential.Caracteristic; +import fr.ifremer.tutti.persistence.entities.referential.CaracteristicQualitativeValue; +import fr.ifremer.tutti.persistence.entities.referential.CaracteristicType; +import fr.ifremer.tutti.persistence.entities.referential.Species; +import fr.ifremer.tutti.persistence.service.measure.MeasurementPersistenceHelper; + +@Service("batchPersistenceService") +public class BatchPersistenceServiceImpl + extends AbstractPersistenceService implements BatchPersistenceService, CatchBatchValidator + { + + /** Logger. */ + private static final Log log = + LogFactory.getLog(BatchPersistenceServiceImpl.class); + + @Resource(name = "referentialPersistenceService") + protected ReferentialPersistenceService referentialService; + + @Resource(name = "denormalizedBatchDao") + protected DenormalizedBatchDao denormalizedBatchDao; + + @Resource(name = "sortingBatchDao") + protected SortingBatchDao sortingBatchDao; + + @Resource(name = "catchBatchDao") + protected CatchBatchExtendDao catchBatchDao; + + @Resource(name = "measurementPersistenceHelper") + protected MeasurementPersistenceHelper measurementHelper; + + @Override + public void init() { + super.init(); + catchBatchDao.registerCatchBatchValidator(this); + } + + @Override + public void close() { + catchBatchDao.unregisterCatchBatchValidator(this); + super.close(); + } + + @Override + public boolean isEnable(fr.ifremer.adagio.core.dao.data.batch.CatchBatch catchBatch) { + // Apply validation only on catch batch for fishingOperation + return (catchBatch.getFishingOperation() != null); + } + + @Override + public List<CatchBatchValidationError> validate(fr.ifremer.adagio.core.dao.data.batch.CatchBatch catchBatch) { + List<CatchBatchValidationError> errors = Lists.newArrayList(); + validate(catchBatch.getChildBatchs(), errors, 1); + return errors; + } + + @Override + public CatchBatch getCatchBatchFromFishingOperation(String fishingOperationId) { + Preconditions.checkNotNull(fishingOperationId); + + Integer catchBatchId = catchBatchDao.getIdByFishingOperationId(Integer.valueOf(fishingOperationId)); + + fr.ifremer.adagio.core.dao.data.batch.CatchBatch source; + try { + source = catchBatchDao.loadFullTree(catchBatchId, true, true); + } catch (CatchBatchValidationException e) { + throw new DataRetrievalFailureException("Invalid batch tree structure, for fishing operation id=" + fishingOperationId, e); + } + + CatchBatch result = new CatchBatch(); + result.setId(source.getId().toString()); + result.setCatchTotalWeight(source.getWeight()); + + // Vrac + SortingBatch vracBatch = catchBatchDao.getSortingBatch(source.getChildBatchs(), + "pmfmId", enumeration.PMFM_ID_SORTED_UNSORTED, enumeration.QUALITATIVE_VRAC_ID); + result.setCatchTotalSortedCarousselWeight(vracBatch.getWeight()); + result.setCatchTotalSortedTremisWeight(vracBatch.getWeightBeforeSampling()); + { + // Species + SortingBatch speciesBatch = catchBatchDao.getSortingBatch(vracBatch.getChildBatchs(), + "pmfmId", enumeration.PMFM_ID_SORTING_TYPE, enumeration.QUALITATIVE_ID_SORTING_TYPE_SPECIES); + + result.setSpeciesTotalSampleSortedWeight(speciesBatch.getWeight()); + result.setSpeciesTotalSortedWeight(speciesBatch.getWeightBeforeSampling()); + + { + // Inert + SortingBatch inertBatch = catchBatchDao.getSortingBatch(speciesBatch.getChildBatchs(), + "referenceTaxonId", enumeration.REFERENCE_TAXON_ID_INERT); + result.setSpeciesTotalInertWeight(inertBatch.getWeight()); + + // Alive no itemized + SortingBatch livingNotItemizedBatch = catchBatchDao.getSortingBatch(speciesBatch.getChildBatchs(), + "referenceTaxonId", enumeration.REFERENCE_TAXON_ID_LIFE); + result.setSpeciesTotalLivingNotItemizedWeight(livingNotItemizedBatch.getWeight()); + } + + // TODO : Benthos, Plancton... + } + + // Hors Vrac + SortingBatch horsVracBatch = catchBatchDao.getSortingBatch(source.getChildBatchs(), + "pmfmId", enumeration.PMFM_ID_SORTED_UNSORTED, enumeration.QUALITATIVE_HORS_VRAC_ID); + result.setCatchTotalUnsortedWeight(horsVracBatch.getWeight()); + { + // Species + SortingBatch speciesBatch = catchBatchDao.getSortingBatch(horsVracBatch.getChildBatchs(), + "pmfmId", enumeration.PMFM_ID_SORTING_TYPE, enumeration.QUALITATIVE_ID_SORTING_TYPE_SPECIES); + + result.setSpeciesTotalUnsortedWeight(speciesBatch.getWeight()); + + // TODO : Benthos, Plancton... + } + + // Non trié + SortingBatch unsortedBatch = catchBatchDao.getSortingBatch(source.getChildBatchs(), + "pmfmId", enumeration.PMFM_ID_SORTED_UNSORTED, enumeration.QUALITATIVE_UNSORTED_ID); + result.setCatchTotalRejectedWeight(unsortedBatch.getWeight()); + + return result; + } + + @Override + + public CatchBatch createCatchBatch(CatchBatch bean) { + Preconditions.checkNotNull(bean); + Preconditions.checkArgument(bean.getId() == null); + Preconditions.checkNotNull(bean.getFishingOperation()); + Preconditions.checkNotNull(bean.getFishingOperation().getId()); + + fr.ifremer.adagio.core.dao.data.batch.CatchBatch catchBatch = fr.ifremer.adagio.core.dao.data.batch.CatchBatch.Factory.newInstance(); + beanToEntity(bean, catchBatch, true); + catchBatch = catchBatchDao.create(catchBatch); + bean.setId(String.valueOf(catchBatch.getId())); + + // Link to fishing operation + getCurrentSession().flush(); + Integer fishingOperationId = Integer.valueOf(bean.getFishingOperation().getId()); + int rowUpdated = queryUpdate("updateFishingOperationCatchBatch", + "fishingOperationId", IntegerType.INSTANCE, fishingOperationId, + "catchBatchId", IntegerType.INSTANCE, catchBatch.getId()); + if (rowUpdated == 0) { + throw new DataIntegrityViolationException("Could not attach catch batch to the given operation : operation was not found."); + } + + return bean; + } + + @Override + @CacheEvict(value = "batchTree", key="#bean.fishingOperation.id") + public CatchBatch saveCatchBatch(CatchBatch bean) { + + Preconditions.checkNotNull(bean); + Preconditions.checkNotNull(bean.getId()); + + getCurrentSession().enableFetchProfile("batch-with-childs"); + getCurrentSession().setFlushMode(FlushMode.COMMIT); + fr.ifremer.adagio.core.dao.data.batch.CatchBatch catchBatch = catchBatchDao.load(Integer.valueOf(bean.getId())); + if (catchBatch == null) { + throw new DataRetrievalFailureException("Could not retrieve catch batch with id=" + bean.getId()); + } + + beanToEntity(bean, catchBatch, true); + catchBatchDao.update(catchBatch); + getCurrentSession().flush(); + + return bean; + } + + @Override + public List<SpeciesBatch> getAllRootSpeciesBatch(String fishingOperationId) { + + // Load batch tree + Integer catchBatchId = catchBatchDao.getIdByFishingOperationId(Integer.valueOf(fishingOperationId)); + fr.ifremer.adagio.core.dao.data.batch.CatchBatch catchBatch = catchBatchDao.loadFullTree(catchBatchId); + + List<SpeciesBatch> result = new ArrayList<SpeciesBatch>(); + + // Vrac / Species + SortingBatch vracSpeciesBatch = catchBatchDao.getSortingBatch(catchBatch.getChildBatchs(), + "pmfmId", enumeration.PMFM_ID_SORTED_UNSORTED, enumeration.QUALITATIVE_VRAC_ID, + "pmfmId", enumeration.PMFM_ID_SORTING_TYPE, enumeration.QUALITATIVE_ID_SORTING_TYPE_SPECIES); + for (Iterator<Batch> iterator = vracSpeciesBatch.getChildBatchs().iterator(); iterator.hasNext();) { + SortingBatch source = (SortingBatch) iterator.next(); + + // evict some special batches : Life (or Biota) and Inert + if (source.getReferenceTaxon() != null + && enumeration.REFERENCE_TAXON_ID_LIFE.equals(source.getReferenceTaxon().getId()) == false + && enumeration.REFERENCE_TAXON_ID_INERT.equals(source.getReferenceTaxon().getId()) == false) { + SpeciesBatch target = new SpeciesBatch(); + + entityToBean(source, target); + result.add(target); + } + } + + // Hors-Vrac / Species + SortingBatch horsVracSpeciesBatch = catchBatchDao.getSortingBatch(catchBatch.getChildBatchs(), + "pmfmId", enumeration.PMFM_ID_SORTED_UNSORTED, enumeration.QUALITATIVE_HORS_VRAC_ID, + "pmfmId", enumeration.PMFM_ID_SORTING_TYPE, enumeration.QUALITATIVE_ID_SORTING_TYPE_SPECIES); + for (Iterator<Batch> iterator = horsVracSpeciesBatch.getChildBatchs().iterator(); iterator.hasNext();) { + SortingBatch source = (SortingBatch) iterator.next(); + + SpeciesBatch target = new SpeciesBatch(); + + entityToBean(source, target); + result.add(target); + } + + return result; + } + + protected SpeciesBatch entityToBean(SortingBatch source, SpeciesBatch target) { + + target.setId(source.getId().toString()); + + // Individual count + target.setNumber(source.getIndividualCount()); + + // Convert database weight (and sampling ratio) into UI weight and sampleCategoryWeight + if (source.getWeight() != null && source.getWeightBeforeSampling() == null) { + target.setSampleCategoryWeight(source.getWeight()); + } + else { + target.setWeight(source.getWeight()); + target.setSampleCategoryWeight(source.getWeightBeforeSampling()); + } + + // Comments + target.setComment(source.getComments()); + + // Sample category type (only one is applied) + SortingMeasurement sm = null; + if (source.getSortingMeasurements().size() == 1) { + sm = source.getSortingMeasurements().iterator().next(); + } + else if (source.getReferenceTaxon() != null && source.getReferenceTaxon().getId() != null){ + sm = measurementHelper.getInheritedSortingMeasurement(source, enumeration.PMFM_ID_SORTED_UNSORTED); + } + if (sm != null) { + SampleCategoryEnum sampleCategory = referentialService.getSampleCategoryByPmfmId(sm.getPmfm().getId()); + if (sampleCategory != null) { + setSampleCategoryQualitative(target, sm.getPmfm().getId(), sm.getNumericalValue(), sm.getAlphanumericalValue(), sm.getQualitativeValue().getId()); + } + } + + // Species + Integer referenceTaxonId = source.getInheritedReferenceTaxonId(); + if (referenceTaxonId == null && source.getReferenceTaxon() != null) { + referenceTaxonId = source.getReferenceTaxon().getId(); + } + if (referenceTaxonId != null) { + // TODO : add cache on getSpeciesByReferenceTaxonId + Species species = referentialService.getSpeciesByReferenceTaxonId(referenceTaxonId); + target.setSpecies(species); + } + + if (target.getSampleCategoryType() != null && source.getChildBatchs().size() > 0) { + List<SpeciesBatch> targetChilds = Lists.newArrayList(); + for (Iterator<Batch> iterator = source.getChildBatchs().iterator(); iterator.hasNext();) { + SortingBatch sourceChild = (SortingBatch) iterator.next(); + SpeciesBatch targetChild = new SpeciesBatch(); + entityToBean(sourceChild, targetChild); + if (targetChild.getSampleCategoryValue() != null) { + targetChilds.add(targetChild); + targetChild.setParentBatch(target); + } + } + target.setChildBatchs(targetChilds); + } + + return target; + } + + @Override + public SpeciesBatch createSpeciesBatch(SpeciesBatch bean, + String parentBatchId) { + Preconditions.checkNotNull(bean); + Preconditions.checkArgument(bean.getId() == null); + Preconditions.checkNotNull(bean.getSpecies()); + Preconditions.checkNotNull(bean.getSpecies().getId()); + Preconditions.checkNotNull(bean.getFishingOperation()); + Preconditions.checkNotNull(bean.getFishingOperation().getId()); + + getCurrentSession().setFlushMode(FlushMode.COMMIT); + + // Load full batch tree + Integer catchBatchId = catchBatchDao.getIdByFishingOperationId(Integer.valueOf(bean.getFishingOperation().getId())); + fr.ifremer.adagio.core.dao.data.batch.CatchBatch catchBatch = catchBatchDao.loadFullTree(catchBatchId); + + SortingBatch batch = SortingBatch.Factory.newInstance(); + beanToEntity(bean, batch, parentBatchId, catchBatch, true); + batch = sortingBatchDao.create(batch); + + bean.setId(String.valueOf(batch.getId())); + + getCurrentSession().flush(); + + return bean; + } + + @Override + public SpeciesBatch saveSpeciesBatch(SpeciesBatch bean) { + Preconditions.checkNotNull(bean); + Preconditions.checkNotNull(bean.getId()); + + // Load full batch tree + Integer catchBatchId = catchBatchDao.getIdBySortingBatchId(Integer.valueOf(bean.getId())); + fr.ifremer.adagio.core.dao.data.batch.CatchBatch catchBatch = catchBatchDao.loadFullTree(catchBatchId); + + getCurrentSession().setFlushMode(FlushMode.COMMIT); + + SortingBatch batch = catchBatchDao.getSortingBatchById(catchBatch, Integer.valueOf(bean.getId())); + String parentBatchId = null; + if (bean.getParentBatch() != null) { + parentBatchId = bean.getParentBatch().getId(); + } + beanToEntity(bean, batch, parentBatchId, catchBatch, true); + sortingBatchDao.update(batch); + getCurrentSession().flush(); + + return bean; + } + + @Override + public void deleteSpeciesBatch(String id) { + Preconditions.checkNotNull(id); + + getCurrentSession().setFlushMode(FlushMode.COMMIT); + + catchBatchDao.removeWithChildren(Integer.valueOf(id)); + + getCurrentSession().flush(); + } + + public void deleteSpeciesSubBatch(String id) { + deleteSpeciesBatch(id); + } + + public void changeSpeciesBatchSpecies(String batchId, Species species) { + Preconditions.checkNotNull(batchId); + Preconditions.checkNotNull(species); + Preconditions.checkNotNull(species.getReferenceTaxonId()); + + if (log.isDebugEnabled()) { + log.debug("Changing species for batch id=" + batchId); + } + + int rowUpdated = queryUpdate("updateBatchSpecies", + "batchId", IntegerType.INSTANCE, Integer.valueOf(batchId), + "referenceTaxonId", IntegerType.INSTANCE, species.getReferenceTaxonId()); + Preconditions.checkArgument(rowUpdated == 1, "Unable to update operation, to be linked with catch batch."); + } + + public List<SpeciesBatchFrequency> getAllSpeciesBatchFrequency( + String speciesBatchId) { + List<SpeciesBatchFrequency> results = Lists.newArrayList(); + + Integer catchBatchId = catchBatchDao.getIdBySortingBatchId(Integer.valueOf(speciesBatchId)); + fr.ifremer.adagio.core.dao.data.batch.CatchBatch catchBatch = catchBatchDao.loadFullTree(catchBatchId); + + if (catchBatchId == null) { + return results; + } + + SortingBatch sortingBatch = catchBatchDao.getSortingBatchById(catchBatch, Integer.valueOf(speciesBatchId)); + + for (Iterator<Batch> iterator = sortingBatch.getChildBatchs().iterator(); iterator.hasNext();) { + SortingBatch source = (SortingBatch) iterator.next(); + SpeciesBatchFrequency target = new SpeciesBatchFrequency(); + + entityToBean(source, target); + results.add(target); + } + return results; + } + + protected void entityToBean(SortingBatch source, SpeciesBatchFrequency target) { + + target.setId(source.getId().toString()); + + target.setNumber(source.getIndividualCount()); + target.setWeight(source.getWeight()); + target.setComment(source.getComments()); + + // Length step category + if (source.getSortingMeasurements().size() == 1) { + SortingMeasurement sm = source.getSortingMeasurements().iterator().next(); + if (sm.getPmfm() != null && sm.getPmfm().getId() != null) { + Caracteristic lengthStepCaracteristic = referentialService.getCaracteristic(sm.getPmfm().getId()); + target.setLengthStepCaracteristic(lengthStepCaracteristic); + } + + // Length + target.setLengthStep(sm.getNumericalValue()); + } + } + + public List<SpeciesBatchFrequency> saveSpeciesBatchFrequency( + String speciesBatchId, List<SpeciesBatchFrequency> frequencies) { + Preconditions.checkNotNull(speciesBatchId); + Preconditions.checkNotNull(frequencies); + + if (frequencies.size() == 0) { + return frequencies; + } + getCurrentSession().setFlushMode(FlushMode.COMMIT); + + Integer catchBatchId = catchBatchDao.getIdBySortingBatchId(Integer.valueOf(speciesBatchId)); + fr.ifremer.adagio.core.dao.data.batch.CatchBatch catchBatch = catchBatchDao.loadFullTree(catchBatchId); + + if (catchBatch == null) { + return frequencies; + } + + // Retrieve parent + SortingBatch parentBatch = catchBatchDao.getSortingBatchById(catchBatch, Integer.valueOf(speciesBatchId)); + + // Remember child ids, to remove unchanged item (see at bottom in this method) + List<Integer> notUpdatedChildIds = Lists.newArrayList(); + for (Iterator<Batch> iterator = parentBatch.getChildBatchs().iterator(); iterator.hasNext();) { + SortingBatch sortingBatch = (SortingBatch) iterator.next(); + notUpdatedChildIds.add(sortingBatch.getId()); + } + + short rankOrder = 0; + String pmfmId = null; + List<SortingBatch> batchsToUpdate = Lists.newArrayList(); + for (SpeciesBatchFrequency source : frequencies) { + rankOrder++; + + // Check that all frequencies have the same length PMFM + if (pmfmId == null) { + source.getLengthStepCaracteristic().getId(); + } else if (!pmfmId.equals(source.getLengthStepCaracteristic().getId())) { + throw new DataIntegrityViolationException("Batch frequencies under one Speciesbatch must have all the same lengthStepCaracteristic"); + } + + // Not existing batch + SortingBatch target = null; + if (source.getId() == null) { + target = SortingBatch.Factory.newInstance(); + + // Fill the sorting batch from the source + beanToEntity(source, target, parentBatch, rankOrder, true); + + // Create the targeted batch, then update the source id + sortingBatchDao.create(target); + source.setId(target.getId().toString()); + } + + // Existing batch + else { + target = sortingBatchDao.load(Integer.valueOf(source.getId())); + + // Fill the sorting batch from the source + beanToEntity(source, target, parentBatch, rankOrder, true); + + // Add the batch into a list (will be update later, using this list) + batchsToUpdate.add(target); + + notUpdatedChildIds.remove(target.getId()); + } + } + + // If some batchs need to be update, do it + if (batchsToUpdate.size() > 0) { + sortingBatchDao.update(batchsToUpdate); + } + + if (notUpdatedChildIds.size() > 0) { + for (Iterator<Integer> iterator = notUpdatedChildIds.iterator(); iterator.hasNext();) { + Integer batchId = iterator.next(); + catchBatchDao.removeWithChildren(batchId); + } + } + + getCurrentSession().flush(); + + return frequencies; + } + + // ------------------------------------------------------------------------// + // -- Internal methods --// + // ------------------------------------------------------------------------// + + protected void validate(Collection<Batch> batchs, List<CatchBatchValidationError> errors, int treeLevel) { + + List<Integer> expectedPmfms = null; + boolean expectedReferenceTaxon = false; + // First tree level : should have pmfm SORTED (Vrac, Hors Vrac, Non trié) + if (treeLevel == 1) { + expectedPmfms = Lists.newArrayList(enumeration.PMFM_ID_SORTED_UNSORTED); + } + // Second tree level : should have pmfm SORTING_TYPE (Species, Benthos...) + else if (treeLevel == 2) { + expectedPmfms = Lists.newArrayList(enumeration.PMFM_ID_SORTING_TYPE); + } + else if (treeLevel == 3) { + expectedReferenceTaxon = true; + } + else if (treeLevel > 3) { + expectedPmfms = referentialService.getSampleCategoryIds(); + expectedPmfms.remove(enumeration.PMFM_ID_SORTED_UNSORTED); + } + + // First level : should be only PMFM=SORTED + for (Iterator<Batch> iterator = batchs.iterator(); iterator.hasNext();) { + SortingBatch batch = (SortingBatch) iterator.next(); + boolean batchHasError = false; + + // For all sorting measurements + if (batch.getSortingMeasurements() != null && batch.getSortingMeasurements().size() > 0) { + for (Iterator<SortingMeasurement> iterator2 = batch.getSortingMeasurements().iterator(); iterator2.hasNext();) { + SortingMeasurement sm = iterator2.next(); + Integer pmfmId = sm.getPmfm().getId(); + if (expectedReferenceTaxon) { + CatchBatchValidationError error = new CatchBatchValidationError( + "tutti.persistence.batch.validation.onlyTaxonButPmfmFound", + _("tutti.persistence.batch.validation.onlyTaxonButPmfmFound", batch.getId(), pmfmId), + CatchBatchValidationError.GRAVITY_ERROR); + errors.add(error); + } + else if (expectedPmfms.contains(pmfmId) == false) { + if (sm.getNumericalValue() == null || batch.getChildBatchs().size() > 0) { + batchHasError = true; + CatchBatchValidationError error = new CatchBatchValidationError( + "tutti.persistence.batch.validation.pmfmNotFound", + _("tutti.persistence.batch.validation.pmfmNotFound", + batch.getId(), Arrays.toString(expectedPmfms.toArray()), pmfmId), + CatchBatchValidationError.GRAVITY_ERROR); + errors.add(error); + } + } + } + } + else if (expectedPmfms != null && expectedPmfms.size() > 0){ + batchHasError = true; + CatchBatchValidationError error = new CatchBatchValidationError( + "tutti.persistence.batch.validation.pmfmNotFound", + _("tutti.persistence.batch.validation.pmfmNotFound", + batch.getId(), Arrays.toString(expectedPmfms.toArray()), "null"), + CatchBatchValidationError.GRAVITY_ERROR); + errors.add(error); + } + + if (!batchHasError && expectedReferenceTaxon == true && batch.getReferenceTaxon() == null) { + CatchBatchValidationError error = new CatchBatchValidationError( + "tutti.persistence.batch.validation.referenceTaxonNotFound", + _("tutti.persistence.batch.validation.referenceTaxonNotFound", batch.getId()), + CatchBatchValidationError.GRAVITY_ERROR); + errors.add(error); + } + + if (!batchHasError) { + validate(batch.getChildBatchs(), errors, treeLevel+1); + } + } + } + + protected void beanToEntity(SpeciesBatch source, + SortingBatch target, + String parentBatchId, + fr.ifremer.adagio.core.dao.data.batch.CatchBatch catchBatch, + boolean copyIfNull) { + Preconditions.checkNotNull(source.getFishingOperation()); + Preconditions.checkNotNull(source.getFishingOperation().getId()); + + // Retrieve recorder department + Integer recorderDepartmentId = getRecorderDepartmentId(); + + // Create lists to store all updates, then remove not updated items + Set<QuantificationMeasurement> notChangedQuantificationMeasurements = new HashSet<QuantificationMeasurement>(); + if (target.getQuantificationMeasurements() != null) { + notChangedQuantificationMeasurements.addAll(target.getQuantificationMeasurements()); + } + Set<SortingMeasurement> notChangedSortingMeasurements = new HashSet<SortingMeasurement>(); + if (target.getSortingMeasurements() != null) { + notChangedSortingMeasurements.addAll(target.getSortingMeasurements()); + } + + // If parent and root need to be set + if (target.getId() == null + || target.getRootBatch() == null + || (target.getParentBatch() != null && !target.getParentBatch().getId().toString().equals(parentBatchId))) { + setBatchParents(source, target, parentBatchId, catchBatch); + } + + // RankOrder (initialize once, at creation) + if (target.getRankOrder() == null) { + // Start rank order at 3, because of special batches 'Biota' and 'Inert' + short rankOrder = (short) 3; + if (source.getParentBatch() != null && source.getParentBatch().getChildBatchs() != null) { + // TODO BL : vérifier cela (est-ce que l'item est ajouté à son père AVANT d'être passé au service ?) + rankOrder += (short) source.getParentBatch().getChildBatchs().size(); + } + target.setRankOrder(rankOrder); + } + + // Force subgroup count to '1', as Allegro + target.setSubgroupCount(1f); + + // Weight or SampleCategoryWeight + if (copyIfNull && source.getWeight() == null && source.getSampleCategoryWeight() == null) { + // Nothing to do : will be removed later, using notChangedSortingMeasurements + } else if (source.getSampleCategoryWeight() != null && source.getWeight() == null) { + QuantificationMeasurement quantificationMeasurement = measurementHelper.setQuantificationMeasurement(target, + enumeration.PMFM_ID_WEIGHT_MEASURED, recorderDepartmentId, source.getSampleCategoryWeight(), true); + notChangedQuantificationMeasurements.remove(quantificationMeasurement); + } else if (source.getWeight() != null && source.getSampleCategoryWeight() == null) { + QuantificationMeasurement quantificationMeasurement = measurementHelper.setQuantificationMeasurement(target, + enumeration.PMFM_ID_WEIGHT_MEASURED, recorderDepartmentId, source.getWeight(), true); + notChangedQuantificationMeasurements.remove(quantificationMeasurement); + } + + // Sampling Ratio + if (copyIfNull && (source.getSampleCategoryWeight() == null || source.getWeight() == null)) { + target.setSamplingRatio(null); + target.setSamplingRatioText(null); + } else if (source.getSampleCategoryWeight() != null && source.getWeight() != null) { + String samplingRatioText = source.getWeight() + "/" + source.getSampleCategoryWeight(); + samplingRatioText = samplingRatioText.replaceAll(",", "."); + target.setSamplingRatioText(samplingRatioText); + target.setSamplingRatio(source.getWeight() / source.getSampleCategoryWeight()); + QuantificationMeasurement quantificationMeasurement = measurementHelper.setQuantificationMeasurement(target, + enumeration.PMFM_ID_WEIGHT_MEASURED, recorderDepartmentId, source.getWeight(), true); + notChangedQuantificationMeasurements.remove(quantificationMeasurement); + } + + // Sorting measurement + if (copyIfNull && (source.getSampleCategoryType() == null || source.getSampleCategoryValue() == null)) { + // Nothing to do : will be removed later, using notChangedSortingMeasurements + } else if (source.getSampleCategoryType() != null && source.getSampleCategoryValue() != null) { + Integer pmfmId = measurementHelper.sampleCategory2PmfmId(source.getSampleCategoryType()); + // Do not store sorting measurement if pmfm = SORTED (already store in an ancestor batch) + if (!pmfmId.equals(enumeration.PMFM_ID_SORTED_UNSORTED)) { + SortingMeasurement sortingMeasurement = measurementHelper.setSortingMeasurement(target, recorderDepartmentId, + source.getSampleCategoryType(), source.getSampleCategoryValue()); + notChangedSortingMeasurements.remove(sortingMeasurement); + } + } + + // Individual count + if (copyIfNull && source.getNumber() == null) { + target.setIndividualCount(null); + } else if (source.getNumber() != null) { + target.setIndividualCount(source.getNumber()); + } + + // Species + if (copyIfNull && (source.getSpecies() == null || parentBatchId != null)) { + target.setReferenceTaxon(null); + } else if (source.getSpecies() != null && parentBatchId == null) { + ReferenceTaxon referenceTaxon = load(ReferenceTaxonImpl.class, source.getSpecies().getReferenceTaxonId()); + target.setReferenceTaxon(referenceTaxon); + } + + // QualityFlag + if (source.isSpeciesToConfirm()) { + target.setQualityFlag(load(QualityFlagImpl.class, enumeration.QUALITY_FLAG_CODE_DOUBTFUL)); + } else { + target.setQualityFlag(load(QualityFlagImpl.class, enumeration.QUALITY_FLAG_CODE_NOT_QUALIFIED)); + } + + // Comments + if (copyIfNull && source.getComment() == null) { + target.setComments(null); + } else if (source.getComment() != null) { + target.setComments(source.getComment()); + } + + // Exhaustive inventory (always true under a species batch) + target.setExhaustiveInventory(true); + + // Removed not changed measurements (in sorting and quantification measurement lists) + if (target.getQuantificationMeasurements() != null && notChangedQuantificationMeasurements.size() > 0) { + for (QuantificationMeasurement qm : notChangedQuantificationMeasurements) { + target.getQuantificationMeasurements().remove(qm); + } + } + if (target.getSortingMeasurements() != null && notChangedSortingMeasurements.size() > 0) { + for (SortingMeasurement sm : notChangedSortingMeasurements) { + target.getSortingMeasurements().remove(sm); + } + } + } + + public void setBatchParents(SpeciesBatch source, SortingBatch target, String parentBatchIdStr, + fr.ifremer.adagio.core.dao.data.batch.CatchBatch catchBatch) { + + Preconditions.checkNotNull(target); + Preconditions.checkNotNull(source.getFishingOperation()); + Preconditions.checkNotNull(source.getFishingOperation().getId()); + + // Load existing parent and root + SortingBatch parentBatch = null; + if (parentBatchIdStr != null) { + parentBatch = catchBatchDao.getSortingBatchById(catchBatch, Integer.valueOf(parentBatchIdStr)); + } + + // Or retrieve parent batch, from pmfm id + else { + // Retrieve category type + Integer pmfmId = measurementHelper.sampleCategory2PmfmId(source.getSampleCategoryType()); + if (pmfmId == null || !pmfmId.equals(enumeration.PMFM_ID_SORTED_UNSORTED)) { + throw new DataIntegrityViolationException(MessageFormat.format( + "A species batch with no parent should have a sampleCategoryType {0} (PMFM.ID={1})", + SampleCategoryEnum.sortedUnsorted.name(), + enumeration.PMFM_ID_SORTED_UNSORTED)); + } + Integer qualitativeValueId = convertSampleCategoryValueIntoQualitativeId(source.getSampleCategoryValue()); + + parentBatch = catchBatchDao.getSortingBatch(catchBatch.getChildBatchs(), + "pmfmId", pmfmId, qualitativeValueId, + "pmfmId", enumeration.PMFM_ID_SORTING_TYPE, enumeration.QUALITATIVE_ID_SORTING_TYPE_SPECIES); + + // Parent Batch + target.setParentBatch(parentBatch); + } + + + if (parentBatch == null) { + throw new DataIntegrityViolationException( + "Could not retrieve parent batch, for a given speciesBatch : invalid batch tree structure. Please make sure CatchBatch has been saved before to create a SpeciesBatch."); + } + + // Parent Batch + target.setParentBatch(parentBatch); + target.setRootBatch(catchBatch); + } + + Integer convertSampleCategoryValueIntoQualitativeId(Serializable value) { + if (value == null) + return null; + Integer qualitativeValueId = null; + if (value instanceof CaracteristicQualitativeValue) { + CaracteristicQualitativeValue cqValue = (CaracteristicQualitativeValue) value; + qualitativeValueId = Integer.valueOf(cqValue.getId()); + } else if (value instanceof String) { + qualitativeValueId = Integer.valueOf((String) value); + } + return qualitativeValueId; + } + + protected void setSampleCategoryQualitative(SpeciesBatch target, Integer pmfmId, Float numericalvalue, String alphanumericalValue, + Integer qualitativeValueId) { + // skip if null or corresponding to the SORTING_TYPE PMFM (Expèce, Benthos, Plancton, etc.) + if (pmfmId == null || pmfmId.equals(enumeration.PMFM_ID_SORTING_TYPE)) { + return; + } + + SampleCategoryEnum sampleCategory = referentialService.getSampleCategoryByPmfmId(pmfmId); + Preconditions.checkNotNull(sampleCategory, "Unable to find corresponding SampleCategoryEnum for PMFM.ID : " + pmfmId); + + target.setSampleCategoryType(sampleCategory); + if (numericalvalue != null) { + target.setSampleCategoryValue(numericalvalue); + return; + } + if (alphanumericalValue != null) { + target.setSampleCategoryValue(alphanumericalValue); + return; + } + + Caracteristic caracteristic = referentialService.getCaracteristic(pmfmId); + if (caracteristic == null || caracteristic.getCaracteristicType() != CaracteristicType.QUALITATIVE) { + return; + } + CaracteristicQualitativeValue value = null; + for (CaracteristicQualitativeValue qv : caracteristic.getQualitativeValue()) { + if (qualitativeValueId == Integer.parseInt(qv.getId())) { + value = qv; + break; + } + } + target.setSampleCategoryValue(value); + } + + protected void beanToEntity(SpeciesBatchFrequency source, SortingBatch target, SortingBatch parentBatch, short rankOrder, boolean copyIfNull) { + Preconditions.checkNotNull(source.getBatch()); + Preconditions.checkNotNull(source.getBatch().getId()); + + // Retrieve recorder department + Integer recorderDepartmentId = getRecorderDepartmentId(); + + // Create lists to store all updates, then remove not updated items + Set<QuantificationMeasurement> notChangedQuantificationMeasurements = new HashSet<QuantificationMeasurement>(); + if (target.getQuantificationMeasurements() != null) { + notChangedQuantificationMeasurements.addAll(target.getQuantificationMeasurements()); + } + Set<SortingMeasurement> notChangedSortingMeasurements = new HashSet<SortingMeasurement>(); + if (target.getSortingMeasurements() != null) { + notChangedSortingMeasurements.addAll(target.getSortingMeasurements()); + } + + // If parent and root need to be set + if (target.getId() == null + || target.getRootBatch() == null + || (target.getParentBatch() != null && !target.getParentBatch().getId().equals(parentBatch.getId()))) { + + target.setParentBatch(parentBatch); + target.setRootBatch(parentBatch.getRootBatch()); + } + + // RankOrder + target.setRankOrder(rankOrder); + + // Weight or SampleCategoryWeight + if (copyIfNull && source.getWeight() == null) { + // Nothing to do : will be removed later, using notChangedSortingMeasurements + } else if (source.getWeight() != null) { + QuantificationMeasurement quantificationMeasurement = measurementHelper.setQuantificationMeasurement(target, + enumeration.PMFM_ID_WEIGHT_MEASURED, recorderDepartmentId, source.getWeight(), true); + notChangedQuantificationMeasurements.remove(quantificationMeasurement); + } + + // Sorting measurement + if (copyIfNull && (source.getLengthStepCaracteristic() == null || source.getLengthStep() == null)) { + // Nothing to do : will be removed later, using notChangedSortingMeasurements + } else if (source.getLengthStepCaracteristic() != null && source.getLengthStep() != null) { + Integer pmfmId = Integer.valueOf(source.getLengthStepCaracteristic().getId()); + SortingMeasurement sortingMeasurement = measurementHelper.setSortingMeasurement(target, recorderDepartmentId, pmfmId, + source.getLengthStep()); + notChangedSortingMeasurements.remove(sortingMeasurement); + } + + // Individual count + if (copyIfNull && source.getNumber() == null) { + target.setIndividualCount(null); + } else if (source.getNumber() != null) { + target.setIndividualCount(source.getNumber()); + } + + // Species + target.setReferenceTaxon(null); + + // QualityFlag + target.setQualityFlag(parentBatch.getQualityFlag()); + + // Comments + if (copyIfNull && source.getComment() == null) { + target.setComments(null); + } else if (source.getComment() != null) { + target.setComments(source.getComment()); + } + + // Exhaustive inventory (always true under a species batch) + target.setExhaustiveInventory(true); + + // Removed not changed measurements (in sorting and quantification measurement lists) + if (target.getQuantificationMeasurements() != null && notChangedQuantificationMeasurements.size() > 0) { + for (QuantificationMeasurement qm : notChangedQuantificationMeasurements) { + target.getQuantificationMeasurements().remove(qm); + } + } + if (target.getSortingMeasurements() != null && notChangedSortingMeasurements.size() > 0) { + for (SortingMeasurement sm : notChangedSortingMeasurements) { + target.getSortingMeasurements().remove(sm); + } + } + } + + protected UIWeight convertDatabase2UI(Float weight, Float samplingRatio, String samplingRatioText) { + UIWeight result = new UIWeight(); + + // Weight & sampleCategory Weight + if (samplingRatio == null) { + result.sampleCategoryWeight = weight; + } else if (weight != null) { + String startStr = weight.toString().replace(',', '.') + "/"; + if (samplingRatioText != null && samplingRatioText.startsWith(startStr)) { + String weightStr = samplingRatioText.substring(startStr.length()); + if (weightStr != null && !weightStr.isEmpty()) { + result.sampleCategoryWeight = Float.parseFloat(weightStr); + result.weight = weight; + } + } else { + result.sampleCategoryWeight = weight; + } + } + return result; + } + + static class UIWeight { + Float sampleCategoryWeight = null; + + Float weight = null; + } + + protected void beanToEntity(CatchBatch source, + fr.ifremer.adagio.core.dao.data.batch.CatchBatch target, + boolean copyIfNull) { + Preconditions.checkNotNull(source.getFishingOperation()); + Preconditions.checkNotNull(source.getFishingOperation().getId()); + + // Retrieve recorder department + Integer recorderDepartmentId = getRecorderDepartmentId(); + + // First initialization (when created) + Integer fishingOperationId = Integer.valueOf(source.getFishingOperation().getId()); + target.setFishingOperation(load(FishingOperationImpl.class, fishingOperationId)); + + target.setQualityFlag(load(QualityFlagImpl.class, enumeration.QUALITY_FLAG_CODE_NOT_QUALIFIED)); + target.setRankOrder((short) 1); + target.setSynchronizationStatus(SynchronizationStatus.DIRTY.getValue()); + + // Create lists to store all updates, then remove not updated items + Set<QuantificationMeasurement> notChangedQuantificationMeasurements = new HashSet<QuantificationMeasurement>(); + if (target.getQuantificationMeasurements() != null) { + notChangedQuantificationMeasurements.addAll(target.getQuantificationMeasurements()); + } + + // Total Weight + if (copyIfNull && source.getCatchTotalWeight() == null) { + // Nothing to do : will be removed later, using notChangedQuantificationMeasurements + } else if (source.getCatchTotalWeight() != null) { + QuantificationMeasurement quantificationMeasurement = measurementHelper.setQuantificationMeasurement(target, + enumeration.PMFM_ID_WEIGHT_MEASURED, recorderDepartmentId, source.getCatchTotalWeight(), true); + notChangedQuantificationMeasurements.remove(quantificationMeasurement); + } + + // Removed not changed measurements (in sorting and quantification measurement lists) + if (target.getQuantificationMeasurements() != null && notChangedQuantificationMeasurements.size() > 0) { + for (QuantificationMeasurement qm : notChangedQuantificationMeasurements) { + target.getQuantificationMeasurements().remove(qm); + } + } + Map<Integer, SortingBatch> catchBatchChilds = getChildsMap(target, enumeration.PMFM_ID_SORTED_UNSORTED); + + // ----------------------------------------------------------------------------- + // Sorted Vrac + // ----------------------------------------------------------------------------- + { + SortingBatch batch = catchBatchChilds.get(enumeration.QUALITATIVE_VRAC_ID); + if (batch == null) { + batch = SortingBatch.Factory.newInstance(); + target.getChildBatchs().add(batch); + } + beanToEntitySortingBatch(target, target, batch, recorderDepartmentId, + enumeration.PMFM_ID_SORTED_UNSORTED, enumeration.QUALITATIVE_VRAC_ID, + source.getCatchTotalSortedCarousselWeight(), source.getCatchTotalSortedTremisWeight(), + copyIfNull); + batch.setRankOrder((short) 1); + + // Manage childs : + { + Map<Integer, SortingBatch> batchChilds = getChildsMap(batch, enumeration.PMFM_ID_SORTING_TYPE); + + // ----------------------------------------------------------------------------- + // Sorted Vrac / Species + // ----------------------------------------------------------------------------- + SortingBatch speciesBatch = batchChilds.get(enumeration.QUALITATIVE_ID_SORTING_TYPE_SPECIES); + if (speciesBatch == null) { + speciesBatch = SortingBatch.Factory.newInstance(); + if (batch.getChildBatchs() == null) { + batch.setChildBatchs(Lists.newArrayList((Batch) speciesBatch)); + } else { + batch.getChildBatchs().add(speciesBatch); + } + } + beanToEntitySortingBatch(target, batch, speciesBatch, recorderDepartmentId, + enumeration.PMFM_ID_SORTING_TYPE, enumeration.QUALITATIVE_ID_SORTING_TYPE_SPECIES, + source.getSpeciesTotalSampleSortedWeight(), source.getSpeciesTotalSortedWeight(), + copyIfNull); + speciesBatch.setRankOrder((short) 1); + + { + + // ----------------------------------------------------------------------------- + // Sorted Vrac / Species / Alive not itemized + // ----------------------------------------------------------------------------- + SortingBatch aliveNotItemizedBatch = catchBatchDao.getSortingBatch(speciesBatch.getChildBatchs(), "referenceTaxonId", enumeration.REFERENCE_TAXON_ID_LIFE); + if (aliveNotItemizedBatch == null) { + aliveNotItemizedBatch = SortingBatch.Factory.newInstance(); + if (speciesBatch.getChildBatchs() == null) { + speciesBatch.setChildBatchs(Lists.newArrayList((Batch) aliveNotItemizedBatch)); + } else { + speciesBatch.getChildBatchs().add(aliveNotItemizedBatch); + } + } + beanToEntityReferenceTaxonBatch(target, speciesBatch, aliveNotItemizedBatch, recorderDepartmentId, + enumeration.REFERENCE_TAXON_ID_LIFE, + source.getSpeciesTotalLivingNotItemizedWeight(), null, + copyIfNull); + aliveNotItemizedBatch.setRankOrder((short) 1); + + // ----------------------------------------------------------------------------- + // Sorted Vrac / Species / Inert (not alive) + // ----------------------------------------------------------------------------- + SortingBatch inertBatch = catchBatchDao.getSortingBatch(speciesBatch.getChildBatchs(), "referenceTaxonId", enumeration.REFERENCE_TAXON_ID_INERT); + if (inertBatch == null) { + inertBatch = SortingBatch.Factory.newInstance(); + speciesBatch.getChildBatchs().add(inertBatch); + } + beanToEntityReferenceTaxonBatch(target, speciesBatch, inertBatch, recorderDepartmentId, + enumeration.REFERENCE_TAXON_ID_INERT, + source.getSpeciesTotalInertWeight(), null, + copyIfNull); + inertBatch.setRankOrder((short) 2); + } + } + // TODO BL : benthos, plancton, macro déchet... + } + + // ----------------------------------------------------------------------------- + // Sorted Hors Vrac + // ----------------------------------------------------------------------------- + { + SortingBatch batch = catchBatchChilds.get(enumeration.QUALITATIVE_HORS_VRAC_ID); + if (batch == null) { + batch = SortingBatch.Factory.newInstance(); + target.getChildBatchs().add(batch); + } + beanToEntitySortingBatch(target, target, batch, recorderDepartmentId, + enumeration.PMFM_ID_SORTED_UNSORTED, enumeration.QUALITATIVE_HORS_VRAC_ID, + source.getCatchTotalUnsortedWeight(), null, + copyIfNull); + batch.setRankOrder((short) 2); + + // Manage childs : + { + Map<Integer, SortingBatch> batchChilds = getChildsMap(batch, enumeration.PMFM_ID_SORTING_TYPE); + + // Species : + SortingBatch speciesBatch = batchChilds.get(enumeration.QUALITATIVE_ID_SORTING_TYPE_SPECIES); + if (speciesBatch == null) { + speciesBatch = SortingBatch.Factory.newInstance(); + if (batch.getChildBatchs() == null) { + batch.setChildBatchs(Lists.newArrayList((Batch) speciesBatch)); + } else { + batch.getChildBatchs().add(speciesBatch); + } + } + beanToEntitySortingBatch(target, batch, speciesBatch, recorderDepartmentId, + enumeration.PMFM_ID_SORTING_TYPE, enumeration.QUALITATIVE_ID_SORTING_TYPE_SPECIES, + source.getSpeciesTotalUnsortedWeight(), null, + copyIfNull); + speciesBatch.setRankOrder((short) 1); + } + + // TODO BL : benthos, plancton, macro déchet... + } + + // ----------------------------------------------------------------------------- + // Unsorted (=rejected) + // ----------------------------------------------------------------------------- + // Unsorted : + SortingBatch unsortedBatch = catchBatchChilds.get(enumeration.QUALITATIVE_UNSORTED_ID); + if (unsortedBatch == null) { + unsortedBatch = SortingBatch.Factory.newInstance(); + target.getChildBatchs().add(unsortedBatch); + } + beanToEntitySortingBatch(target, target, unsortedBatch, recorderDepartmentId, + enumeration.PMFM_ID_SORTED_UNSORTED, enumeration.QUALITATIVE_UNSORTED_ID, + source.getCatchTotalRejectedWeight(), null, + copyIfNull); + unsortedBatch.setRankOrder((short) 3); + + } + + protected Map<Integer, SortingBatch> getChildsMap(Batch parentBatch, Integer pmfmId) { + Map<Integer, SortingBatch> batchByQualitativeValueId = new HashMap<Integer, SortingBatch>(); + if (parentBatch.getChildBatchs() == null) { + return batchByQualitativeValueId; + } + for (Batch childBatch : parentBatch.getChildBatchs()) { + SortingBatch childSortingBatch = (SortingBatch) childBatch; + SortingMeasurement sm = measurementHelper.getSortingMeasurement((SortingBatch) childBatch, pmfmId, null, false); + if (sm != null && sm.getQualitativeValue() != null && sm.getQualitativeValue().getId() != null) { + batchByQualitativeValueId.put(sm.getQualitativeValue().getId(), childSortingBatch); + } + } + return batchByQualitativeValueId; + } + + /** + * Retrieve child batchs if species is "Life" or "No life" + * (need to retrieve: speciesTotalLivingNotItemizedWeight and speciesTotalInertWeight) + * + * @param parentBatch + * @return + */ + protected Map<Integer, SortingBatch> getChildAliveNotSortedOrInert(Batch parentBatch) { + Map<Integer, SortingBatch> batchByQualitativeValueId = new HashMap<Integer, SortingBatch>(); + if (parentBatch.getChildBatchs() == null) { + return batchByQualitativeValueId; + } + for (Batch childBatch : parentBatch.getChildBatchs()) { + SortingBatch childSortingBatch = (SortingBatch) childBatch; + if (childSortingBatch.getReferenceTaxon() != null && childSortingBatch.getId().intValue() < 0) { + if (enumeration.REFERENCE_TAXON_ID_LIFE.equals(childSortingBatch.getId())) { + batchByQualitativeValueId.put(enumeration.REFERENCE_TAXON_ID_LIFE, childSortingBatch); + } else if (enumeration.REFERENCE_TAXON_ID_LIFE.equals(childSortingBatch.getId())) { + batchByQualitativeValueId.put(enumeration.REFERENCE_TAXON_ID_LIFE, childSortingBatch); + } + } + } + return batchByQualitativeValueId; + } + + protected void beanToEntitySortingBatch( + fr.ifremer.adagio.core.dao.data.batch.CatchBatch rootBatch, + fr.ifremer.adagio.core.dao.data.batch.Batch parentBatch, + fr.ifremer.adagio.core.dao.data.batch.SortingBatch target, + Integer recorderDepartmentId, + Integer sortingPmfmId, + Integer sortingQualitativeValueId, + Float weight, + Float sampleWeight, + boolean copyIfNull) { + + // Create lists to store all updates, then remove not updated items + Set<QuantificationMeasurement> notChangedQuantificationMeasurements = new HashSet<QuantificationMeasurement>(); + if (target.getQuantificationMeasurements() != null) { + notChangedQuantificationMeasurements.addAll(target.getQuantificationMeasurements()); + } + Set<SortingMeasurement> notChangedSortingMeasurements = new HashSet<SortingMeasurement>(); + if (target.getSortingMeasurements() != null) { + notChangedSortingMeasurements.addAll(target.getSortingMeasurements()); + } + + // Some mandatory properties : + target.setQualityFlag(load(QualityFlagImpl.class, enumeration.QUALITY_FLAG_CODE_NOT_QUALIFIED)); + target.setRootBatch(rootBatch); + target.setParentBatch(parentBatch); + target.setExhaustiveInventory(true); + + // No taxon or taxon group + target.setReferenceTaxon(null); + target.setTaxonGroup(null); + + // Sorting measurement + if (copyIfNull && (sortingPmfmId == null || sortingQualitativeValueId == null)) { + // Nothing to do : will be removed later, using notChangedSortingMeasurements + } else if (sortingPmfmId != null && sortingQualitativeValueId != null) { + SortingMeasurement sm = measurementHelper.setSortingMeasurement(target, recorderDepartmentId, sortingPmfmId, sortingQualitativeValueId); + notChangedSortingMeasurements.remove(sm); + } + + // Sampling Ratio + if (copyIfNull && (sampleWeight == null || weight == null)) { + target.setSamplingRatio(null); + target.setSamplingRatioText(null); + } else if (sampleWeight != null && weight != null) { + String samplingRatioText = weight + "/" + sampleWeight; + samplingRatioText = samplingRatioText.replaceAll(",", "."); + target.setSamplingRatioText(samplingRatioText); + target.setSamplingRatio(weight / sampleWeight); + } + + // Weight + if (copyIfNull && (sampleWeight == null && weight == null)) { + // Nothing to do : will be removed later, using notChangedQuantificationMeasurements + } else if (sampleWeight != null || weight != null) { + Float batchReferenceWeight = weight; + if (batchReferenceWeight == null) { + batchReferenceWeight = sampleWeight; + } + QuantificationMeasurement quantificationMeasurement = measurementHelper.setQuantificationMeasurement(target, + enumeration.PMFM_ID_WEIGHT_MEASURED, recorderDepartmentId, batchReferenceWeight, true); + notChangedQuantificationMeasurements.remove(quantificationMeasurement); + } + + // Removed not changed measurements (in sorting and quantification measurement lists) + if (target.getQuantificationMeasurements() != null && notChangedQuantificationMeasurements.size() > 0) { + for (QuantificationMeasurement qm : notChangedQuantificationMeasurements) { + target.getQuantificationMeasurements().remove(qm); + } + } + if (target.getSortingMeasurements() != null && notChangedSortingMeasurements.size() > 0) { + for (SortingMeasurement sm : notChangedSortingMeasurements) { + target.getSortingMeasurements().remove(sm); + } + } + } + + protected void beanToEntityReferenceTaxonBatch( + fr.ifremer.adagio.core.dao.data.batch.CatchBatch rootBatch, + fr.ifremer.adagio.core.dao.data.batch.Batch parentBatch, + fr.ifremer.adagio.core.dao.data.batch.SortingBatch target, + Integer recorderDepartmentId, + Integer referenceTaxonId, + Float weight, + Float sampleWeight, + boolean copyIfNull) { + + // Create lists to store all updates, then remove not updated items + Set<QuantificationMeasurement> notChangedQuantificationMeasurements = new HashSet<QuantificationMeasurement>(); + if (target.getQuantificationMeasurements() != null) { + notChangedQuantificationMeasurements.addAll(target.getQuantificationMeasurements()); + } + Set<SortingMeasurement> notChangedSortingMeasurements = new HashSet<SortingMeasurement>(); + if (target.getSortingMeasurements() != null) { + notChangedSortingMeasurements.addAll(target.getSortingMeasurements()); + } + + // Some mandatory properties : + target.setQualityFlag(load(QualityFlagImpl.class, enumeration.QUALITY_FLAG_CODE_NOT_QUALIFIED)); + target.setRootBatch(rootBatch); + target.setParentBatch(parentBatch); + target.setExhaustiveInventory(true); + + // Reference taxon + target.setReferenceTaxon(load(ReferenceTaxonImpl.class, referenceTaxonId)); + target.setTaxonGroup(null); + + // Sampling Ratio + if (copyIfNull && (sampleWeight == null || weight == null)) { + target.setSamplingRatio(null); + target.setSamplingRatioText(null); + } else if (sampleWeight != null && weight != null) { + String samplingRatioText = weight + "/" + sampleWeight; + samplingRatioText = samplingRatioText.replaceAll(",", "."); + target.setSamplingRatioText(samplingRatioText); + target.setSamplingRatio(weight / sampleWeight); + } + + // Weight + if (copyIfNull && (sampleWeight == null && weight == null)) { + // Nothing to do : will be removed later, using notChangedQuantificationMeasurements + } else if (sampleWeight != null || weight != null) { + Float batchReferenceWeight = weight; + if (batchReferenceWeight == null) { + batchReferenceWeight = sampleWeight; + } + QuantificationMeasurement quantificationMeasurement = measurementHelper.setQuantificationMeasurement(target, + enumeration.PMFM_ID_WEIGHT_MEASURED, recorderDepartmentId, batchReferenceWeight, true); + notChangedQuantificationMeasurements.remove(quantificationMeasurement); + } + + // Removed not changed measurements (in sorting and quantification measurement lists) + if (target.getQuantificationMeasurements() != null && notChangedQuantificationMeasurements.size() > 0) { + for (QuantificationMeasurement qm : notChangedQuantificationMeasurements) { + target.getQuantificationMeasurements().remove(qm); + } + } + if (target.getSortingMeasurements() != null && notChangedSortingMeasurements.size() > 0) { + for (SortingMeasurement sm : notChangedSortingMeasurements) { + target.getSortingMeasurements().remove(sm); + } + } + } + + protected Integer getRecorderDepartmentId() { + // TODO BL : voir si on peut récupérer le departement (du 1er saisisseur ?) + return enumeration.DEPARTMENT_ID_UNKNOWN_RECORDER_DEPARTMENT; + } +} Deleted: trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/CatchBatchPersistenceServiceImpl.java =================================================================== --- trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/CatchBatchPersistenceServiceImpl.java 2013-02-14 10:40:25 UTC (rev 412) +++ trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/CatchBatchPersistenceServiceImpl.java 2013-02-14 15:27:16 UTC (rev 413) @@ -1,437 +0,0 @@ -package fr.ifremer.tutti.persistence.service; - -/* - * #%L - * Tutti :: Persistence API - * $Id$ - * $HeadURL$ - * %% - * Copyright (C) 2012 - 2013 Ifremer - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/gpl-3.0.html>. - * #L% - */ - -import com.google.common.base.Preconditions; -import com.google.common.collect.Lists; -import fr.ifremer.adagio.core.dao.data.batch.Batch; -import fr.ifremer.adagio.core.dao.data.batch.CatchBatchDao; -import fr.ifremer.adagio.core.dao.data.batch.SortingBatch; -import fr.ifremer.adagio.core.dao.data.batch.SortingBatchDao; -import fr.ifremer.adagio.core.dao.data.batch.denormalized.DenormalizedBatchDao; -import fr.ifremer.adagio.core.dao.data.measure.QuantificationMeasurement; -import fr.ifremer.adagio.core.dao.data.measure.SortingMeasurement; -import fr.ifremer.adagio.core.dao.data.operation.FishingOperationImpl; -import fr.ifremer.adagio.core.dao.referential.QualityFlagImpl; -import fr.ifremer.adagio.core.dao.technical.synchronization.SynchronizationStatus; -import fr.ifremer.tutti.persistence.entities.data.CatchBatch; -import fr.ifremer.tutti.persistence.service.measure.MeasurementPersistenceHelper; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.hibernate.FlushMode; -import org.hibernate.type.IntegerType; -import org.springframework.dao.DataIntegrityViolationException; -import org.springframework.dao.DataRetrievalFailureException; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; - -/** - * @author tchemit <chemit@codelutin.com> - * @since 1.0 - */ -@Service("catchBatchPersistenceService") -public class CatchBatchPersistenceServiceImpl extends AbstractPersistenceService implements CatchBatchPersistenceService { - - /** Logger. */ - private static final Log log = - LogFactory.getLog(CatchBatchPersistenceServiceImpl.class); - - @Resource(name = "referentialPersistenceService") - protected ReferentialPersistenceService referentialService; - - @Resource(name = "denormalizedBatchDao") - protected DenormalizedBatchDao denormalizedBatchDao; - - @Resource(name = "sortingBatchDao") - protected SortingBatchDao sortingBatchDao; - - @Resource(name = "catchBatchDao") - protected CatchBatchDao catchBatchDao; - - @Resource(name = "measurementPersistenceHelper") - protected MeasurementPersistenceHelper measurementHelper; - - - @Override - public CatchBatch getCatchBatchFromFishingOperation(String id) { - Preconditions.checkNotNull(id); - - Iterator<Object[]> list = queryList("catchBatch", - "fishingOperationId", IntegerType.INSTANCE, Integer.valueOf(id), - "pmfmIdSorted", IntegerType.INSTANCE, enumeration.PMFM_ID_SORTED_UNSORTED, - "pmfmIdSortingType", IntegerType.INSTANCE, enumeration.PMFM_ID_SORTING_TYPE); - - int rowCount = 0; - CatchBatch result = new CatchBatch(); - Integer previousSortedBatchId = null; - while (list.hasNext()) { - Object[] source = list.next(); - rowCount++; - - if (rowCount == 1) { - // Id - result.setId(source[0].toString()); - - // Total weight - Float totalWeight = (Float) source[1]; - result.setCatchTotalWeight(totalWeight); - } - - Integer sortedBatchId = (Integer) source[2]; - Integer sortedQualitativeValueId = (Integer) source[5]; - if (sortedBatchId != null && !sortedBatchId.equals(previousSortedBatchId)) { - // TODO BL : retrieve QV - String samplingRatioText = (String) source[3]; - Float weight = (Float) source[4]; - if (weight != null && enumeration.QUALITATIVE_VRAC_ID.equals(sortedQualitativeValueId)) { - result.setCatchTotalSortedCarousselWeight(weight); - result.setCatchTotalSortedTremisWeight(getTotalWeight(weight, samplingRatioText)); - } else if (weight != null && enumeration.QUALITATIVE_HORS_VRAC_ID.equals(sortedQualitativeValueId)) { - result.setCatchTotalUnsortedWeight(weight); - if (samplingRatioText != null && !samplingRatioText.isEmpty()) { - // TODO BL : throw error because baths are not compatible with tutti ?? - } - } else if (weight != null && enumeration.QUALITATIVE_UNSORTED_ID.equals(sortedQualitativeValueId)) { - result.setCatchTotalRejectedWeight(weight); - if (samplingRatioText != null && !samplingRatioText.isEmpty()) { - // TODO BL : throw error because baths are not compatible with tutti ?? - } - } - } - - Integer sortingTypeBatchId = (Integer) source[6]; - { - String samplingRatioText = (String) source[7]; - Float weight = (Float) source[8]; - Integer qualitativeValueId = (Integer) source[9]; - if (weight != null) { - if (enumeration.QUALITATIVE_VRAC_ID.equals(sortedQualitativeValueId) - && enumeration.QUALITATIVE_ID_SORTING_TYPE_SPECIES.equals(qualitativeValueId)) { - result.setSpeciesTotalSampleSortedWeight(weight); - result.setSpeciesTotalSortedWeight(getTotalWeight(weight, samplingRatioText)); - } else if (enumeration.QUALITATIVE_HORS_VRAC_ID.equals(sortedQualitativeValueId) - && enumeration.QUALITATIVE_ID_SORTING_TYPE_SPECIES.equals(qualitativeValueId)) { - result.setSpeciesTotalUnsortedWeight(weight); - // TODO error si samplingRatio not null - } - // TOBO BL : add benthos, plancton, etc. - } - } - - - previousSortedBatchId = sortedBatchId; - } - - return result; - } - - @Override - public CatchBatch createCatchBatch(CatchBatch bean) { - Preconditions.checkNotNull(bean); - Preconditions.checkArgument(bean.getId() == null); - Preconditions.checkNotNull(bean.getFishingOperation()); - Preconditions.checkNotNull(bean.getFishingOperation().getId()); - - fr.ifremer.adagio.core.dao.data.batch.CatchBatch catchBatch = fr.ifremer.adagio.core.dao.data.batch.CatchBatch.Factory.newInstance(); - beanToEntity(bean, catchBatch, true); - catchBatch = catchBatchDao.create(catchBatch); - bean.setId(String.valueOf(catchBatch.getId())); - - // Link to fishing operation - getCurrentSession().flush(); - Integer fishingOperationId = Integer.valueOf(bean.getFishingOperation().getId()); - int rowUpdated = queryUpdate("updateFishingOperationCatchBatch", - "fishingOperationId", IntegerType.INSTANCE, fishingOperationId, - "catchBatchId", IntegerType.INSTANCE, catchBatch.getId()); - if (rowUpdated == 0) { - throw new DataIntegrityViolationException("Could not attach catch batch to the given operation : operation was not found."); - } - - return bean; - } - - @Override - public CatchBatch saveCatchBatch(CatchBatch bean) { - - Preconditions.checkNotNull(bean); - Preconditions.checkNotNull(bean.getId()); - - getCurrentSession().enableFetchProfile("batch-with-childs"); - getCurrentSession().setFlushMode(FlushMode.COMMIT); - fr.ifremer.adagio.core.dao.data.batch.CatchBatch catchBatch = catchBatchDao.load(Integer.valueOf(bean.getId())); - if (catchBatch == null) { - throw new DataRetrievalFailureException("Could not retrieve catch batch with id=" + bean.getId()); - } - - beanToEntity(bean, catchBatch, true); - catchBatchDao.update(catchBatch); - getCurrentSession().flush(); - return bean; - } - - // ------------------------------------------------------------------------// - // -- Internal methods --// - // ------------------------------------------------------------------------// - protected void beanToEntity(CatchBatch source, - fr.ifremer.adagio.core.dao.data.batch.CatchBatch target, - boolean copyIfNull) { - Preconditions.checkNotNull(source.getFishingOperation()); - Preconditions.checkNotNull(source.getFishingOperation().getId()); - - // Retrieve recorder department - // TODO BLA : prendre le service du 1er saisisseur sur l'OP ? - Integer recorderDepartmentId = enumeration.DEPARTMENT_ID_UNKNOWN_RECORDER_DEPARTMENT; - - // First initialization (when created) - Integer fishingOperationId = Integer.valueOf(source.getFishingOperation().getId()); - target.setFishingOperation(load(FishingOperationImpl.class, fishingOperationId)); - - target.setQualityFlag(load(QualityFlagImpl.class, enumeration.QUALITY_FLAG_CODE_NOT_QUALIFIED)); - target.setRankOrder((short) 1); - target.setSynchronizationStatus(SynchronizationStatus.DIRTY.getValue()); - - // Create lists to store all updates, then remove not updated items - Set<QuantificationMeasurement> notChangedQuantificationMeasurements = new HashSet<QuantificationMeasurement>(); - if (target.getQuantificationMeasurements() != null) { - notChangedQuantificationMeasurements.addAll(target.getQuantificationMeasurements()); - } - - // Total Weight - if (copyIfNull && source.getCatchTotalWeight() == null) { - // Nothing to do : will be removed later, using notChangedQuantificationMeasurements - } else if (source.getCatchTotalWeight() != null) { - QuantificationMeasurement quantificationMeasurement = measurementHelper.setQuantificationMeasurement(target, enumeration.PMFM_ID_WEIGHT_MEASURED, recorderDepartmentId, source.getCatchTotalWeight(), true); - notChangedQuantificationMeasurements.remove(quantificationMeasurement); - } - - // Removed not changed measurements (in sorting and quantification measurement lists) - if (target.getQuantificationMeasurements() != null && notChangedQuantificationMeasurements.size() > 0) { - for (QuantificationMeasurement qm : notChangedQuantificationMeasurements) { - target.getQuantificationMeasurements().remove(qm); - } - } - Map<Integer, SortingBatch> catchBatchChilds = getChildsMap(target, enumeration.PMFM_ID_SORTED_UNSORTED); - - // ----------------------------------------------------------------------------- - // Sorted Vrac - // ----------------------------------------------------------------------------- - { - SortingBatch batch = catchBatchChilds.get(enumeration.QUALITATIVE_VRAC_ID); - if (batch == null) { - batch = SortingBatch.Factory.newInstance(); - target.getChildBatchs().add(batch); - } - beanToEntitySortingBatch(target, target, batch, recorderDepartmentId, - enumeration.PMFM_ID_SORTED_UNSORTED, enumeration.QUALITATIVE_VRAC_ID, - source.getCatchTotalSortedTremisWeight(), source.getCatchTotalSortedCarousselWeight(), - copyIfNull); - batch.setRankOrder((short) 1); - - // Manage childs : - { - Map<Integer, SortingBatch> batchChilds = getChildsMap(batch, enumeration.PMFM_ID_SORTING_TYPE); - - // Species : - SortingBatch speciesBatch = batchChilds.get(enumeration.QUALITATIVE_ID_SORTING_TYPE_SPECIES); - if (speciesBatch == null) { - speciesBatch = SortingBatch.Factory.newInstance(); - if (batch.getChildBatchs() == null) { - batch.setChildBatchs(Lists.newArrayList((Batch) speciesBatch)); - } else { - batch.getChildBatchs().add(speciesBatch); - } - } - beanToEntitySortingBatch(target, batch, speciesBatch, recorderDepartmentId, - enumeration.PMFM_ID_SORTING_TYPE, enumeration.QUALITATIVE_ID_SORTING_TYPE_SPECIES, - source.getSpeciesTotalSortedWeight(), source.getSpeciesTotalSampleSortedWeight(), - copyIfNull); - speciesBatch.setRankOrder((short) 1); - } - // TODO BL : benthos, plancton, macro déchet... - } - - // ----------------------------------------------------------------------------- - // Sorted Hors Vrac - // ----------------------------------------------------------------------------- - { - SortingBatch batch = catchBatchChilds.get(enumeration.QUALITATIVE_HORS_VRAC_ID); - if (batch == null) { - batch = SortingBatch.Factory.newInstance(); - target.getChildBatchs().add(batch); - } - beanToEntitySortingBatch(target, target, batch, recorderDepartmentId, - enumeration.PMFM_ID_SORTED_UNSORTED, enumeration.QUALITATIVE_HORS_VRAC_ID, - source.getCatchTotalUnsortedWeight(), null, - copyIfNull); - batch.setRankOrder((short) 2); - - // Manage childs : - { - Map<Integer, SortingBatch> batchChilds = getChildsMap(batch, enumeration.PMFM_ID_SORTING_TYPE); - - // Species : - SortingBatch speciesBatch = batchChilds.get(enumeration.QUALITATIVE_ID_SORTING_TYPE_SPECIES); - if (speciesBatch == null) { - speciesBatch = SortingBatch.Factory.newInstance(); - if (batch.getChildBatchs() == null) { - batch.setChildBatchs(Lists.newArrayList((Batch) speciesBatch)); - } else { - batch.getChildBatchs().add(speciesBatch); - } - } - beanToEntitySortingBatch(target, batch, speciesBatch, recorderDepartmentId, - enumeration.PMFM_ID_SORTING_TYPE, enumeration.QUALITATIVE_ID_SORTING_TYPE_SPECIES, - source.getSpeciesTotalUnsortedWeight(), null, - copyIfNull); - speciesBatch.setRankOrder((short) 1); - } - - // TODO BL : benthos, plancton, macro déchet... - } - - // ----------------------------------------------------------------------------- - // Unsorted (=rejected) - // ----------------------------------------------------------------------------- - // Unsorted : - SortingBatch unsortedBatch = catchBatchChilds.get(enumeration.QUALITATIVE_UNSORTED_ID); - if (unsortedBatch == null) { - unsortedBatch = SortingBatch.Factory.newInstance(); - target.getChildBatchs().add(unsortedBatch); - } - beanToEntitySortingBatch(target, target, unsortedBatch, recorderDepartmentId, - enumeration.PMFM_ID_SORTED_UNSORTED, enumeration.QUALITATIVE_UNSORTED_ID, - source.getCatchTotalRejectedWeight(), null, - copyIfNull); - unsortedBatch.setRankOrder((short) 3); - - - } - - protected Map<Integer, SortingBatch> getChildsMap(Batch parentBatch, Integer pmfmId) { - Map<Integer, SortingBatch> batchByQualitativeValueId = new HashMap<Integer, SortingBatch>(); - if (parentBatch.getChildBatchs() == null) { - return batchByQualitativeValueId; - } - for (Batch childBatch : parentBatch.getChildBatchs()) { - SortingMeasurement sm = measurementHelper.getSortingMeasurement((SortingBatch) childBatch, pmfmId, null, false); - if (sm != null && sm.getQualitativeValue() != null && sm.getQualitativeValue().getId() != null) { - batchByQualitativeValueId.put(sm.getQualitativeValue().getId(), (SortingBatch) childBatch); - } - } - return batchByQualitativeValueId; - } - - protected void beanToEntitySortingBatch( - fr.ifremer.adagio.core.dao.data.batch.CatchBatch rootBatch, - fr.ifremer.adagio.core.dao.data.batch.Batch parentBatch, - fr.ifremer.adagio.core.dao.data.batch.SortingBatch target, - Integer recorderDepartmentId, - Integer sortingPmfmId, - Integer sortingQualitativeValueId, - Float weight, - Float sampleWeight, - boolean copyIfNull) { - - // Create lists to store all updates, then remove not updated items - Set<QuantificationMeasurement> notChangedQuantificationMeasurements = new HashSet<QuantificationMeasurement>(); - if (target.getQuantificationMeasurements() != null) { - notChangedQuantificationMeasurements.addAll(target.getQuantificationMeasurements()); - } - Set<SortingMeasurement> notChangedSortingMeasurements = new HashSet<SortingMeasurement>(); - if (target.getSortingMeasurements() != null) { - notChangedSortingMeasurements.addAll(target.getSortingMeasurements()); - } - - // Some mandatory properties : - target.setQualityFlag(load(QualityFlagImpl.class, enumeration.QUALITY_FLAG_CODE_NOT_QUALIFIED)); - target.setRootBatch(rootBatch); - target.setParentBatch(parentBatch); - - // Sorting measurement - if (copyIfNull && (sortingPmfmId == null || sortingQualitativeValueId == null)) { - // Nothing to do : will be removed later, using notChangedSortingMeasurements - } else if (sortingPmfmId != null && sortingQualitativeValueId != null) { - SortingMeasurement sm = measurementHelper.setSortingMeasurement(target, recorderDepartmentId, sortingPmfmId, sortingQualitativeValueId); - notChangedSortingMeasurements.remove(sm); - } - - // Sampling Ratio - if (copyIfNull && (sampleWeight == null || weight == null)) { - target.setSamplingRatio(null); - target.setSamplingRatioText(null); - } else if (sampleWeight != null && weight != null) { - String samplingRatioText = sampleWeight + "/" + weight; - samplingRatioText = samplingRatioText.replaceAll(",", "."); - target.setSamplingRatioText(samplingRatioText); - target.setSamplingRatio(sampleWeight / weight); - } - - // Weight - if (copyIfNull && (sampleWeight == null && weight == null)) { - // Nothing to do : will be removed later, using notChangedQuantificationMeasurements - } else if (sampleWeight != null || weight != null) { - Float batchReferenceWeight = sampleWeight; - if (batchReferenceWeight == null) { - batchReferenceWeight = weight; - } - QuantificationMeasurement quantificationMeasurement = measurementHelper.setQuantificationMeasurement(target, enumeration.PMFM_ID_WEIGHT_MEASURED, recorderDepartmentId, batchReferenceWeight, true); - notChangedQuantificationMeasurements.remove(quantificationMeasurement); - } - - // Removed not changed measurements (in sorting and quantification measurement lists) - if (target.getQuantificationMeasurements() != null && notChangedQuantificationMeasurements.size() > 0) { - for (QuantificationMeasurement qm : notChangedQuantificationMeasurements) { - target.getQuantificationMeasurements().remove(qm); - } - } - if (target.getSortingMeasurements() != null && notChangedSortingMeasurements.size() > 0) { - for (SortingMeasurement sm : notChangedSortingMeasurements) { - target.getSortingMeasurements().remove(sm); - } - } - } - - protected Float getTotalWeight(Float weight, String samplingRatioText) { - if (weight == null) { - return null; - } - String startStr = weight.toString().replace(',', '.') + "/"; - if (samplingRatioText != null && samplingRatioText.startsWith(startStr)) { - String weightStr = samplingRatioText.substring(startStr.length()); - if (weightStr != null && !weightStr.isEmpty()) { - return Float.parseFloat(weightStr); - } - } - // TODO BL : attention au saise "1/2" qui ne seront pas pris (mais "1.0/2.0" oui) - return null; - } - -} Modified: trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/ReferentialPersistenceService.java =================================================================== --- trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/ReferentialPersistenceService.java 2013-02-14 10:40:25 UTC (rev 412) +++ trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/ReferentialPersistenceService.java 2013-02-14 15:27:16 UTC (rev 413) @@ -188,7 +188,9 @@ Caracteristic getCaracteristic(Integer pmfmId); boolean isSortedQualitativeValue(CaracteristicQualitativeValue value); - + + List<Integer> getSampleCategoryIds(); + /** * Import given temporary species. * Modified: trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/ReferentialPersistenceServiceImpl.java =================================================================== --- trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/ReferentialPersistenceServiceImpl.java 2013-02-14 10:40:25 UTC (rev 412) +++ trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/ReferentialPersistenceServiceImpl.java 2013-02-14 15:27:16 UTC (rev 413) @@ -815,6 +815,20 @@ } /** + * Return list of protected pmfm for sample category + * (i.e. to check the validity of a existing batch tree) + * + * @return + */ + public List<Integer> getSampleCategoryIds() { + return Lists.newArrayList(enumeration.PMFM_ID_SORTED_UNSORTED + , enumeration.PMFM_ID_SIZE_CATEGORY + , enumeration.PMFM_ID_MATURITY + , enumeration.PMFM_ID_SEX + , enumeration.PMFM_ID_AGE); + } + + /** * Return true if the pmfm should NOT be used for caracteristics lists * (i.e. because used somewhere when storing some properties into the database) * Deleted: trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/SpeciesBatchPersistenceServiceImpl.java =================================================================== --- trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/SpeciesBatchPersistenceServiceImpl.java 2013-02-14 10:40:25 UTC (rev 412) +++ trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/SpeciesBatchPersistenceServiceImpl.java 2013-02-14 15:27:16 UTC (rev 413) @@ -1,812 +0,0 @@ -package fr.ifremer.tutti.persistence.service; - -/* - * #%L - * Tutti :: Persistence API - * $Id$ - * $HeadURL$ - * %% - * Copyright (C) 2012 - 2013 Ifremer - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/gpl-3.0.html>. - * #L% - */ - -import com.google.common.base.Preconditions; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import fr.ifremer.adagio.core.dao.data.batch.CatchBatchDao; -import fr.ifremer.adagio.core.dao.data.batch.CatchBatchImpl; -import fr.ifremer.adagio.core.dao.data.batch.SortingBatch; -import fr.ifremer.adagio.core.dao.data.batch.SortingBatchDao; -import fr.ifremer.adagio.core.dao.data.batch.SortingBatchImpl; -import fr.ifremer.adagio.core.dao.data.batch.denormalized.DenormalizedBatchDao; -import fr.ifremer.adagio.core.dao.data.measure.QuantificationMeasurement; -import fr.ifremer.adagio.core.dao.data.measure.SortingMeasurement; -import fr.ifremer.adagio.core.dao.referential.QualityFlagImpl; -import fr.ifremer.adagio.core.dao.referential.taxon.ReferenceTaxon; -import fr.ifremer.adagio.core.dao.referential.taxon.ReferenceTaxonImpl; -import fr.ifremer.tutti.persistence.entities.data.SampleCategoryEnum; -import fr.ifremer.tutti.persistence.entities.data.SpeciesBatch; -import fr.ifremer.tutti.persistence.entities.data.SpeciesBatchFrequency; -import fr.ifremer.tutti.persistence.entities.referential.Caracteristic; -import fr.ifremer.tutti.persistence.entities.referential.CaracteristicQualitativeValue; -import fr.ifremer.tutti.persistence.entities.referential.CaracteristicType; -import fr.ifremer.tutti.persistence.entities.referential.Species; -import fr.ifremer.tutti.persistence.service.measure.MeasurementPersistenceHelper; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.hibernate.FlushMode; -import org.hibernate.type.IntegerType; -import org.springframework.dao.DataIntegrityViolationException; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.io.Serializable; -import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * @author tchemit <chemit@codelutin.com> - * @since 0.3 - */ -@Service("speciesBatchPersistenceService") -public class SpeciesBatchPersistenceServiceImpl extends - AbstractPersistenceService implements SpeciesBatchPersistenceService { - - /** Logger. */ - private static final Log log = LogFactory - .getLog(SpeciesBatchPersistenceServiceImpl.class); - - @Resource(name = "referentialPersistenceService") - protected ReferentialPersistenceService referentialService; - - @Resource(name = "denormalizedBatchDao") - protected DenormalizedBatchDao denormalizedBatchDao; - - @Resource(name = "sortingBatchDao") - protected SortingBatchDao sortingBatchDao; - - @Resource(name = "catchBatchDao") - protected CatchBatchDao catchBatchDao; - - @Resource(name = "measurementPersistenceHelper") - protected MeasurementPersistenceHelper measurementHelper; - - @Override - public List<SpeciesBatch> getAllRootSpeciesBatch(String fishingOperationId) { - Iterator<Object[]> list = queryList("allSpeciesBatch", - "fishingOperationId", IntegerType.INSTANCE, Integer.valueOf(fishingOperationId)); - - List<SpeciesBatch> result = new ArrayList<SpeciesBatch>(); - List<SpeciesBatch> rootBatchs = new ArrayList<SpeciesBatch>(); - - Map<String, SpeciesBatch> batchMapById = new HashMap<String, SpeciesBatch>(); - //TODO BLA : uncomment if a property speciesBatch.speciesBatchFrequency exists - //Map<String, List<SpeciesBatchFrequency>> batchFrequenciesMapByParentId = new HashMap<String, List<SpeciesBatchFrequency>>(); - Map<String, String> parentBatchMapById = new HashMap<String, String>(); - while (list.hasNext()) { - Object[] source = list.next(); - - Integer parentbatchId = (Integer) source[11]; - - // If row is not a species batch, load as batch frequency - if (couldBeASpeciesBatchFrequency(source)) { - //TODO BLA : uncomment if a property speciesBatch.speciesBatchFrequency exists - //loadSpeciesBatchFrequency(source, batchFrequenciesMapByParentId); - } else { - // In all case, load row as species batch - SpeciesBatch speciesBatch = loadSpeciesBatch(source); - - // Add result into a maps - batchMapById.put(speciesBatch.getId(), speciesBatch); - if (parentbatchId != null) { - parentBatchMapById.put(speciesBatch.getId(), parentbatchId.toString()); - } - } - } - - // Retrieve the parent links for all batchs - for (SpeciesBatch speciesBatch : batchMapById.values()) { - // If retrieve the parent from the parent map - String parentbatchId = parentBatchMapById.get(speciesBatch.getId()); - if (parentbatchId != null) { - SpeciesBatch parentSpeciesBatch = batchMapById.get(parentbatchId); - - // If found, link the batch with its parent : - if (parentSpeciesBatch != null) { - speciesBatch.setParentBatch(parentSpeciesBatch); - if (parentSpeciesBatch.getChildBatchs() == null) { - parentSpeciesBatch.setChildBatchs(Lists.newArrayList(speciesBatch)); - } else { - parentSpeciesBatch.addChildBatchs(speciesBatch); - } - } - - // If no parent found, the batch should be a direct child of the catch batch - else { - rootBatchs.add(speciesBatch); - } - - //TODO BLA : uncomment if a property speciesBatch.speciesBatchFrequency exists - //List<SpeciesBatchFrequency> batchFrequencies = batchFrequenciesMapByParentId.get(speciesBatch.getId()); - //if (batchFrequencies != null) { - // speciesBatch.setSpeciesBatchFrequency(batchFrequencies); - //} - } - } - - // Apply inheritance, starting with the catch batch children - applyInheritedProperties(rootBatchs, null, null, result); - - return result; - } - - @Override - public SpeciesBatch createSpeciesBatch(SpeciesBatch bean, - String parentBatchId) { - Preconditions.checkNotNull(bean); - Preconditions.checkArgument(bean.getId() == null); - Preconditions.checkNotNull(bean.getSpecies()); - Preconditions.checkNotNull(bean.getSpecies().getId()); - Preconditions.checkNotNull(bean.getFishingOperation()); - Preconditions.checkNotNull(bean.getFishingOperation().getId()); - // TODO BLA uncomment this after v1.0 : - //Preconditions.checkNotNull(bean.getCatchBatch()); - - getCurrentSession().setFlushMode(FlushMode.COMMIT); - - SortingBatch batch = SortingBatch.Factory.newInstance(); - beanToEntity(bean, batch, parentBatchId, true); - batch = sortingBatchDao.create(batch); - - bean.setId(String.valueOf(batch.getId())); - - getCurrentSession().flush(); - - return bean; - } - - @Override - public SpeciesBatch saveSpeciesBatch(SpeciesBatch bean) { - Preconditions.checkNotNull(bean); - Preconditions.checkNotNull(bean.getId()); - - // TODO BL : pourquoi un clear() ? => pas nécessaire. - //getCurrentSession().clear(); - - getCurrentSession().enableFetchProfile("batch-with-measurements"); - getCurrentSession().setFlushMode(FlushMode.COMMIT); - SortingBatch batch = sortingBatchDao.load(Integer.valueOf(bean.getId())); - String parentBatchId = null; - if (bean.getParentBatch() != null) { - parentBatchId = bean.getParentBatch().getId(); - } - beanToEntity(bean, batch, parentBatchId, true); - sortingBatchDao.update(batch); - getCurrentSession().flush(); - return bean; - } - - @Override - public void deleteSpeciesBatch(String id) { - Preconditions.checkNotNull(id); - - getCurrentSession().setFlushMode(FlushMode.COMMIT); - - List<SortingBatch> allChildrenBatchs = Lists.newArrayList(); - removeAllChildrenBatchs(Integer.valueOf(id), allChildrenBatchs); - - getCurrentSession().flush(); - } - - @Override - public void deleteSpeciesSubBatch(String id) { - deleteSpeciesBatch(id); - } - - @Override - public void changeSpeciesBatchSpecies(String batchId, Species species) { - Preconditions.checkNotNull(batchId); - Preconditions.checkNotNull(species); - Preconditions.checkNotNull(species.getReferenceTaxonId()); - - if (log.isDebugEnabled()) { - log.debug("Changing species for batch id="+batchId); - } - - int rowUpdated = queryUpdate("updateBatchSpecies", - "batchId", IntegerType.INSTANCE, Integer.valueOf(batchId), - "referenceTaxonId", IntegerType.INSTANCE, species.getReferenceTaxonId()); - } - - @Override - public List<SpeciesBatchFrequency> getAllSpeciesBatchFrequency( - String speciesBatchId) { - Iterator<Object[]> list = queryList("allSpeciesBatchFrequency", - "parentBatchId", IntegerType.INSTANCE, Integer.valueOf(speciesBatchId)); - - List<SpeciesBatchFrequency> results = Lists.newArrayList(); - - while (list.hasNext()) { - Object[] source = list.next(); - SpeciesBatchFrequency target = new SpeciesBatchFrequency(); - - int colIndex = 0; - target.setId(source[colIndex++].toString()); - - target.setNumber((Integer) source[colIndex++]); - target.setWeight((Float) source[colIndex++]); - target.setComment((String) source[colIndex++]); - - // Length step category - Integer lengthPmfmId = (Integer) source[colIndex++]; - Caracteristic lengthStepCaracteristic = referentialService.getCaracteristic(lengthPmfmId); - target.setLengthStepCaracteristic(lengthStepCaracteristic); - - // Length - target.setLengthStep((Float) source[colIndex++]); - results.add(target); - } - return results; - } - - - @Override - public List<SpeciesBatchFrequency> saveSpeciesBatchFrequency( - String speciesBatchId, List<SpeciesBatchFrequency> frequencies) { - Preconditions.checkNotNull(speciesBatchId); - Preconditions.checkNotNull(frequencies); - - if (frequencies.size() == 0) { - return frequencies; - } - getCurrentSession().setFlushMode(FlushMode.COMMIT); - getCurrentSession().enableFetchProfile("batch-with-measurements"); - - // Retirve parent - SortingBatch parentBatch = sortingBatchDao.load(Integer.valueOf(speciesBatchId)); - - short rankOrder = 0; - String pmfmId = null; - Map<SortingBatch, SpeciesBatchFrequency> batchsToCreate = Maps.newHashMap(); - List<SortingBatch> batchsToUpdate = Lists.newArrayList(); - for (SpeciesBatchFrequency source : frequencies) { - rankOrder++; - - // Check that all frequencies have the same length PMFM - if (pmfmId == null) { - source.getLengthStepCaracteristic().getId(); - } else if (!pmfmId.equals(source.getLengthStepCaracteristic().getId())) { - throw new DataIntegrityViolationException("Batch frequencies under one Speciesbatch must have all the same lengthStepCaracteristic"); - } - - // Not existing batch - SortingBatch target = null; - if (source.getId() == null) { - target = SortingBatch.Factory.newInstance(); - - // Fill the sorting batch from the source - beanToEntity(source, target, parentBatch, rankOrder, true); - - // Create the targeted batch, then update the source id - sortingBatchDao.create(target); - source.setId(target.getId().toString()); - } - - // Existing batch - else { - target = sortingBatchDao.load(Integer.valueOf(source.getId())); - - // Fill the sorting batch from the source - beanToEntity(source, target, parentBatch, rankOrder, true); - - // Add the batch into a list (will be update later, using this list) - batchsToUpdate.add(target); - } - } - - // If some batchs need to be update, do it - if (batchsToUpdate.size() > 0) { - sortingBatchDao.update(batchsToUpdate); - } - - getCurrentSession().flush(); - - return frequencies; - } - - // ------------------------------------------------------------------------// - // -- Internal methods --// - // ------------------------------------------------------------------------// - protected void beanToEntity(SpeciesBatch source, SortingBatch target, String parentBatchId, boolean copyIfNull) { - Preconditions.checkNotNull(source.getFishingOperation()); - Preconditions.checkNotNull(source.getFishingOperation().getId()); - - // Retrieve recorder department - // TODO BLA : prendre le service du 1er saisisseur ? - Integer recorderDepartmentId = enumeration.DEPARTMENT_ID_UNKNOWN_RECORDER_DEPARTMENT; - - // Create lists to store all updates, then remove not updated items - Set<QuantificationMeasurement> notChangedQuantificationMeasurements = new HashSet<QuantificationMeasurement>(); - if (target.getQuantificationMeasurements() != null) { - notChangedQuantificationMeasurements.addAll(target.getQuantificationMeasurements()); - } - Set<SortingMeasurement> notChangedSortingMeasurements = new HashSet<SortingMeasurement>(); - if (target.getSortingMeasurements() != null) { - notChangedSortingMeasurements.addAll(target.getSortingMeasurements()); - } - - // If parent and root need to be set - if (target.getId() == null - || target.getRootBatch() == null - || (target.getParentBatch() != null && !target.getParentBatch().getId().toString().equals(parentBatchId))) { - setBatchParents(source, target, parentBatchId, notChangedSortingMeasurements); - } - - // RankOrder - if (target.getRankOrder() == null) { - short rankOrder = (short) 1; - if (source.getParentBatch() != null && source.getParentBatch().getChildBatchs() != null) { - // TODO BL : vérifier cela (est-ce que l'item est ajouté à son père AVANT d'être passé au service ?) - rankOrder = (short) source.getParentBatch().getChildBatchs().size(); - } - target.setRankOrder(rankOrder); - } - - // Weight or SampleCategoryWeight - if (copyIfNull && source.getWeight() == null && source.getSampleCategoryWeight() == null) { - // Nothing to do : will be removed later, using notChangedSortingMeasurements - } else if (source.getSampleCategoryWeight() != null && source.getWeight() == null) { - QuantificationMeasurement quantificationMeasurement = measurementHelper.setQuantificationMeasurement(target, enumeration.PMFM_ID_WEIGHT_MEASURED, recorderDepartmentId, source.getSampleCategoryWeight(), true); - notChangedQuantificationMeasurements.remove(quantificationMeasurement); - } else if (source.getWeight() != null && source.getSampleCategoryWeight() == null) { - QuantificationMeasurement quantificationMeasurement = measurementHelper.setQuantificationMeasurement(target, enumeration.PMFM_ID_WEIGHT_MEASURED, recorderDepartmentId, source.getWeight(), true); - notChangedQuantificationMeasurements.remove(quantificationMeasurement); - } - - // Sampling Ratio - if (copyIfNull && (source.getSampleCategoryWeight() == null || source.getWeight() == null)) { - target.setSamplingRatio(null); - target.setSamplingRatioText(null); - } else if (source.getSampleCategoryWeight() != null && source.getWeight() != null) { - String samplingRatioText = source.getWeight() + "/" + source.getSampleCategoryWeight(); - samplingRatioText = samplingRatioText.replaceAll(",", "."); - target.setSamplingRatioText(samplingRatioText); - target.setSamplingRatio(source.getWeight() / source.getSampleCategoryWeight()); - QuantificationMeasurement quantificationMeasurement = measurementHelper.setQuantificationMeasurement(target, enumeration.PMFM_ID_WEIGHT_MEASURED, recorderDepartmentId, source.getWeight(), true); - notChangedQuantificationMeasurements.remove(quantificationMeasurement); - } - - // Sorting measurement - if (copyIfNull && (source.getSampleCategoryType() == null || source.getSampleCategoryValue() == null)) { - // Nothing to do : will be removed later, using notChangedSortingMeasurements - } else if (source.getSampleCategoryType() != null && source.getSampleCategoryValue() != null) { - Integer pmfmId = measurementHelper.sampleCategory2PmfmId(source.getSampleCategoryType()); - // Do not store sorting measurement if pmfm = SORTED (already store in an ancestor batch) - if (!pmfmId.equals(enumeration.PMFM_ID_SORTED_UNSORTED)) { - SortingMeasurement sortingMeasurement = measurementHelper.setSortingMeasurement(target, recorderDepartmentId, source.getSampleCategoryType(), source.getSampleCategoryValue()); - notChangedSortingMeasurements.remove(sortingMeasurement); - } - } - - // Individual count - if (copyIfNull && source.getNumber() == null) { - target.setIndividualCount(null); - } else if (source.getNumber() != null) { - target.setIndividualCount(source.getNumber()); - } - - // Species - if (copyIfNull && (source.getSpecies() == null || parentBatchId != null)) { - target.setReferenceTaxon(null); - } else if (source.getSpecies() != null && parentBatchId == null) { - ReferenceTaxon referenceTaxon = load(ReferenceTaxonImpl.class, source.getSpecies().getReferenceTaxonId()); - target.setReferenceTaxon(referenceTaxon); - } - - // QualityFlag - if (source.isSpeciesToConfirm()) { - target.setQualityFlag(load(QualityFlagImpl.class, enumeration.QUALITY_FLAG_CODE_DOUBTFUL)); - } else { - target.setQualityFlag(load(QualityFlagImpl.class, enumeration.QUALITY_FLAG_CODE_NOT_QUALIFIED)); - } - - // Comments - if (copyIfNull && source.getComment() == null) { - target.setComments(null); - } else if (source.getComment() != null) { - target.setComments(source.getComment()); - } - - // Removed not changed measurements (in sorting and quantification measurement lists) - if (target.getQuantificationMeasurements() != null && notChangedQuantificationMeasurements.size() > 0) { - for (QuantificationMeasurement qm : notChangedQuantificationMeasurements) { - target.getQuantificationMeasurements().remove(qm); - } - } - if (target.getSortingMeasurements() != null && notChangedSortingMeasurements.size() > 0) { - for (SortingMeasurement sm : notChangedSortingMeasurements) { - target.getSortingMeasurements().remove(sm); - } - } - } - - public void setBatchParents(SpeciesBatch source, SortingBatch target, String parentBatchIdStr, - Set<SortingMeasurement> notChangedSortingMeasurements) { - - Preconditions.checkNotNull(target); - Preconditions.checkNotNull(source.getFishingOperation()); - Preconditions.checkNotNull(source.getFishingOperation().getId()); - - // Retrieve parent and root batch - if (parentBatchIdStr == null) { - // Retrieve category type - Integer pmfmId = measurementHelper.sampleCategory2PmfmId(source.getSampleCategoryType()); - if (pmfmId == null || !pmfmId.equals(enumeration.PMFM_ID_SORTED_UNSORTED)) { - throw new DataIntegrityViolationException(MessageFormat.format("A species batch with no parent should have a sampleCategoryType {0} (PMFM.ID={1})", - SampleCategoryEnum.sortedUnsorted.name(), enumeration.PMFM_ID_SORTED_UNSORTED)); - } - Integer qualitativeValueId = convertSampleCategoryValueIntoQualitativeId(source.getSampleCategoryValue()); - - Object[] cols = queryUnique("parentBatch", - "fishingOperationId", IntegerType.INSTANCE, Integer.valueOf(source.getFishingOperation().getId()), - "pmfmIdSorted", IntegerType.INSTANCE, enumeration.PMFM_ID_SORTED_UNSORTED, - "qualitativeIdSorted", IntegerType.INSTANCE, qualitativeValueId, - "pmfmIdSortingType", IntegerType.INSTANCE, enumeration.PMFM_ID_SORTING_TYPE, - "qualitativeIdSortingType", IntegerType.INSTANCE, enumeration.QUALITATIVE_ID_SORTING_TYPE_SPECIES); - - if (cols == null) { - throw new DataIntegrityViolationException("Catch batchs not presents, or invalid batch tree structure. Please make sure CatchBatch has been saved before to create a SpeciesBatch."); - } - // Parent Batch - Integer parentBatchId = (Integer) cols[0]; - SortingBatch parentBatch = load(SortingBatchImpl.class, parentBatchId); - target.setParentBatch(parentBatch); - - // Root Batch - Integer rootBatchId = (Integer) cols[1]; - target.setRootBatch(load(CatchBatchImpl.class, rootBatchId)); - } - - // Load existing parent and root - else { - SortingBatch parentBatch = load(SortingBatchImpl.class, Integer.valueOf(parentBatchIdStr)); - target.setParentBatch(parentBatch); - target.setRootBatch(parentBatch.getRootBatch()); - } - } - - protected SpeciesBatch loadSpeciesBatch(Object[] source) { - int colIndex = 0; - - SpeciesBatch result = new SpeciesBatch(); - result.setId(source[colIndex++].toString()); - - // Individual count - result.setNumber((Integer) source[colIndex++]); - - // Convert database weight (and sampling ratio) into UI weight and sampleCategoryWeight - Float sourceWeight = (Float) source[colIndex++]; - Float sourceSamplingRatio = (Float) source[colIndex++]; - String sourceSamplingRatioText = (String) source[colIndex++]; - UIWeight uiWeight = convertDatabase2UI(sourceWeight, sourceSamplingRatio, sourceSamplingRatioText); - result.setWeight(uiWeight.weight); - result.setSampleCategoryWeight(uiWeight.sampleCategoryWeight); - - // Comments - result.setComment((String) source[colIndex++]); - - // Sample category type - Integer pmfmId = (Integer) source[colIndex++]; - - // Sample category value - Integer qvValue = (Integer) source[colIndex++]; - Float numValue = (Float) source[colIndex++]; - String alphaValue = (String) source[colIndex++]; - if (pmfmId != null) { - setSampleCategoryQualitative(result, pmfmId, numValue, alphaValue, qvValue); - } - - // Species - Integer referenceTaxonId = (Integer) source[colIndex++]; - if (referenceTaxonId != null) { - // TODO : add cache on getSpeciesByReferenceTaxonId - Species species = referentialService.getSpeciesByReferenceTaxonId(referenceTaxonId); - result.setSpecies(species); - } - - return result; - } - - protected void applyInheritedProperties(List<SpeciesBatch> speciesBatchs, CaracteristicQualitativeValue inheritedSortedUnsortedValue, Species inheritedSpecies, List<SpeciesBatch> results) { - if (speciesBatchs == null || speciesBatchs.size() == 0) { - return; - } - for (SpeciesBatch speciesBatch : speciesBatchs) { - // If batch store a species (in the database) - if (speciesBatch.getSpecies() != null) { - // Remove the link to the parent (not need in UI) - speciesBatch.setParentBatch(null); - // Store into result list only if species has been set (=species root batch) - results.add(speciesBatch); - } - - // Apply sampleCategoryValue inheritance, if need - if (inheritedSortedUnsortedValue != null && speciesBatch.getSampleCategoryType() == null) { - speciesBatch.setSampleCategoryType(SampleCategoryEnum.sortedUnsorted); - speciesBatch.setSampleCategoryValue(inheritedSortedUnsortedValue); - } - - // Apply species inheritance, if need - if (speciesBatch.getSpecies() == null && inheritedSpecies != null) { - speciesBatch.setSpecies(inheritedSpecies); - } - - // Compute the inheritance sorted/unsorted value for children - if (speciesBatch.getSampleCategoryType() == SampleCategoryEnum.sortedUnsorted) { - inheritedSortedUnsortedValue = (CaracteristicQualitativeValue) speciesBatch.getSampleCategoryValue(); - } else { - inheritedSortedUnsortedValue = null; - } - - // Recursive call : propagate species and sorted/unsorted value - applyInheritedProperties(speciesBatch.getChildBatchs(), - inheritedSortedUnsortedValue, - speciesBatch.getSpecies(), - results); - } - } - - Integer convertSampleCategoryValueIntoQualitativeId(Serializable value) { - if (value == null) return null; - Integer qualitativeValueId = null; - if (value instanceof CaracteristicQualitativeValue) { - CaracteristicQualitativeValue cqValue = (CaracteristicQualitativeValue) value; - qualitativeValueId = Integer.valueOf(cqValue.getId()); - } else if (value instanceof String) { - qualitativeValueId = Integer.valueOf((String) value); - } - return qualitativeValueId; - } - - protected void setSampleCategoryQualitative(SpeciesBatch target, Integer pmfmId, Float numericalvalue, String alphanumericalValue, Integer qualitativeValueId) { - // skip if null or corresponding to the SORTING_TYPE PMFM (Expèce, Benthos, Plancton, etc.) - if (pmfmId == null || pmfmId.equals(enumeration.PMFM_ID_SORTING_TYPE)) { - return; - } - - SampleCategoryEnum sampleCategory = referentialService.getSampleCategoryByPmfmId(pmfmId); - Preconditions.checkNotNull(sampleCategory, "Unable to find corresponding SampleCategoryEnum for PMFM.ID : " + pmfmId); - - target.setSampleCategoryType(sampleCategory); - if (numericalvalue != null) { - target.setSampleCategoryValue(numericalvalue); - return; - } - if (alphanumericalValue != null) { - target.setSampleCategoryValue(alphanumericalValue); - return; - } - - Caracteristic caracteristic = referentialService.getCaracteristic(pmfmId); - if (caracteristic == null || caracteristic.getCaracteristicType() != CaracteristicType.QUALITATIVE) { - return; - } - CaracteristicQualitativeValue value = null; - for (CaracteristicQualitativeValue qv : caracteristic.getQualitativeValue()) { - if (qualitativeValueId == Integer.parseInt(qv.getId())) { - value = qv; - break; - } - } - target.setSampleCategoryValue(value); - } - - protected void removeAllChildrenBatchs(Integer batchId, List<SortingBatch> result) { - Iterator<Integer> list = queryListTyped("speciesBatchChildren", - "batchId", IntegerType.INSTANCE, batchId); - - // First, add childrens - while (list.hasNext()) { - - removeAllChildrenBatchs(list.next(), result); - } - - // Then add the given batch (after children, because of order need in "delete") - SortingBatch batch = sortingBatchDao.load(batchId); - //SortingBatch batch = (SortingBatch)getCurrentSession().get(SortingBatchImpl.class, batchId); - batch.getSortingMeasurements().clear(); - batch.getQuantificationMeasurements().clear(); - sortingBatchDao.remove(batch); - } - - protected void beanToEntity(SpeciesBatchFrequency source, SortingBatch target, SortingBatch parentBatch, short rankOrder, boolean copyIfNull) { - Preconditions.checkNotNull(source.getBatch()); - Preconditions.checkNotNull(source.getBatch().getId()); - - // Retrieve recorder department - // TODO BLA : prendre le service du 1er saisisseur ? - Integer recorderDepartmentId = enumeration.DEPARTMENT_ID_UNKNOWN_RECORDER_DEPARTMENT; - - // Create lists to store all updates, then remove not updated items - Set<QuantificationMeasurement> notChangedQuantificationMeasurements = new HashSet<QuantificationMeasurement>(); - if (target.getQuantificationMeasurements() != null) { - notChangedQuantificationMeasurements.addAll(target.getQuantificationMeasurements()); - } - Set<SortingMeasurement> notChangedSortingMeasurements = new HashSet<SortingMeasurement>(); - if (target.getSortingMeasurements() != null) { - notChangedSortingMeasurements.addAll(target.getSortingMeasurements()); - } - - // If parent and root need to be set - if (target.getId() == null - || target.getRootBatch() == null - || (target.getParentBatch() != null && !target.getParentBatch().getId().equals(parentBatch.getId()))) { - - target.setParentBatch(parentBatch); - target.setRootBatch(parentBatch.getRootBatch()); - } - - // RankOrder - target.setRankOrder(rankOrder); - - // Weight or SampleCategoryWeight - if (copyIfNull && source.getWeight() == null) { - // Nothing to do : will be removed later, using notChangedSortingMeasurements - } else if (source.getWeight() != null) { - QuantificationMeasurement quantificationMeasurement = measurementHelper.setQuantificationMeasurement(target, enumeration.PMFM_ID_WEIGHT_MEASURED, recorderDepartmentId, source.getWeight(), true); - notChangedQuantificationMeasurements.remove(quantificationMeasurement); - } - - // Sorting measurement - if (copyIfNull && (source.getLengthStepCaracteristic() == null || source.getLengthStep() == null)) { - // Nothing to do : will be removed later, using notChangedSortingMeasurements - } else if (source.getLengthStepCaracteristic() != null && source.getLengthStep() != null) { - Integer pmfmId = Integer.valueOf(source.getLengthStepCaracteristic().getId()); - SortingMeasurement sortingMeasurement = measurementHelper.setSortingMeasurement(target, recorderDepartmentId, pmfmId, source.getLengthStep()); - notChangedSortingMeasurements.remove(sortingMeasurement); - } - - // Individual count - if (copyIfNull && source.getNumber() == null) { - target.setIndividualCount(null); - } else if (source.getNumber() != null) { - target.setIndividualCount(source.getNumber()); - } - - // Species - target.setReferenceTaxon(null); - - // QualityFlag - target.setQualityFlag(parentBatch.getQualityFlag()); - - // Comments - if (copyIfNull && source.getComment() == null) { - target.setComments(null); - } else if (source.getComment() != null) { - target.setComments(source.getComment()); - } - - // Removed not changed measurements (in sorting and quantification measurement lists) - if (target.getQuantificationMeasurements() != null && notChangedQuantificationMeasurements.size() > 0) { - for (QuantificationMeasurement qm : notChangedQuantificationMeasurements) { - target.getQuantificationMeasurements().remove(qm); - } - } - if (target.getSortingMeasurements() != null && notChangedSortingMeasurements.size() > 0) { - for (SortingMeasurement sm : notChangedSortingMeasurements) { - target.getSortingMeasurements().remove(sm); - } - } - } - - private SpeciesBatchFrequency loadSpeciesBatchFrequency(Object[] source, Map<String, List<SpeciesBatchFrequency>> batchFrequenciesMapByParentId) { - SpeciesBatchFrequency target = new SpeciesBatchFrequency(); - - int colIndex = 0; - target.setId(source[colIndex++].toString()); - - // Individual count - target.setNumber((Integer) source[colIndex++]); - - // Covert database weight (and sampling ratio) into UI weight - Float sourceWeight = (Float) source[colIndex++]; - Float sourceSamplingRatio = (Float) source[colIndex++]; - String sourceSamplingRatioText = (String) source[colIndex++]; - UIWeight uiWeight = convertDatabase2UI(sourceWeight, sourceSamplingRatio, sourceSamplingRatioText); - target.setWeight(uiWeight.weight); - - target.setComment((String) source[colIndex++]); - - // Length step category - Integer lengthPmfmId = (Integer) source[colIndex++]; - Caracteristic lengthStepCaracteristic = referentialService.getCaracteristic(lengthPmfmId); - target.setLengthStepCaracteristic(lengthStepCaracteristic); - - // Qualitative value (should be null) - Preconditions.checkState(source[colIndex++] == null, "Invalid batch tree format : batch frequency could not have a qualitative value."); - - // Length (skip qvValue and alphaValue column) - target.setLengthStep((Float) source[colIndex++]); - - // Alphanumerical value (should be null) - Preconditions.checkState(source[colIndex++] == null, "Invalid batch tree format : batch frequency could not have a alphanumerical value."); - - // Taxon (should be null) - Preconditions.checkState(source[colIndex++] == null, "Invalid batch tree format : taxon frequency could not have species."); - - Integer parentBatchId = (Integer) source[colIndex++]; - - // Add target into the result map - List<SpeciesBatchFrequency> parentBatchFrequencies = batchFrequenciesMapByParentId.get(parentBatchId.toString()); - if (parentBatchFrequencies == null) { - parentBatchFrequencies = Lists.newArrayList(); - batchFrequenciesMapByParentId.put(parentBatchId.toString(), parentBatchFrequencies); - } - parentBatchFrequencies.add(target); - - return target; - } - - protected boolean couldBeASpeciesBatchFrequency(Object[] source) { - Integer pmfmId = (Integer) source[6]; - Integer referenceTaxonId = (Integer) source[10]; - Float numericalValue = (Float) source[8]; - Integer parentbatchId = (Integer) source[11]; - SampleCategoryEnum sampleCategory = referentialService.getSampleCategoryByPmfmId(pmfmId); - - // Batch frequency is a batch with : - // - a numerical value - // - a parent - // - no species - // - no corresponding sample category - return numericalValue != null && parentbatchId != null && referenceTaxonId == null && sampleCategory == null; - } - - protected UIWeight convertDatabase2UI(Float weight, Float samplingRatio, String samplingRatioText) { - UIWeight result = new UIWeight(); - - // Weight & sampleCategory Weight - if (samplingRatio == null) { - result.sampleCategoryWeight = weight; - } else if (weight != null) { - String startStr = weight.toString().replace(',', '.') + "/"; - if (samplingRatioText != null && samplingRatioText.startsWith(startStr)) { - String weightStr = samplingRatioText.substring(startStr.length()); - if (weightStr != null && !weightStr.isEmpty()) { - result.sampleCategoryWeight = Float.parseFloat(weightStr); - result.weight = weight; - } - } - else { - result.sampleCategoryWeight = weight; - } - } - return result; - } - - static class UIWeight { - Float sampleCategoryWeight = null; - - Float weight = null; - } -} Modified: trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/TuttiEnumerationFile.java =================================================================== --- trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/TuttiEnumerationFile.java 2013-02-14 10:40:25 UTC (rev 412) +++ trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/TuttiEnumerationFile.java 2013-02-14 15:27:16 UTC (rev 413) @@ -188,6 +188,12 @@ @Value("${TaxonGroupTypeCode.COMMERCIAL_SPECIES}") public final String TAXON_GROUP_TYPE_ID_COMMERCIAL_SPECIES = null; + @Value("${ReferenceTaxonId.LIFE}") + public final Integer REFERENCE_TAXON_ID_LIFE = null; + + @Value("${ReferenceTaxonId.INERT}") + public final Integer REFERENCE_TAXON_ID_INERT = null; + public void init() { Field[] declaredFields = getClass().getDeclaredFields(); Modified: trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/TuttiPersistenceServiceLocator.java =================================================================== --- trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/TuttiPersistenceServiceLocator.java 2013-02-14 10:40:25 UTC (rev 412) +++ trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/TuttiPersistenceServiceLocator.java 2013-02-14 15:27:16 UTC (rev 413) @@ -80,13 +80,18 @@ FishingOperationPersistenceService.class); } + public static BatchPersistenceService getBatchPersistenceService() { + return getPersistenceService("batchPersistenceService", + BatchPersistenceService.class); + } + public static CatchBatchPersistenceService getCatchBatchPersistenceService() { - return getPersistenceService("catchBatchPersistenceService", - CatchBatchPersistenceService.class); + return getPersistenceService("batchPersistenceService", + CatchBatchPersistenceService.class); } public static SpeciesBatchPersistenceService getSpeciesBatchPersistenceService() { - return getPersistenceService("speciesBatchPersistenceService", + return getPersistenceService("batchPersistenceService", SpeciesBatchPersistenceService.class); } Modified: trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/measure/MeasurementPersistenceHelper.java =================================================================== --- trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/measure/MeasurementPersistenceHelper.java 2013-02-14 10:40:25 UTC (rev 412) +++ trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/measure/MeasurementPersistenceHelper.java 2013-02-14 15:27:16 UTC (rev 413) @@ -206,6 +206,19 @@ return sortingMeasurement; } + + public SortingMeasurement getInheritedSortingMeasurement( + SortingBatch sortingBatch, Integer pmfmId) { + if (sortingBatch.getInheritedSortingMeasurements() != null) { + for (SortingMeasurement qm : sortingBatch + .getInheritedSortingMeasurements()) { + if (pmfmId.equals(qm.getPmfm().getId())) { + return qm; + } + } + } + return null; + } public Integer sampleCategory2PmfmId(SampleCategoryEnum sampleCategory) { Integer pmfmId = null; Modified: trunk/tutti-persistence/src/main/resources/applicationContext-service-tutti.xml =================================================================== --- trunk/tutti-persistence/src/main/resources/applicationContext-service-tutti.xml 2013-02-14 10:40:25 UTC (rev 412) +++ trunk/tutti-persistence/src/main/resources/applicationContext-service-tutti.xml 2013-02-14 15:27:16 UTC (rev 413) @@ -53,8 +53,8 @@ <property name="diskExpiryThreadIntervalSeconds" value="300"/> </bean> - <bean id="tuttiPmfmsCache" parent="tuttiAbstractEternalCache"> - <property name="cacheName" value="pmfms" /> + <bean id="tuttiBatchTreeCache" parent="tuttiAbstractCache"> + <property name="cacheName" value="batchTree" /> </bean> <!-- Eternal caches : --> @@ -67,6 +67,10 @@ <property name="timeToIdle" value="0"/> </bean> + <bean id="tuttiPmfmsCache" parent="tuttiAbstractEternalCache"> + <property name="cacheName" value="pmfms" /> + </bean> + <bean id="tuttiFishingVesselsCache" parent="tuttiAbstractEternalCache"> <property name="cacheName" value="fishingVessels" /> </bean> Modified: trunk/tutti-persistence/src/main/resources/i18n/tutti-persistence_fr_FR.properties =================================================================== --- trunk/tutti-persistence/src/main/resources/i18n/tutti-persistence_fr_FR.properties 2013-02-14 10:40:25 UTC (rev 412) +++ trunk/tutti-persistence/src/main/resources/i18n/tutti-persistence_fr_FR.properties 2013-02-14 15:27:16 UTC (rev 413) @@ -12,4 +12,7 @@ tutti.option.persistence.jdbc.url.description=URL de connexion à la base de données tutti.option.persistence.jdbc.username.description=Login de l'utilisateur pour se connecter à la base de données tutti.option.persistence.protocol.directory.description=Répertoire où sont conservés les protocoles +tutti.persistence.batch.validation.onlyTaxonButPmfmFound=Batch [id\=%s] should not have any sorting measurement (should only have a reference taxon), but found pmfm [id\=%s]. +tutti.persistence.batch.validation.pmfmNotFound=Batch [id\=%s] should have a sorting measurement with a pmfm id in %s or a length pmfm, but found pmfm [id\=%s]. +tutti.persistence.batch.validation.referenceTaxonNotFound=Batch [id\=%s] should have a reference taxon. tutti.persistence.config=Configuration de la persistence de Tutti Modified: trunk/tutti-persistence/src/main/resources/queries-override.hbm.xml =================================================================== --- trunk/tutti-persistence/src/main/resources/queries-override.hbm.xml 2013-02-14 10:40:25 UTC (rev 412) +++ trunk/tutti-persistence/src/main/resources/queries-override.hbm.xml 2013-02-14 15:27:16 UTC (rev 413) @@ -310,77 +310,6 @@ <query-param name="pmfmIdSortingType" type="java.lang.Integer"/> </query> - <query name="allSpeciesBatch"> - <![CDATA[ - SELECT - b.id as batchId, - b.individualCount AS individualCount, - qm.numericalValue AS weight, - b.samplingRatio AS samplingRatio, - b.samplingRatioText AS samplingRatioText, - b.comments AS comments, - sm.pmfm.id AS pmfmId, - sm.qualitativeValue.id as qvValue, - sm.numericalValue AS numValue, - sm.alphanumericalValue AS alphaValue, - b.referenceTaxon.id as referenceTaxonId, - b.parentBatch.id as parentBatchId - FROM - SortingBatchImpl b - INNER JOIN b.rootBatch cb - LEFT OUTER JOIN b.sortingMeasurements sm - LEFT OUTER JOIN b.quantificationMeasurements qm - WHERE - cb.fishingOperation.id=:fishingOperationId - AND ( - qm is null - OR qm.isReferenceQuantification=true - ) - ORDER BY b.id - ]]> - <query-param name="fishingOperationId" type="java.lang.Integer"/> - </query> - - <query name="parentBatch"> - <![CDATA[ - SELECT - b2.id as parentBatchId, - cb.id as rootBatchId - FROM - CatchBatchImpl cb - INNER JOIN cb.childBatchs b1 - INNER JOIN b1.childBatchs b2, - SortingMeasurementImpl sm1, - SortingMeasurementImpl sm2 - WHERE - cb.fishingOperation.id = :fishingOperationId - AND sm1.sortingBatch.id=b1.id - AND sm1.pmfm.id=:pmfmIdSorted - AND sm1.qualitativeValue.id=:qualitativeIdSorted - AND sm2.sortingBatch.id=b2.id - AND sm2.pmfm.id=:pmfmIdSortingType - AND sm2.qualitativeValue.id=:qualitativeIdSortingType - ]]> - <query-param name="fishingOperationId" type="java.lang.Integer"/> - <query-param name="pmfmIdSorted" type="java.lang.Integer"/> - <query-param name="qualitativeIdSorted" type="java.lang.Integer"/> - <query-param name="pmfmIdSortingType" type="java.lang.Integer"/> - <query-param name="qualitativeIdSortingType" type="java.lang.Integer"/> - </query> - - <query name="speciesBatchChildren"> - <![CDATA[ - SELECT - cb.id - FROM - SortingBatchImpl b - INNER JOIN b.childBatchs cb - WHERE - b.id = :batchId - ]]> - <query-param name="batchId" type="java.lang.Integer"/> - </query> - <query name="updateBatchSpecies"> <![CDATA[ UPDATE SortingBatchImpl b @@ -815,16 +744,6 @@ <!--<fetch-profile name="tutti">--> <!--TODO Create fetch profile to avoid eager loading --> <!--</fetch-profile>--> - - <fetch-profile name="batch-with-measurements"> - <fetch entity="BatchImpl" association="quantificationMeasurements" style="join"/> - <fetch entity="CatchBatchImpl" association="quantificationMeasurements" style="join"/> - <fetch entity="SortingBatchImpl" association="sortingMeasurements" style="join"/> - <fetch entity="SortingBatchImpl" association="quantificationMeasurements" style="join"/> - </fetch-profile> - <fetch-profile name="batch-with-childs"> - <fetch entity="BatchImpl" association="childBatchs" style="join"/> - </fetch-profile> - + </hibernate-mapping> Modified: trunk/tutti-persistence/src/main/resources/tutti-db-conf.properties =================================================================== --- trunk/tutti-persistence/src/main/resources/tutti-db-conf.properties 2013-02-14 10:40:25 UTC (rev 412) +++ trunk/tutti-persistence/src/main/resources/tutti-db-conf.properties 2013-02-14 15:27:16 UTC (rev 413) @@ -46,4 +46,6 @@ hibernate.generate_statistics=false hibernate.query.substitutions=true 1, false 0 hibernate.hbm2ddl.auto=none -hibernate.default_batch_fetch_size=1 \ No newline at end of file +hibernate.default_batch_fetch_size=1 +adagio.cache.use_tree_cache=true +ehcache.disk.store.dir=c:/temp/ehcache \ No newline at end of file Modified: trunk/tutti-persistence/src/main/resources/tutti-db-enumerations.properties =================================================================== --- trunk/tutti-persistence/src/main/resources/tutti-db-enumerations.properties 2013-02-14 10:40:25 UTC (rev 412) +++ trunk/tutti-persistence/src/main/resources/tutti-db-enumerations.properties 2013-02-14 15:27:16 UTC (rev 413) @@ -375,4 +375,10 @@ DepartmentId.UNKNOWN_RECORDER_DEPARTMENT=181 #TODO A creer (dans les enumerations Allegro) -ProgramCode.SCIENTIFIC_CRUISE_PREFIX=CAM- \ No newline at end of file +ProgramCode.SCIENTIFIC_CRUISE_PREFIX=CAM- + +#Reference taxon correspondant à "Biota" (ou "Vie") +ReferenceTaxonId.LIFE=7637 +#Reference taxon correspondant à "Non Biota" (ou "Non Vie" - matière inerte) +# TODO : a creer dans la base harmonie et a�changer ! +ReferenceTaxonId.INERT=1 \ No newline at end of file Added: trunk/tutti-persistence/src/test/java/fr/ifremer/tutti/persistence/service/BatchPersistenceServiceReadTest.java =================================================================== --- trunk/tutti-persistence/src/test/java/fr/ifremer/tutti/persistence/service/BatchPersistenceServiceReadTest.java (rev 0) +++ trunk/tutti-persistence/src/test/java/fr/ifremer/tutti/persistence/service/BatchPersistenceServiceReadTest.java 2013-02-14 15:27:16 UTC (rev 413) @@ -0,0 +1,187 @@ +package fr.ifremer.tutti.persistence.service; + +/* + * #%L + * Tutti :: Persistence API + * $Id: CatchBatchPersistenceServiceReadTest.java 379 2013-02-10 13:41:29Z tchemit $ + * $HeadURL: http://svn.forge.codelutin.com/svn/tutti/trunk/tutti-persistence/src/test/ja... $ + * %% + * Copyright (C) 2012 - 2013 Ifremer + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import static org.junit.Assert.*; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; +import java.util.Map; + +import fr.ifremer.tutti.persistence.DatabaseResource; +import fr.ifremer.tutti.persistence.entities.data.CatchBatch; +import fr.ifremer.tutti.persistence.entities.data.Cruise; +import fr.ifremer.tutti.persistence.entities.data.FishingOperation; +import fr.ifremer.tutti.persistence.entities.data.SampleCategoryEnum; +import fr.ifremer.tutti.persistence.entities.data.SpeciesBatch; +import fr.ifremer.tutti.persistence.entities.data.SpeciesBatchFrequency; +import fr.ifremer.tutti.persistence.entities.referential.CaracteristicQualitativeValue; + +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Ignore; +import org.junit.Test; +import org.springframework.dao.DataRetrievalFailureException; + +import com.google.common.collect.Maps; + +/** + * To test {@link CatchBatchPersistenceService} for read operation. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.0 + */ +public class BatchPersistenceServiceReadTest { + + @ClassRule + public static final DatabaseResource dbResource = DatabaseResource.readDb(); + + protected BatchPersistenceService service; + protected FishingOperationPersistenceService fishingOperationService; + protected FishingOperation fishingOperation; + + @Before + public void setUp() throws Exception { + service = TuttiPersistenceServiceLocator.getBatchPersistenceService(); + fishingOperationService = TuttiPersistenceServiceLocator.getFishingOperationPersistenceService(); + + List<FishingOperation> fishingOperations = fishingOperationService.getAllFishingOperation(dbResource.getFixtures().cruiseId()); + assertNotNull(fishingOperations); + assertTrue(fishingOperations.size() > 0); + fishingOperation = fishingOperations.get(0); + assertNotNull(fishingOperation); + assertNotNull(fishingOperation.getId()); + } + + @Test + public void getCatchBatchFromFishingOperation() throws Exception { + + try { + CatchBatch catchBatch = service.getCatchBatchFromFishingOperation(fishingOperation.getId()); + fail("batch tree must be invalid (old CGFS tree structure), for fishing operation id=" + fishingOperation.getId()); + } + catch(DataRetrievalFailureException drfe) { + // success + } + } + + @Test + public void getAllRootSpeciesBatch(/*String fishingOperationId*/) { + } + + @Test + public void getAllSpeciesBatchFrequency(/*String speciesBatchId*/) { + + } + + public static void assertSpeciesBatch(SpeciesBatch expectedBatch, SpeciesBatch actualBatch, boolean assertIdEquals) { + assertNotNull(actualBatch); + assertNotNull(actualBatch.getId()); + if (assertIdEquals && expectedBatch.getId() != null) { + assertEquals(expectedBatch.getId(), actualBatch.getId()); + } + assertEquals(expectedBatch.getWeight(), actualBatch.getWeight()); + assertEquals(expectedBatch.getSampleCategoryType(), actualBatch.getSampleCategoryType()); + if (expectedBatch.getSampleCategoryValue() != null && expectedBatch.getSampleCategoryValue() instanceof CaracteristicQualitativeValue) { + assertNotNull("Bad sampleCategoryValue : expected <" + ((CaracteristicQualitativeValue) expectedBatch.getSampleCategoryValue()).getId() + "> but was <null>", + actualBatch.getSampleCategoryValue()); + assertEquals( + ((CaracteristicQualitativeValue) expectedBatch.getSampleCategoryValue()).getId(), + ((CaracteristicQualitativeValue) actualBatch.getSampleCategoryValue()).getId()); + } else { + assertEquals(expectedBatch.getSampleCategoryValue(), actualBatch.getSampleCategoryValue()); + } + assertEquals(expectedBatch.getSampleCategoryWeight(), actualBatch.getSampleCategoryWeight()); + assertEquals(expectedBatch.getNumber(), actualBatch.getNumber()); + assertEquals(expectedBatch.getComment(), actualBatch.getComment()); + + // Check species only if Vrac/HorsVrac or if batch has been load throw getAllxxx method + // (Because getSpeciesBatch(id) could not always retrieve the species) + if (expectedBatch.getSpecies() != null && ( + expectedBatch.getSampleCategoryType() == SampleCategoryEnum.sortedUnsorted + || actualBatch.getSpecies() != null)) { + assertNotNull(actualBatch.getSpecies()); + assertEquals(expectedBatch.getSpecies().getId(), actualBatch.getSpecies().getId()); + } + } + + public static void assertBatchFrequencies(List<SpeciesBatchFrequency> expectedFrequencies, List<SpeciesBatchFrequency> actualFrequencies, boolean assertIdEquals) { + assertNotNull(actualFrequencies); + assertEquals(expectedFrequencies.size(), actualFrequencies.size()); + + // Store actual batches into a map, using the length as key + Map<Float, SpeciesBatchFrequency> expectedLengthMap = Maps.newHashMap(); + for (SpeciesBatchFrequency speciesBatchFrequency : expectedFrequencies) { + expectedLengthMap.put(speciesBatchFrequency.getLengthStep(), speciesBatchFrequency); + } + + // Store expected batches into a map, using the length as key + Map<Float, SpeciesBatchFrequency> actualLengthMap = Maps.newHashMap(); + for (SpeciesBatchFrequency speciesBatchFrequency : actualFrequencies) { + assertFalse("Duplicate lengthStep found in batchFrequencies, for length=" + speciesBatchFrequency.getLengthStep(), actualLengthMap.containsKey(speciesBatchFrequency.getLengthStep())); + actualLengthMap.put(speciesBatchFrequency.getLengthStep(), speciesBatchFrequency); + assertNotNull(speciesBatchFrequency.getId()); + } + + for (Float lengthStep : expectedLengthMap.keySet()) { + SpeciesBatchFrequency expectedBatchFrequency = expectedLengthMap.get(lengthStep); + SpeciesBatchFrequency actualBatchFrequency = actualLengthMap.get(lengthStep); + if (assertIdEquals) { + assertEquals(expectedBatchFrequency.getId(), actualBatchFrequency.getId()); + } + assertNotNull(expectedBatchFrequency.getLengthStepCaracteristic()); + assertEquals(expectedBatchFrequency.getLengthStepCaracteristic().getId(), actualBatchFrequency.getLengthStepCaracteristic().getId()); + assertEquals(expectedBatchFrequency.getNumber(), actualBatchFrequency.getNumber()); + assertEquals(expectedBatchFrequency.getWeight(), actualBatchFrequency.getWeight()); + assertEquals(expectedBatchFrequency.getComment(), actualBatchFrequency.getComment()); + //assertNotNull(expectedBatchFrequency.getBatch()); + //assertEquals(expectedBatchFrequency.getBatch().getId(), actualBatchFrequency.getBatch().getId()); + } + } + + public static SpeciesBatch getSpeciesBatch(String fishingOperationId, String speciesBatchId) { + return getSpeciesBatch(speciesBatchId, TuttiPersistenceServiceLocator.getBatchPersistenceService().getAllRootSpeciesBatch(fishingOperationId)); + } + + public static SpeciesBatch getSpeciesBatch(String speciesBatchId, List<SpeciesBatch> speciesBatchs) { + if (speciesBatchs == null) { + return null; + } + for (SpeciesBatch speciesBatch : speciesBatchs) { + if (speciesBatchId.equals(speciesBatch.getId())) { + return speciesBatch; + } + if (speciesBatch.getChildBatchs() != null) { + speciesBatch = getSpeciesBatch(speciesBatchId, speciesBatch.getChildBatchs()); + if (speciesBatch != null) { + return speciesBatch; + } + } + } + return null; + } + +} Added: trunk/tutti-persistence/src/test/java/fr/ifremer/tutti/persistence/service/BatchPersistenceServiceWriteTest.java =================================================================== --- trunk/tutti-persistence/src/test/java/fr/ifremer/tutti/persistence/service/BatchPersistenceServiceWriteTest.java (rev 0) +++ trunk/tutti-persistence/src/test/java/fr/ifremer/tutti/persistence/service/BatchPersistenceServiceWriteTest.java 2013-02-14 15:27:16 UTC (rev 413) @@ -0,0 +1,621 @@ +package fr.ifremer.tutti.persistence.service; + +/* + * #%L + * Tutti :: Persistence API + * $Id: CatchBatchPersistenceServiceWriteTest.java 379 2013-02-10 13:41:29Z tchemit $ + * $HeadURL: http://svn.forge.codelutin.com/svn/tutti/trunk/tutti-persistence/src/test/ja... $ + * %% + * Copyright (C) 2012 - 2013 Ifremer + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import fr.ifremer.tutti.persistence.DatabaseResource; +import fr.ifremer.tutti.persistence.entities.data.CatchBatch; +import fr.ifremer.tutti.persistence.entities.data.Cruise; +import fr.ifremer.tutti.persistence.entities.data.FishingOperation; +import fr.ifremer.tutti.persistence.entities.data.SampleCategoryEnum; +import fr.ifremer.tutti.persistence.entities.data.SpeciesBatch; +import fr.ifremer.tutti.persistence.entities.data.SpeciesBatchFrequency; +import fr.ifremer.tutti.persistence.entities.referential.Caracteristic; +import fr.ifremer.tutti.persistence.entities.referential.CaracteristicQualitativeValue; +import fr.ifremer.tutti.persistence.entities.referential.CaracteristicType; +import fr.ifremer.tutti.persistence.entities.referential.Species; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Ignore; +import org.junit.Test; +import org.springframework.dao.DataRetrievalFailureException; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.*; + +/** + * To test {@link CatchBatchPersistenceService} for write operation. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.0 + */ +public class BatchPersistenceServiceWriteTest { + + @ClassRule + public static final DatabaseResource dbResource = DatabaseResource.writeDb(); + + protected BatchPersistenceService service; + + protected CruisePersistenceService cruiseService; + + protected FishingOperationPersistenceService fishingOperationService; + + protected CatchBatchPersistenceService catchBatchService; + + protected ReferentialPersistenceService referentialService; + + protected Cruise cruise; + + protected FishingOperation fishingOperationNoCatchBatch; + + protected FishingOperation fishingOperationWithEmptyBatch; + + protected CatchBatch catchBacth; + + protected List<Species> species; + + protected Caracteristic sortedUnsortedPMFM; + + protected CaracteristicQualitativeValue horsVracQualitativeValue; + + protected CaracteristicQualitativeValue vracQualitativeValue; + + protected Caracteristic maturityPMFM; + + protected CaracteristicQualitativeValue firstMaturityQualitativeValue; + + protected Caracteristic sexPMFM; + + protected CaracteristicQualitativeValue maleQualitativeValue; + + protected CaracteristicQualitativeValue femaleQualitativeValue; + + protected CaracteristicQualitativeValue unkQualitativeValue; + + protected Caracteristic frequencyPMFM; + + @Before + public void setUp() throws Exception { + service = TuttiPersistenceServiceLocator.getBatchPersistenceService(); + cruiseService = TuttiPersistenceServiceLocator.getCruisePersistenceService(); + fishingOperationService = TuttiPersistenceServiceLocator.getFishingOperationPersistenceService(); + catchBatchService = TuttiPersistenceServiceLocator.getCatchBatchPersistenceService(); + referentialService = TuttiPersistenceServiceLocator.getReferentialPersistenceService(); + + species = referentialService.getAllSpecies(); + assertNotNull(species); + assertTrue(species.size() > 2); + + cruise = cruiseService.getCruise(dbResource.getFixtures().cruiseId()); + cruise.setId(null); + Calendar calendar = new GregorianCalendar(); + cruise.setBeginDate(calendar.getTime()); + cruise.setYear(calendar.get(Calendar.YEAR)); + calendar.add(Calendar.MONTH, 1); // add one month + cruise.setEndDate(calendar.getTime()); + cruise = cruiseService.createCruise(cruise); + + // Create a first operation, with no cacth batch : to test CatchBatch insert/update : + List<FishingOperation> fishingOperations = fishingOperationService.getAllFishingOperation(dbResource.getFixtures().cruiseId()); + assertNotNull(fishingOperations); + assertTrue(fishingOperations.size() > 0); + fishingOperationNoCatchBatch = fishingOperations.get(0); + fishingOperationNoCatchBatch = fishingOperationService.getFishingOperation(fishingOperationNoCatchBatch.getId()); + fishingOperationNoCatchBatch.setId(null); + fishingOperationNoCatchBatch.setCruise(cruise); + calendar.setTime(new Date()); + calendar.set(Calendar.HOUR_OF_DAY, 1); + calendar.set(Calendar.MILLISECOND, 0); + fishingOperationNoCatchBatch.setGearShootingStartDate(calendar.getTime()); + calendar.setTime(new Date()); + calendar.set(Calendar.HOUR_OF_DAY, 10); + calendar.set(Calendar.MILLISECOND, 0); + fishingOperationNoCatchBatch.setGearShootingEndDate(calendar.getTime()); + fishingOperationNoCatchBatch = fishingOperationService.createFishingOperation(fishingOperationNoCatchBatch); + + // Create a second operation, with no cacth batch : to test CatchBatch insert/update : + fishingOperationWithEmptyBatch = fishingOperations.get(1); + fishingOperationWithEmptyBatch = fishingOperationService.getFishingOperation(fishingOperationWithEmptyBatch.getId()); + fishingOperationWithEmptyBatch.setId(null); + fishingOperationWithEmptyBatch.setCruise(cruise); + calendar.setTime(new Date()); + calendar.set(Calendar.HOUR_OF_DAY, 11); + calendar.set(Calendar.MILLISECOND, 0); + fishingOperationWithEmptyBatch.setGearShootingStartDate(calendar.getTime()); + calendar.setTime(new Date()); + calendar.set(Calendar.HOUR_OF_DAY, 12); + calendar.set(Calendar.MILLISECOND, 0); + fishingOperationWithEmptyBatch.setGearShootingEndDate(calendar.getTime()); + fishingOperationWithEmptyBatch = fishingOperationService.createFishingOperation(fishingOperationWithEmptyBatch); + + catchBacth = new CatchBatch(); + catchBacth.setFishingOperation(fishingOperationWithEmptyBatch); + catchBacth = catchBatchService.createCatchBatch(catchBacth); + + sortedUnsortedPMFM = referentialService.getSortedUnsortedCaracteristic(); + horsVracQualitativeValue = sortedUnsortedPMFM.getQualitativeValue(0); + vracQualitativeValue = sortedUnsortedPMFM.getQualitativeValue(1); + maturityPMFM = referentialService.getMaturityCaracteristic(); + firstMaturityQualitativeValue = maturityPMFM.getQualitativeValue(0); + sexPMFM = referentialService.getSexCaracteristic(); + maleQualitativeValue = sexPMFM.getQualitativeValue(1); + femaleQualitativeValue = sexPMFM.getQualitativeValue(2); + unkQualitativeValue = sexPMFM.getQualitativeValue(3); + + List<Caracteristic> cara = referentialService.getAllCaracteristic(); + for (Caracteristic caracteristic : cara) { + if (caracteristic.getCaracteristicType() == CaracteristicType.NUMBER + && caracteristic.getPrecision() != null + && caracteristic.getPrecision() == 0.5f) { + frequencyPMFM = caracteristic; + break; + } + } + assertNotNull("no numerical PMFM with a precision has been found. Could not define a PMFM for batch frequencies.", frequencyPMFM); + + } + + @Test + public void createAndSaveCatchBatch() throws Exception { + CatchBatch catchBatch; + + catchBatch = new CatchBatch(); + catchBatch.setFishingOperation(fishingOperationNoCatchBatch); + + // ----------------------------------------------------------------------------- + // 1. Test with only mandatory properties + // ----------------------------------------------------------------------------- + + // Create and reload (test round trip) + assertCreateAndReloadCatchBatch(catchBatch, fishingOperationNoCatchBatch.getId()); + + // ----------------------------------------------------------------------------- + // 2. Test with all properties + // ----------------------------------------------------------------------------- + catchBatch.setId(null); + // total weight : 100kg + catchBatch.setCatchTotalWeight(75f); + // Vrac : + { + // note : poids trie par la balance tremis (thalassa) (init par pupitri) + catchBatch.setCatchTotalSortedTremisWeight(50f); + // note : poids vrac caroussel (thalassa) (init par pupitri) (vrac trie) ou bien "poids trié fournie par la table de tri (Sum(Si) + catchBatch.setCatchTotalSortedCarousselWeight(45f); + + // Species + { + catchBatch.setSpeciesTotalSortedWeight(12f); + catchBatch.setSpeciesTotalSampleSortedWeight(8f); + catchBatch.setSpeciesTotalLivingNotItemizedWeight(0.2f); + catchBatch.setSpeciesTotalInertWeight(0.1f); + } + } + // Hors Vrac : 10kg + { + catchBatch.setCatchTotalUnsortedWeight(10f); + + // Species + { + catchBatch.setSpeciesTotalUnsortedWeight(10f); + } + } + // Rejet : 15kg + catchBatch.setCatchTotalRejectedWeight(15f); + + // Create and reload (test round trip) + assertCreateAndReloadCatchBatch(catchBatch, fishingOperationNoCatchBatch.getId()); + + // ----------------------------------------------------------------------------- + // 2. Test save after modification + // ----------------------------------------------------------------------------- + catchBatch.setCatchTotalSortedTremisWeight(null); + catchBatch.setCatchTotalSortedCarousselWeight(null); + catchBatch.setSpeciesTotalSortedWeight(null); + catchBatch.setSpeciesTotalSampleSortedWeight(null); + catchBatch.setCatchTotalUnsortedWeight(null); + catchBatch.setSpeciesTotalUnsortedWeight(null); + + assertSaveAndReloadCatchBatch(catchBatch, fishingOperationNoCatchBatch.getId()); + } + + @Test + public void createAndSaveSpeciesBatchAndFrequencies() { + SpeciesBatch esp1Batch = null; + SpeciesBatch esp2Batch = null; + SpeciesBatch frequenciesParentBatch = null; + SpeciesBatch batch = null; + Species taxon1 = species.get(0); + Species taxon2 = species.get(1); + + // ----------------------------------------------------------------------------- + // 1. Test with only mandatory properties + // ----------------------------------------------------------------------------- + // batch : "ESP1 - Vrac/5" + batch = new SpeciesBatch(); + batch.setParentBatch(null); + batch.setFishingOperation(fishingOperationNoCatchBatch); + batch.setSpecies(taxon1); + batch.setSampleCategoryType(SampleCategoryEnum.sortedUnsorted); + batch.setSampleCategoryValue(vracQualitativeValue); + batch.setSampleCategoryWeight(5f); + + assertCreateAndReloadSpeciesBatch(batch, null); + + // Save ESP1 batch + esp1Batch = batch; + + // ----------------------------------------------------------------------------- + // 2. Test child "Male/2" + // ----------------------------------------------------------------------------- + // Batch : ESP1 - Vrac/5 Male/2 ss-ech/1 Nombre/7 + batch = new SpeciesBatch(); + batch.setId(null); + batch.setParentBatch(esp1Batch); + batch.setSpecies(taxon1); + batch.setComment("ESP1 - Vrac/5 Male/2 ss-ech/1 Nombre/7"); + batch.setSampleCategoryType(SampleCategoryEnum.sex); + batch.setSampleCategoryValue(maleQualitativeValue); + batch.setSampleCategoryWeight(2f); + batch.setWeight(1f); + batch.setNumber(7); + + assertCreateAndReloadSpeciesBatch(batch, batch.getParentBatch().getId()); + + // ----------------------------------------------------------------------------- + // 3. Test child "Female/2" + // ----------------------------------------------------------------------------- + // Batch : ESP1 - Vrac/5 Female/3 Nombre/14 + batch = new SpeciesBatch(); + batch.setId(null); + batch.setParentBatch(esp1Batch); + batch.setSpecies(taxon1); + batch.setComment("ESP1 - Vrac/5 Female/3 Nombre/14"); + batch.setSampleCategoryType(SampleCategoryEnum.sex); + batch.setSampleCategoryValue(femaleQualitativeValue); + batch.setSampleCategoryWeight(3f); + batch.setWeight(null); + batch.setNumber(14); + + assertCreateAndReloadSpeciesBatch(batch, batch.getParentBatch().getId()); + + // ----------------------------------------------------------------------------- + // 4. Test : ESP2 - Vrac/7 + // \- ESP2 - Vrac/7 UNK/2 ss-ech/1 Nombre/11 + // ----------------------------------------------------------------------------- + // batch : "ESP2 - Vrac/7 " + batch = new SpeciesBatch(); + batch.setParentBatch(null); + batch.setSpecies(taxon2); + batch.setSampleCategoryType(SampleCategoryEnum.sortedUnsorted); + batch.setSampleCategoryValue(vracQualitativeValue); + batch.setSampleCategoryWeight(7f); + + assertCreateAndReloadSpeciesBatch(batch, null); + esp2Batch = batch; + + // Batch : ESP2 - Vrac/7 UNK/2 ss-ech/1 Nombre/11 + batch = new SpeciesBatch(); + batch.setId(null); + batch.setParentBatch(esp2Batch); + batch.setSpecies(taxon2); + batch.setComment("ESP2 - Vrac/7 UNK/2 ss-ech/1 Nombre/11"); + batch.setSampleCategoryType(SampleCategoryEnum.maturity); + batch.setSampleCategoryValue(firstMaturityQualitativeValue); + batch.setSampleCategoryWeight(2f); + batch.setWeight(1f); + batch.setNumber(11); + + assertCreateAndReloadSpeciesBatch(batch, batch.getParentBatch().getId()); + + // ----------------------------------------------------------------------------- + // 5. Test save after modifications + // ----------------------------------------------------------------------------- + // Batch : ESP2 - Vrac/7 UNK/1.75 ss-ech/1.11 Nombre/99 + batch.setComment("ESP2 - Vrac/7 UNK/1.75 ss-ech/1.11 Nombre/99"); + batch.setSampleCategoryType(SampleCategoryEnum.sex); + batch.setSampleCategoryValue(unkQualitativeValue); + batch.setSampleCategoryWeight(1.75f); + batch.setWeight(1.11f); + batch.setFishingOperation(fishingOperationWithEmptyBatch); + batch.setNumber(99); + + // Save and reload, then check + SpeciesBatch savedBatch = service.saveSpeciesBatch(batch); + assertSpeciesBatch(savedBatch, batch, false); + SpeciesBatch reloadedBatch = getSpeciesBatch(fishingOperationWithEmptyBatch.getId(), savedBatch.getId()); + assertSpeciesBatch(savedBatch, reloadedBatch, true); + + // Save batch for later + frequenciesParentBatch = batch; + + // ----------------------------------------------------------------------------- + // 6. Test change species + // ----------------------------------------------------------------------------- + esp2Batch.setSpecies(taxon1); + service.changeSpeciesBatchSpecies(esp2Batch.getId(), taxon1); + assertSpeciesBatch(savedBatch, batch, false); + reloadedBatch = getSpeciesBatch(fishingOperationWithEmptyBatch.getId(), esp2Batch.getId()); + assertSpeciesBatch(esp2Batch, reloadedBatch, true); + + // ----------------------------------------------------------------------------- + // 7. Test get all root species + // ----------------------------------------------------------------------------- + List<SpeciesBatch> rootSpeciesBatch = service.getAllRootSpeciesBatch(fishingOperationWithEmptyBatch.getId()); + assertNotNull(rootSpeciesBatch); + assertEquals(2, rootSpeciesBatch.size()); + assertNotNull(rootSpeciesBatch.get(0).getChildBatchs()); + assertTrue(rootSpeciesBatch.get(0).getChildBatchs().size() > 0); + assertNotNull(rootSpeciesBatch.get(1).getChildBatchs()); + assertTrue(rootSpeciesBatch.get(1).getChildBatchs().size() > 0); + + // ----------------------------------------------------------------------------- + // 8. Test batch frequency creation + // ----------------------------------------------------------------------------- + + List<SpeciesBatchFrequency> frequencies = Lists.newArrayList(); + float lengthStep = 0.5f; + for (float length = lengthStep; length < lengthStep * 20; length += lengthStep) { + SpeciesBatchFrequency frequency = new SpeciesBatchFrequency(); + frequency.setLengthStep(length); + frequency.setNumber((int) (length * 2)); + frequency.setWeight(0.01f * length * 2); + frequency.setLengthStepCaracteristic(frequencyPMFM); + frequency.setBatch(frequenciesParentBatch); + frequency.setComment("comments"); + frequencies.add(frequency); + } + List<SpeciesBatchFrequency> createdFrequencies = assertCreateAndReloadSpeciesBatchFrequency(frequencies, frequenciesParentBatch.getId()); + + // ----------------------------------------------------------------------------- + // 9. Test batch frequency update + // ----------------------------------------------------------------------------- + // Update some batchs (1cm, 2cm, etc) + for (SpeciesBatchFrequency speciesBatchFrequency : createdFrequencies) { + float length = speciesBatchFrequency.getLengthStep(); + if ((float) (int) length == length) { + speciesBatchFrequency.setNumber(12); + speciesBatchFrequency.setComment(null); + } + } + // And remove the last item (should be deleted in DB) + createdFrequencies.remove(createdFrequencies.size()-1); + List<SpeciesBatchFrequency> savedFrequencies = service.saveSpeciesBatchFrequency(frequenciesParentBatch.getId(), frequencies); + assertBatchFrequencies(createdFrequencies, savedFrequencies, true); + } + + @Test + public void deleteSpeciesBatch(/*String id*/) { + SpeciesBatch esp1Batch; + SpeciesBatch batch; + Species taxon1 = species.get(0); + + // ----------------------------------------------------------------------------- + // 1. Create two batchs (parent + child), then remove the parent batch + // ----------------------------------------------------------------------------- + // batch : ESP1 Vrac/5 + batch = new SpeciesBatch(); + batch.setParentBatch(null); + batch.setFishingOperation(fishingOperationWithEmptyBatch); + batch.setSpecies(taxon1); + batch.setSampleCategoryType(SampleCategoryEnum.sortedUnsorted); + batch.setSampleCategoryValue(vracQualitativeValue); + batch.setSampleCategoryWeight(5f); + assertCreateAndReloadSpeciesBatch(batch, null); + esp1Batch = batch; + + // batch : ESP1 Vrac/5 Male/2 + batch = new SpeciesBatch(); + batch.setParentBatch(esp1Batch); + batch.setFishingOperation(fishingOperationWithEmptyBatch); + batch.setSpecies(taxon1); + batch.setSampleCategoryType(SampleCategoryEnum.sex); + batch.setSampleCategoryValue(maleQualitativeValue); + batch.setSampleCategoryWeight(2f); + assertCreateAndReloadSpeciesBatch(batch, esp1Batch.getId()); + + // Try to remove + service.deleteSpeciesBatch(esp1Batch.getId()); + + // Check if remove + try { + batch = getSpeciesBatch(fishingOperationWithEmptyBatch.getId(), esp1Batch.getId()); + assertNull(batch); + } catch (DataRetrievalFailureException drfe) { + assertNotNull(drfe); + } + } + + protected void assertCreateAndReloadSpeciesBatch(SpeciesBatch batch, String parentBatchId) { + batch.setFishingOperation(fishingOperationWithEmptyBatch); + + // Create batch + SpeciesBatch createdBatch = service.createSpeciesBatch(batch, parentBatchId); + assertSpeciesBatch(batch, createdBatch, false); + + // then reload (for round trip check) + SpeciesBatch reloadedBatch = getSpeciesBatch(fishingOperationWithEmptyBatch.getId(), createdBatch.getId()); + if (parentBatchId == null) { + assertNull(reloadedBatch.getParentBatch()); + } else { + assertNotNull(reloadedBatch.getParentBatch()); + assertEquals(parentBatchId, reloadedBatch.getParentBatch().getId()); + } + assertSpeciesBatch(createdBatch, reloadedBatch, false); + + batch.setId(createdBatch.getId()); + } + + protected void assertCreateAndReloadCatchBatch(CatchBatch catchBatch, String fishingOperationId) { + CatchBatch createdCatchBatch = service.createCatchBatch(catchBatch); + assertNotNull(createdCatchBatch); + assertNotNull(createdCatchBatch.getId()); + assertCatchBatch(catchBatch, createdCatchBatch, false); + + CatchBatch reloadedCatchBatch = service.getCatchBatchFromFishingOperation(fishingOperationId); + assertCatchBatch(createdCatchBatch, reloadedCatchBatch, true); + + catchBatch.setId(createdCatchBatch.getId()); + } + + protected void assertSaveAndReloadCatchBatch(CatchBatch catchBatch, String fishingOperationId) { + CatchBatch savedCatchBatch = service.saveCatchBatch(catchBatch); + assertNotNull(savedCatchBatch); + assertNotNull(savedCatchBatch.getId()); + assertCatchBatch(catchBatch, savedCatchBatch, false); + + CatchBatch reloadedCatchBatch = service.getCatchBatchFromFishingOperation(fishingOperationId); + assertCatchBatch(savedCatchBatch, reloadedCatchBatch, true); + } + + protected void assertCatchBatch(CatchBatch expectedCatchBatch,CatchBatch actualCatchBatch, boolean assertIdEquals) { + if (expectedCatchBatch == null) { + assertNull(actualCatchBatch); + return; + } + + assertNotNull(actualCatchBatch); + if (assertIdEquals) { + assertEquals(expectedCatchBatch.getId(), actualCatchBatch.getId()); + } + assertEquals(expectedCatchBatch.getCatchTotalWeight(), actualCatchBatch.getCatchTotalWeight()); + assertEquals(expectedCatchBatch.getCatchTotalSortedCarousselWeight(), actualCatchBatch.getCatchTotalSortedCarousselWeight()); + assertEquals(expectedCatchBatch.getCatchTotalSortedTremisWeight(), actualCatchBatch.getCatchTotalSortedTremisWeight()); + assertEquals(expectedCatchBatch.getCatchTotalUnsortedWeight(), actualCatchBatch.getCatchTotalUnsortedWeight()); + + assertEquals(expectedCatchBatch.getSpeciesTotalSampleSortedWeight(), actualCatchBatch.getSpeciesTotalSampleSortedWeight()); + assertEquals(expectedCatchBatch.getSpeciesTotalSortedWeight(), actualCatchBatch.getSpeciesTotalSortedWeight()); + assertEquals(expectedCatchBatch.getSpeciesTotalUnsortedWeight(), actualCatchBatch.getSpeciesTotalUnsortedWeight()); + assertEquals(expectedCatchBatch.getSpeciesTotalInertWeight(), actualCatchBatch.getSpeciesTotalInertWeight()); + assertEquals(expectedCatchBatch.getSpeciesTotalLivingNotItemizedWeight(), actualCatchBatch.getSpeciesTotalLivingNotItemizedWeight()); + } + + protected void assertSpeciesBatch(SpeciesBatch expectedBatch, SpeciesBatch actualBatch, boolean assertIdEquals) { + assertNotNull(actualBatch); + assertNotNull(actualBatch.getId()); + if (assertIdEquals && expectedBatch.getId() != null) { + assertEquals(expectedBatch.getId(), actualBatch.getId()); + } + assertEquals(expectedBatch.getWeight(), actualBatch.getWeight()); + assertEquals(expectedBatch.getSampleCategoryType(), actualBatch.getSampleCategoryType()); + if (expectedBatch.getSampleCategoryValue() != null && expectedBatch.getSampleCategoryValue() instanceof CaracteristicQualitativeValue) { + assertNotNull("Bad sampleCategoryValue : expected <" + ((CaracteristicQualitativeValue) expectedBatch.getSampleCategoryValue()).getId() + "> but was <null>", + actualBatch.getSampleCategoryValue()); + assertEquals( + ((CaracteristicQualitativeValue) expectedBatch.getSampleCategoryValue()).getId(), + ((CaracteristicQualitativeValue) actualBatch.getSampleCategoryValue()).getId()); + } else { + assertEquals(expectedBatch.getSampleCategoryValue(), actualBatch.getSampleCategoryValue()); + } + assertEquals(expectedBatch.getSampleCategoryWeight(), actualBatch.getSampleCategoryWeight()); + assertEquals(expectedBatch.getNumber(), actualBatch.getNumber()); + assertEquals(expectedBatch.getComment(), actualBatch.getComment()); + + // Check species only if Vrac/HorsVrac or if batch has been load throw getAllxxx method + // (Because getSpeciesBatch(id) could not always retrieve the species) + if (expectedBatch.getSpecies() != null && ( + expectedBatch.getSampleCategoryType() == SampleCategoryEnum.sortedUnsorted + || actualBatch.getSpecies() != null)) { + assertNotNull(actualBatch.getSpecies()); + assertEquals(expectedBatch.getSpecies().getId(), actualBatch.getSpecies().getId()); + } + } + protected List<SpeciesBatchFrequency> assertCreateAndReloadSpeciesBatchFrequency(List<SpeciesBatchFrequency> frequencies, String parentBatchId) { + + // Create batch + List<SpeciesBatchFrequency> createdFrequencies = service.saveSpeciesBatchFrequency(parentBatchId, frequencies); + assertBatchFrequencies(frequencies, createdFrequencies, false); + + // then reload (for round trip check) + List<SpeciesBatchFrequency> reloadedFrequencies = service.getAllSpeciesBatchFrequency(parentBatchId); + assertBatchFrequencies(createdFrequencies, reloadedFrequencies, true); + + return createdFrequencies; + } + + protected void assertBatchFrequencies(List<SpeciesBatchFrequency> expectedFrequencies, List<SpeciesBatchFrequency> actualFrequencies, boolean assertIdEquals) { + assertNotNull(actualFrequencies); + assertEquals(expectedFrequencies.size(), actualFrequencies.size()); + + // Store actual batches into a map, using the length as key + Map<Float, SpeciesBatchFrequency> expectedLengthMap = Maps.newHashMap(); + for (SpeciesBatchFrequency speciesBatchFrequency : expectedFrequencies) { + expectedLengthMap.put(speciesBatchFrequency.getLengthStep(), speciesBatchFrequency); + } + + // Store expected batches into a map, using the length as key + Map<Float, SpeciesBatchFrequency> actualLengthMap = Maps.newHashMap(); + for (SpeciesBatchFrequency speciesBatchFrequency : actualFrequencies) { + assertFalse("Duplicate lengthStep found in batchFrequencies, for length=" + speciesBatchFrequency.getLengthStep(), actualLengthMap.containsKey(speciesBatchFrequency.getLengthStep())); + actualLengthMap.put(speciesBatchFrequency.getLengthStep(), speciesBatchFrequency); + assertNotNull(speciesBatchFrequency.getId()); + } + + for (Float lengthStep : expectedLengthMap.keySet()) { + SpeciesBatchFrequency expectedBatchFrequency = expectedLengthMap.get(lengthStep); + SpeciesBatchFrequency actualBatchFrequency = actualLengthMap.get(lengthStep); + if (assertIdEquals) { + assertEquals(expectedBatchFrequency.getId(), actualBatchFrequency.getId()); + } + assertNotNull(expectedBatchFrequency.getLengthStepCaracteristic()); + assertEquals(expectedBatchFrequency.getLengthStepCaracteristic().getId(), actualBatchFrequency.getLengthStepCaracteristic().getId()); + assertEquals(expectedBatchFrequency.getNumber(), actualBatchFrequency.getNumber()); + assertEquals(expectedBatchFrequency.getWeight(), actualBatchFrequency.getWeight()); + assertEquals(expectedBatchFrequency.getComment(), actualBatchFrequency.getComment()); + //assertNotNull(expectedBatchFrequency.getBatch()); + //assertEquals(expectedBatchFrequency.getBatch().getId(), actualBatchFrequency.getBatch().getId()); + } + } + + protected SpeciesBatch getSpeciesBatch(String fishingOperationId, String speciesBatchId) { + return getSpeciesBatch(speciesBatchId, service.getAllRootSpeciesBatch(fishingOperationId)); + } + + protected SpeciesBatch getSpeciesBatch(String speciesBatchId, List<SpeciesBatch> speciesBatchs) { + if (speciesBatchs == null) { + return null; + } + for (SpeciesBatch speciesBatch : speciesBatchs) { + if (speciesBatchId.equals(speciesBatch.getId())) { + return speciesBatch; + } + if (speciesBatch.getChildBatchs() != null) { + speciesBatch = getSpeciesBatch(speciesBatchId, speciesBatch.getChildBatchs()); + if (speciesBatch != null) { + return speciesBatch; + } + } + } + return null; + } +}