branch feature/8256 created (now abb60a4)
This is an automated email from the git hooks/post-receive script. New change to branch feature/8256 in repository tutti. See https://gitlab.nuiton.org/codelutin/tutti.git at abb60a4 Utilisation des caches de campagnes This branch includes the following new commits: new c80d374 ajout toString new c0998d6 Revue de l'API de cache pour avoir un cache de haut niveau sur les cruise puis des caches dédiés new dbdef2d Revue du chargement des caches de campagne new abb60a4 Utilisation des caches de campagnes The 4 revisions listed above as "new" are entirely new to this repository and will be described in separate emails. The revisions listed as "adds" were already present in the repository and have only been added to this reference. Detailed log of new commits: commit abb60a40e675965c84686ccbb512bd9d1328e61b Author: Tony CHEMIT <chemit@codelutin.com> Date: Sun Apr 17 07:36:09 2016 +0200 Utilisation des caches de campagnes commit dbdef2da4edd97ac634bc5c4d42a60ae0c63c8cb Author: Tony CHEMIT <chemit@codelutin.com> Date: Sun Apr 17 07:35:51 2016 +0200 Revue du chargement des caches de campagne commit c0998d61c99c033888bb6fca3c0131d10c7a9fd0 Author: Tony CHEMIT <chemit@codelutin.com> Date: Sun Apr 17 07:35:26 2016 +0200 Revue de l'API de cache pour avoir un cache de haut niveau sur les cruise puis des caches dédiés commit c80d374b8be5d6a5e967bffd7f60b9acef7bc1b1 Author: Tony CHEMIT <chemit@codelutin.com> Date: Sun Apr 17 07:34:51 2016 +0200 ajout toString -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.
This is an automated email from the git hooks/post-receive script. New commit to branch feature/8256 in repository tutti. See https://gitlab.nuiton.org/codelutin/tutti.git commit c80d374b8be5d6a5e967bffd7f60b9acef7bc1b1 Author: Tony CHEMIT <chemit@codelutin.com> Date: Sun Apr 17 07:34:51 2016 +0200 ajout toString --- .../persistence/entities/data/FishingOperationBean.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/entities/data/FishingOperationBean.java b/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/entities/data/FishingOperationBean.java index 4585788..51ed6f6 100644 --- a/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/entities/data/FishingOperationBean.java +++ b/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/entities/data/FishingOperationBean.java @@ -24,11 +24,12 @@ package fr.ifremer.tutti.persistence.entities.data; * #L% */ +import com.google.common.base.MoreObjects; import fr.ifremer.tutti.util.Numbers; public class FishingOperationBean extends AbstractFishingOperationBean { - private static final long serialVersionUID = 3918757535832892722L; + private static final long serialVersionUID = 1L; @Override public void setGearShootingStartLatitude(Float gearShootingStartLatitude) { @@ -49,4 +50,15 @@ public class FishingOperationBean extends AbstractFishingOperationBean { public void setGearShootingEndLongitude(Float gearShootingEndLongitude) { super.setGearShootingEndLongitude(Numbers.roundDecimalCoordinateComponent(gearShootingEndLongitude)); } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add(PROPERTY_ID, id) + .add(PROPERTY_STATION_NUMBER, stationNumber) + .add(PROPERTY_FISHING_OPERATION_NUMBER, fishingOperationNumber) + .add(PROPERTY_MULTIRIG_AGGREGATION, multirigAggregation) + .add(PROPERTY_GEAR_SHOOTING_START_DATE, gearShootingStartDate) + .toString(); + } } -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.
This is an automated email from the git hooks/post-receive script. New commit to branch feature/8256 in repository tutti. See https://gitlab.nuiton.org/codelutin/tutti.git commit c0998d61c99c033888bb6fca3c0131d10c7a9fd0 Author: Tony CHEMIT <chemit@codelutin.com> Date: Sun Apr 17 07:35:26 2016 +0200 Revue de l'API de cache pour avoir un cache de haut niveau sur les cruise puis des caches dédiés --- .../tutti/service/sampling/CruiseCache.java | 141 +++++++ .../tutti/service/sampling/CruiseCacheAble.java | 46 +++ .../tutti/service/sampling/CruiseCacheLoader.java | 149 +++++++ .../service/sampling/CruiseSamplingCache.java | 451 ++++++++++----------- .../sampling/CruiseSamplingCacheLoader.java | 156 ------- .../tutti/service/sampling/SamplingCodeCache.java | 113 ++++++ 6 files changed, 652 insertions(+), 404 deletions(-) diff --git a/tutti-service/src/main/java/fr/ifremer/tutti/service/sampling/CruiseCache.java b/tutti-service/src/main/java/fr/ifremer/tutti/service/sampling/CruiseCache.java new file mode 100644 index 0000000..98bf67f --- /dev/null +++ b/tutti-service/src/main/java/fr/ifremer/tutti/service/sampling/CruiseCache.java @@ -0,0 +1,141 @@ +package fr.ifremer.tutti.service.sampling; + +import com.google.common.base.MoreObjects; +import fr.ifremer.tutti.persistence.entities.data.FishingOperation; +import fr.ifremer.tutti.persistence.entities.data.IndividualObservationBatch; +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.Collection; +import java.util.Objects; +import java.util.Optional; + +/** + * Le cache de données pour une campagne. Ce cache contient tous les caches plus spécifiques + * (codes de prélèvement, algorithme de prélèvement de pièces calcifiées,...). + * + * Created on 16/04/16. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 4.5 + */ +public class CruiseCache implements CruiseCacheAble { + + /** Logger. */ + private static final Log log = LogFactory.getLog(CruiseCache.class); + /** + * L'identifiant de la campagne associée à ce cache. + */ + private final int cruiseId; + /** + * L'identificant du protocol associé à ce cache. + */ + private final String protocolId; + /** + * Le cache optioanel lié à l'algorithme de prélèvement des pièces calcifiées. + */ + private final CruiseSamplingCache cruiseSamplingCache; + /** + * Le cache des codes de prélèvement disponibles. + */ + private final SamplingCodeCache samplingCodeCache; + + public CruiseCache(Integer cruiseId, String protocolId, CruiseSamplingCache cruiseSamplingCache, SamplingCodeCache samplingCodeCache) { + Objects.requireNonNull(cruiseId); + Objects.requireNonNull(samplingCodeCache); + this.cruiseId = cruiseId; + this.protocolId = protocolId; + this.cruiseSamplingCache = cruiseSamplingCache; + this.samplingCodeCache = samplingCodeCache; + } + + public boolean isCacheUpToDate(Integer cruiseId, String protocolId) { + return Objects.equals(this.cruiseId, cruiseId) && Objects.equals(this.protocolId, protocolId); + } + + public boolean useSamplingCache() { + return cruiseSamplingCache != null; + } + + public Integer getCruiseId() { + return cruiseId; + } + + public String getProtocolId() { + return protocolId; + } + + public Optional<CruiseSamplingCache> getSamplingCruiseCache() { + return Optional.ofNullable(cruiseSamplingCache); + } + + public SamplingCodeCache getSamplingCodeCache() { + return samplingCodeCache; + } + + @Override + public void addIndividualObservations(FishingOperation fishingOperation, Collection<IndividualObservationBatch> individualObservations) { + + if (useSamplingCache()) { + cruiseSamplingCache.addIndividualObservations(fishingOperation, individualObservations); + } + + samplingCodeCache.addIndividualObservations(fishingOperation, individualObservations); + + } + + @Override + public void removeIndividualObservations(FishingOperation fishingOperation, Collection<IndividualObservationBatch> individualObservations) { + + if (useSamplingCache()) { + cruiseSamplingCache.removeIndividualObservations(fishingOperation, individualObservations); + } + + samplingCodeCache.removeIndividualObservations(fishingOperation, individualObservations); + + } + + @Override + public void addFishingOperation(FishingOperation fishingOperation, Collection<IndividualObservationBatch> individualObservations) { + + if (useSamplingCache()) { + cruiseSamplingCache.addFishingOperation(fishingOperation, individualObservations); + } + + samplingCodeCache.addFishingOperation(fishingOperation, individualObservations); + + } + + @Override + public void removeFishingOperation(FishingOperation fishingOperation, Collection<IndividualObservationBatch> individualObservations) { + + if (useSamplingCache()) { + cruiseSamplingCache.removeFishingOperation(fishingOperation, individualObservations); + } + + samplingCodeCache.removeFishingOperation(fishingOperation, individualObservations); + + } + + @Override + public void close() { + + if (log.isInfoEnabled()) { + log.info("Closing cruise cache: " + this); + } + if (useSamplingCache()) { + IOUtils.closeQuietly(cruiseSamplingCache); + } + IOUtils.closeQuietly(samplingCodeCache); + } + + @Override + public String toString() { + MoreObjects.ToStringHelper toStringHelper = MoreObjects.toStringHelper(this); + if (cruiseSamplingCache != null) { + toStringHelper.add("cruiseSamplingCache", cruiseSamplingCache); + } + return toStringHelper.add("samplingCodeCache", samplingCodeCache).toString(); + } +} diff --git a/tutti-service/src/main/java/fr/ifremer/tutti/service/sampling/CruiseCacheAble.java b/tutti-service/src/main/java/fr/ifremer/tutti/service/sampling/CruiseCacheAble.java new file mode 100644 index 0000000..88e2015 --- /dev/null +++ b/tutti-service/src/main/java/fr/ifremer/tutti/service/sampling/CruiseCacheAble.java @@ -0,0 +1,46 @@ +package fr.ifremer.tutti.service.sampling; + +import fr.ifremer.tutti.persistence.entities.data.FishingOperation; +import fr.ifremer.tutti.persistence.entities.data.IndividualObservationBatch; + +import java.io.Closeable; +import java.util.Collection; + +/** + * Created on 17/04/16. + * + * @author Tony Chemit - chemit@codelutin.com + */ +public interface CruiseCacheAble extends Closeable { + + /** + * Ajout de toutes les observations individuelles de l'opération de pêche dans le cache. + * + * @param fishingOperation l'opération de pêche concernée + */ + void addFishingOperation(FishingOperation fishingOperation, Collection<IndividualObservationBatch> individualObservations); + + /** + * Suppression de toutes les observations individuelles du cache. + * + * @param fishingOperation l'opération de pêche concernée + */ + void removeFishingOperation(FishingOperation fishingOperation, Collection<IndividualObservationBatch> individualObservations); + + /** + * Ajout des plusieurs échantillons qui sont sur la m$eme opération de pêche dans le cache. + * + * @param fishingOperation l'opération de pêche concernée + * @param individualObservations les observations à ajouter au cache + */ + void addIndividualObservations(FishingOperation fishingOperation, Collection<IndividualObservationBatch> individualObservations); + + /** + * Suppression de plusieurs échantillons qui sont sur la même opération de pêche du cache. + * + * @param fishingOperation l'opération de pêche concernée + * @param individualObservations les observations individuelles à supprimer du cache + */ + void removeIndividualObservations(FishingOperation fishingOperation, Collection<IndividualObservationBatch> individualObservations); + +} diff --git a/tutti-service/src/main/java/fr/ifremer/tutti/service/sampling/CruiseCacheLoader.java b/tutti-service/src/main/java/fr/ifremer/tutti/service/sampling/CruiseCacheLoader.java new file mode 100644 index 0000000..db4c529 --- /dev/null +++ b/tutti-service/src/main/java/fr/ifremer/tutti/service/sampling/CruiseCacheLoader.java @@ -0,0 +1,149 @@ +package fr.ifremer.tutti.service.sampling; + +/* + * #%L + * Tutti :: Service + * $Id:$ + * $HeadURL:$ + * %% + * Copyright (C) 2012 - 2016 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.ProgressionModel; +import fr.ifremer.tutti.persistence.entities.data.FishingOperation; +import fr.ifremer.tutti.persistence.entities.data.IndividualObservationBatch; +import fr.ifremer.tutti.persistence.entities.protocol.TuttiProtocol; +import fr.ifremer.tutti.persistence.entities.referential.Caracteristic; +import fr.ifremer.tutti.service.DecoratorService; +import fr.ifremer.tutti.service.PersistenceService; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.decorator.Decorator; + +import java.util.Collection; +import java.util.List; + +import static org.nuiton.i18n.I18n.t; + +/** + * Pour charger le cache de données de campagnes. + * + * Created on 20/03/16. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 4.5 + */ +public class CruiseCacheLoader { + + /** Logger. */ + private static final Log log = LogFactory.getLog(CruiseCacheLoader.class); + + private final PersistenceService persistenceService; + private final DecoratorService decoratorService; + private final ProgressionModel progressionModel; + private final CruiseCache cruiseCache; + + public static CruiseCacheLoader newCacheLoader(PersistenceService persistenceService, + DecoratorService decoratorService, + ProgressionModel progressionModel, + TuttiProtocol protocol, + Integer cruiseId) { + + boolean loadSamplingCache = protocol != null && protocol.isUseCalcifiedPieceSampling(); + + CruiseSamplingCache cruiseSamplingCache; + + if (loadSamplingCache) { + + Caracteristic sexCaracteristic = persistenceService.getSexCaracteristic(); + + Collection<Caracteristic> maturityCaracteristics = persistenceService.getMaturityCaracteristics(persistenceService.getAllCaracteristic()); + cruiseSamplingCache = new CruiseSamplingCache(protocol, sexCaracteristic, maturityCaracteristics); + + } else { + + cruiseSamplingCache = null; + + } + + CruiseCache cruiseCache = new CruiseCache(cruiseId, protocol == null ? null : protocol.getId(), cruiseSamplingCache, new SamplingCodeCache()); + return new CruiseCacheLoader(persistenceService, decoratorService, progressionModel, cruiseCache); + } + + public static CruiseCacheLoader newCacheLoader(PersistenceService persistenceService, + DecoratorService decoratorService, + ProgressionModel progressionModel, + CruiseCache cruiseCache) { + return new CruiseCacheLoader(persistenceService, decoratorService, progressionModel, cruiseCache); + } + + public CruiseCache loadCruiseCache() { + + if (log.isInfoEnabled()) { + log.info("Loading cruise cache: " + cruiseCache); + } + + Decorator<FishingOperation> fishingOperationDecorator = decoratorService.getDecoratorByType(FishingOperation.class); + + persistenceService.getAllFishingOperationIds(cruiseCache.getCruiseId()).forEach(fishingOperationId -> { + + FishingOperation fishingOperation = persistenceService.getFishingOperation(fishingOperationId); + + progressionModel.increments(t("tutti.cruise.cacheLoader.loading.fishingOperation", fishingOperationDecorator.toString(fishingOperation))); + + loadCruiseCacheForFishingOperation(fishingOperation); + + }); + + if (log.isInfoEnabled()) { + log.info("Cruise cache loaded: " + cruiseCache); + } + + return cruiseCache; + } + + public CruiseCache loadCruiseCacheForFishingOperation(FishingOperation fishingOperation) { + + if (log.isInfoEnabled()) { + log.info("Loading cruise cache for fishing operation: " + fishingOperation + " → " + cruiseCache); + } + + List<IndividualObservationBatch> individualObservations = + persistenceService.getAllIndividualObservationBatchsForFishingOperation(fishingOperation.getIdAsInt()); + + cruiseCache.addFishingOperation(fishingOperation, individualObservations); + + if (log.isInfoEnabled()) { + log.info("Cruise cache loaded for fishing operation: " + fishingOperation + " → " + cruiseCache); + } + + return cruiseCache; + + } + + private CruiseCacheLoader(PersistenceService persistenceService, + DecoratorService decoratorService, + ProgressionModel progressionModel, + CruiseCache cruiseCache) { + this.persistenceService = persistenceService; + this.decoratorService = decoratorService; + this.progressionModel = progressionModel; + this.cruiseCache = cruiseCache; + } + +} diff --git a/tutti-service/src/main/java/fr/ifremer/tutti/service/sampling/CruiseSamplingCache.java b/tutti-service/src/main/java/fr/ifremer/tutti/service/sampling/CruiseSamplingCache.java index 6ce0fd0..ad39cb7 100644 --- a/tutti-service/src/main/java/fr/ifremer/tutti/service/sampling/CruiseSamplingCache.java +++ b/tutti-service/src/main/java/fr/ifremer/tutti/service/sampling/CruiseSamplingCache.java @@ -26,7 +26,6 @@ package fr.ifremer.tutti.service.sampling; import com.google.common.base.MoreObjects; import com.google.common.collect.HashMultimap; -import com.google.common.collect.Maps; import com.google.common.collect.Multimap; import fr.ifremer.tutti.persistence.entities.TuttiEntities; import fr.ifremer.tutti.persistence.entities.data.FishingOperation; @@ -40,12 +39,10 @@ import fr.ifremer.tutti.persistence.entities.referential.CaracteristicQualitativ import fr.ifremer.tutti.persistence.entities.referential.Species; import fr.ifremer.tutti.persistence.entities.referential.TuttiLocation; import fr.ifremer.tutti.util.Numbers; -import org.apache.commons.lang3.mutable.MutableInt; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import javax.swing.event.EventListenerList; -import java.io.Closeable; import java.util.Collection; import java.util.HashMap; import java.util.List; @@ -58,7 +55,7 @@ import java.util.Set; * @author Kevin Morin (Code Lutin) * @since 4.5 */ -public class CruiseSamplingCache implements Closeable { +public class CruiseSamplingCache implements CruiseCacheAble { /** Logger. */ private static final Log log = LogFactory.getLog(CruiseSamplingCache.class); @@ -104,27 +101,13 @@ public class CruiseSamplingCache implements Closeable { */ private final EventListenerList listeners = new EventListenerList(); /** - * L'identifiant de la campagne associée à ce cache. - */ - private final Integer cruiseId; - /** - * L'identificant du protocol associé à ce cache. - */ - private final String protocolId; - /** * Un drapeau pour indiquer qu'on est en train de construire le cache et donc ne déclancher aucun listener. */ private boolean loading; - /** - * Le code prélèvement le plus grand pour chaque espèce. - */ - private final Map<Integer, MutableInt> highestSamplingCodeBySpecies = new HashMap<>(); - public CruiseSamplingCache(int cruiseId, TuttiProtocol protocol, Caracteristic sexCaracteristic, Collection<Caracteristic> maturityCaracteristics) { - this.cruiseId = cruiseId; + public CruiseSamplingCache(TuttiProtocol protocol, Caracteristic sexCaracteristic, Collection<Caracteristic> maturityCaracteristics) { this.sexCaracteristic = sexCaracteristic; - this.sexQualitativeValues = Maps.uniqueIndex(sexCaracteristic.getQualitativeValue(), TuttiEntities.GET_ID_AS_INT); - this.protocolId = protocol.getId(); + this.sexQualitativeValues = TuttiEntities.splitByIdAsInt(sexCaracteristic.getQualitativeValue()); locationIdsPerZone = HashMultimap.create(); protocol.getZone().forEach(zone -> locationIdsPerZone.putAll(zone, Zones.getAllLocationIds(zone))); @@ -141,14 +124,6 @@ public class CruiseSamplingCache implements Closeable { protocol.getMaturityCaracteristics().forEach(mc -> matureStatesByMaturityCracteristic.putAll(mc.getId(), mc.getMatureStateIds())); } - public int getCruiseId() { - return cruiseId; - } - - public String getProtocolId() { - return protocolId; - } - public boolean isLoading() { return loading; } @@ -158,89 +133,207 @@ public class CruiseSamplingCache implements Closeable { } @Override - public void close() { - if (log.isInfoEnabled()) { - log.info("Closing cruise sampling cache."); - } - totalCruiseCache.close(); - zoneCache.close(); - operationCache.close(); - locationIdsPerZone.clear(); - cpsDefinitionsBySpecies.clear(); - maturityCaracteristicBySpecies.clear(); - sexQualitativeValues.clear(); - matureStatesByMaturityCracteristic.clear(); - SamplingListener[] samplingListeners = listeners.getListeners(SamplingListener.class); - for (SamplingListener listener : samplingListeners) { - removeSamplingListener(listener); - } + public void addFishingOperation(FishingOperation fishingOperation, Collection<IndividualObservationBatch> individualObservations) { + + addIndividualObservations(fishingOperation, individualObservations); + } @Override - public String toString() { - return MoreObjects.toStringHelper(this) - .add("cruiseId", cruiseId) - .add("protocolId", protocolId) - .add("totalCruiseCache", totalCruiseCache.size()) - .add("zoneCache", zoneCache.size()) - .add("operationCache", operationCache.size()) - .toString(); + public void addIndividualObservations(FishingOperation fishingOperation, Collection<IndividualObservationBatch> individualObservations) { + + Objects.requireNonNull(fishingOperation); + Objects.requireNonNull(individualObservations); + + setLoading(true); + + try { + + + Zone optionalZone = tryFindZone(fishingOperation).orElse(null); + int fishingOperationId = fishingOperation.getIdAsInt(); + + for (IndividualObservationBatch individualObservationBatch : individualObservations) { + + Optional<CalcifiedPiecesSamplingDefinition> optionalCalcifiedPiecesSamplingDefinition = + tryToFindCalcifiedPiecesSamplingDefinition(individualObservationBatch); + + if (!optionalCalcifiedPiecesSamplingDefinition.isPresent()) { + + // pas dans l'algorithme, one ne tient pas compte de cette observation + continue; + } + + Species species = individualObservationBatch.getSpecies(); + Objects.requireNonNull(species); + + // l'observation a forcement une taille + Float lengthStep = individualObservationBatch.getSize(); + Objects.requireNonNull(lengthStep); + + Boolean maturity = getMaturity(individualObservationBatch); + + int lengthStepInMm = Numbers.convertToMm(lengthStep, individualObservationBatch.getLengthStepCaracteristic().getUnit()); + + CaracteristicQualitativeValue gender = individualObservationBatch.getCaracteristics().getQualitativeValue(sexCaracteristic); + + CalcifiedPiecesSamplingDefinition calcifiedPiecesSamplingDefinition = optionalCalcifiedPiecesSamplingDefinition.get(); + + addIndividualObservation(calcifiedPiecesSamplingDefinition, fishingOperationId, optionalZone, species, gender, maturity, lengthStepInMm); + + String samplingCode = individualObservationBatch.getSamplingCode(); + if (samplingCode != null) { + + addSampling(calcifiedPiecesSamplingDefinition, fishingOperationId, optionalZone, species, gender, maturity, lengthStepInMm); + + } + + } + + } finally { + + setLoading(false); + + } + } - /** - * Ajout d'un échantillon dans le cache. - * - * @param fishingOperationId l'identifiant de l'opération de pêche concernée - * @param optionalZone la zone (facultative) de l'opération de pêche concernée - * @param individualObservationBatchs les observations à ajouter au cache - */ - public void addIndividualObservations(int fishingOperationId, - Zone optionalZone, - List<IndividualObservationBatch> individualObservationBatchs) { + @Override + public void removeIndividualObservations(FishingOperation fishingOperation, Collection<IndividualObservationBatch> individualObservations) { - Objects.requireNonNull(fishingOperationId); -// Objects.requireNonNull(optionalZone); - Objects.requireNonNull(individualObservationBatchs); + Objects.requireNonNull(fishingOperation); + Objects.requireNonNull(individualObservations); + + setLoading(true); + + try { + + Zone optionalZone = tryFindZone(fishingOperation).orElse(null); + int fishingOperationId = fishingOperation.getIdAsInt(); + + for (IndividualObservationBatch individualObservationBatch : individualObservations) { + + Optional<CalcifiedPiecesSamplingDefinition> optionalCalcifiedPiecesSamplingDefinition = + tryToFindCalcifiedPiecesSamplingDefinition(individualObservationBatch); + + if (!optionalCalcifiedPiecesSamplingDefinition.isPresent()) { + + // pas dans l'algorithme, one ne tient pas compte de cette observation + continue; + } - for (IndividualObservationBatch individualObservationBatch : individualObservationBatchs) { + Species species = individualObservationBatch.getSpecies(); + Objects.requireNonNull(species); - Optional<CalcifiedPiecesSamplingDefinition> optionalCalcifiedPiecesSamplingDefinition = - tryToFindCalcifiedPiecesSamplingDefinition(individualObservationBatch); + Boolean maturity = getMaturity(individualObservationBatch); - if (!optionalCalcifiedPiecesSamplingDefinition.isPresent()) { + float lengthStep = individualObservationBatch.getSize(); + int lengthStepInMm = Numbers.convertToMm(lengthStep, individualObservationBatch.getLengthStepCaracteristic().getUnit()); + + CaracteristicQualitativeValue gender = individualObservationBatch.getCaracteristics().getQualitativeValue(sexCaracteristic); + + CalcifiedPiecesSamplingDefinition calcifiedPiecesSamplingDefinition = optionalCalcifiedPiecesSamplingDefinition.get(); + + String samplingCode = individualObservationBatch.getSamplingCode(); + if (samplingCode != null) { + + removeSampling(calcifiedPiecesSamplingDefinition, fishingOperationId, optionalZone, species, gender, maturity, lengthStepInMm); + + } + + removeIndividualObservation(calcifiedPiecesSamplingDefinition, fishingOperationId, optionalZone, species, gender, maturity, lengthStepInMm); - // pas dans l'algorithme, one ne tient pas compte de cette observation - continue; } - Species species = individualObservationBatch.getSpecies(); - Objects.requireNonNull(species); + } finally { - // l'observation a forcement une taille - Float lengthStep = individualObservationBatch.getSize(); - Objects.requireNonNull(lengthStep); + setLoading(false); - Boolean maturity = getMaturity(individualObservationBatch); + } - int lengthStepInMm = Numbers.convertToMm(lengthStep, individualObservationBatch.getLengthStepCaracteristic().getUnit()); + } - CaracteristicQualitativeValue gender = individualObservationBatch.getCaracteristics().getQualitativeValue(sexCaracteristic); + @Override + public void removeFishingOperation(FishingOperation fishingOperation, Collection<IndividualObservationBatch> individualObservations) { - CalcifiedPiecesSamplingDefinition calcifiedPiecesSamplingDefinition = optionalCalcifiedPiecesSamplingDefinition.get(); + Objects.requireNonNull(fishingOperation); + Objects.requireNonNull(individualObservations); - addIndividualObservation(calcifiedPiecesSamplingDefinition, fishingOperationId, optionalZone, species, gender, maturity, lengthStepInMm); + setLoading(true); - String samplingCode = individualObservationBatch.getSamplingCode(); - if (samplingCode != null) { + try { - addSampling(calcifiedPiecesSamplingDefinition, fishingOperationId, optionalZone, species, gender, maturity, lengthStepInMm, samplingCode); + String fishingOperationId = fishingOperation.getId(); + if (log.isInfoEnabled()) { + log.info("Removing fishing operation: " + fishingOperation + " from " + this); + } + + // suppression de toutes les entrées du cache des opérations (et récupération des clefs) + Set<String> removedKeys = operationCache.removeAllWhereKeyStartingWith(fishingOperationId); + + if (log.isInfoEnabled()) { + log.info("Fishing operation: " + fishingOperation + " removed from operationCache: " + operationCache.size()); + } + + removedKeys.forEach(totalCruiseCache::decrementObservationNb); + + if (log.isInfoEnabled()) { + log.info("Fishing operation: " + fishingOperation + " removed from totalCruiseCache: " + totalCruiseCache.size()); + } + + Optional<Zone> optionalZone = tryFindZone(fishingOperation); + + if (optionalZone.isPresent()) { + String zoneId = optionalZone.get().getId(); + removedKeys.forEach(key -> zoneCache.decrementObservationNbIfExist(CruiseSamplingInternalCache.addPrefixKey(zoneId, key))); + + if (log.isInfoEnabled()) { + log.info("Fishing operation: " + fishingOperation + " removed from zoneCache: " + zoneCache.size()); + } + } + + if (log.isInfoEnabled()) { + log.info("Fishing operation: " + fishingOperation + " removed from " + this); } + } finally { + + setLoading(false); + } } + @Override + public void close() { + + if (log.isInfoEnabled()) { + log.info("Closing cruise sampling cache."); + } + totalCruiseCache.close(); + zoneCache.close(); + operationCache.close(); + locationIdsPerZone.clear(); + cpsDefinitionsBySpecies.clear(); + maturityCaracteristicBySpecies.clear(); + matureStatesByMaturityCracteristic.clear(); + SamplingListener[] samplingListeners = listeners.getListeners(SamplingListener.class); + for (SamplingListener listener : samplingListeners) { + removeSamplingListener(listener); + } + + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("totalCruiseCache", totalCruiseCache.size()) + .add("zoneCache", zoneCache.size()) + .add("operationCache", operationCache.size()) + .toString(); + } + /** * Ajout d'un observation dans le cache. * @@ -279,57 +372,6 @@ public class CruiseSamplingCache implements Closeable { /** * Suppression d'un échantillon du cache. * - * @param fishingOperationId l'identifiant de l'opération de pêche concernée - * @param zone la zone (facultative) de l'opération de pêche concernée - * @param individualObservationBatches les observations individuelles à supprimer du cache - */ - public void removeIndividualObservations(int fishingOperationId, - Zone zone, - Collection<IndividualObservationBatch> individualObservationBatches) { - - Objects.requireNonNull(fishingOperationId); - Objects.requireNonNull(zone); - Objects.requireNonNull(individualObservationBatches); - - for (IndividualObservationBatch individualObservationBatch : individualObservationBatches) { - - Optional<CalcifiedPiecesSamplingDefinition> optionalCalcifiedPiecesSamplingDefinition = - tryToFindCalcifiedPiecesSamplingDefinition(individualObservationBatch); - - if (!optionalCalcifiedPiecesSamplingDefinition.isPresent()) { - - // pas dans l'algorithme, one ne tient pas compte de cette observation - continue; - } - - Species species = individualObservationBatch.getSpecies(); - Objects.requireNonNull(species); - - Boolean maturity = getMaturity(individualObservationBatch); - - float lengthStep = individualObservationBatch.getSize(); - int lengthStepInMm = Numbers.convertToMm(lengthStep, individualObservationBatch.getLengthStepCaracteristic().getUnit()); - - CaracteristicQualitativeValue gender = individualObservationBatch.getCaracteristics().getQualitativeValue(sexCaracteristic); - - CalcifiedPiecesSamplingDefinition calcifiedPiecesSamplingDefinition = optionalCalcifiedPiecesSamplingDefinition.get(); - - String samplingCode = individualObservationBatch.getSamplingCode(); - if (samplingCode != null) { - - removeSampling(calcifiedPiecesSamplingDefinition, fishingOperationId, zone, species, gender, maturity, lengthStepInMm, samplingCode); - - } - - removeIndividualObservation(calcifiedPiecesSamplingDefinition, fishingOperationId, zone, species, gender, maturity, lengthStepInMm); - - } - - } - - /** - * Suppression d'un échantillon du cache. - * * @param fishingOperation l'opération de pêche concernée * @param species l'espèces concernée * @param gender le sexe de l'échantillon (peut-être null) @@ -368,14 +410,12 @@ public class CruiseSamplingCache implements Closeable { * @param gender le sexe de l'échantillon (peut-être null) * @param maturity la maturité de l'échantillon (peut-être null) * @param lengthStep la classe de taille de l'échantillon (en mm) - * @param samplingCode le code de prélèvement ajouté */ public void addSampling(FishingOperation fishingOperation, Species species, CaracteristicQualitativeValue gender, Boolean maturity, - int lengthStep, - String samplingCode) { + int lengthStep) { Objects.requireNonNull(fishingOperation); Objects.requireNonNull(species); @@ -395,7 +435,8 @@ public class CruiseSamplingCache implements Closeable { CalcifiedPiecesSamplingDefinition calcifiedPiecesSamplingDefinition = optionalCalcifiedPiecesSamplingDefinition.get(); - addSampling(calcifiedPiecesSamplingDefinition, fishingOperation.getIdAsInt(), optionalZone.orElse(null), species, gender, maturity, lengthStep, samplingCode); + addSampling(calcifiedPiecesSamplingDefinition, fishingOperation.getIdAsInt(), optionalZone.orElse(null), species, gender, maturity, lengthStep); + } /** @@ -406,14 +447,12 @@ public class CruiseSamplingCache implements Closeable { * @param gender le sexe de l'échantillon (peut-être null) * @param maturity la maturité de l'échantillon (peut-être null) * @param lengthStep la classe de taille de l'échantillon (en mm) - * @param samplingCode le code de prélèvement supprimé */ public void removeSampling(FishingOperation fishingOperation, Species species, CaracteristicQualitativeValue gender, Boolean maturity, - int lengthStep, - String samplingCode) { + int lengthStep) { Objects.requireNonNull(fishingOperation); Objects.requireNonNull(species); @@ -428,52 +467,7 @@ public class CruiseSamplingCache implements Closeable { CalcifiedPiecesSamplingDefinition calcifiedPiecesSamplingDefinition = optionalCalcifiedPiecesSamplingDefinition.get(); - removeSampling(calcifiedPiecesSamplingDefinition, fishingOperation.getIdAsInt(), optionalZone.orElse(null), species, gender, maturity, lengthStep, samplingCode); - - } - - /** - * Suppression de toutes les observations individuelles du cache. - * - * @param fishingOperation l'opération de pêche concernée - */ - public void removeFishingOperation(FishingOperation fishingOperation) { - - Objects.requireNonNull(fishingOperation); - - String fishingOperationId = fishingOperation.getId(); - - if (log.isInfoEnabled()) { - log.info("Remove fishing operation: " + fishingOperationId + " from CruiseSamplingCache: " + this); - } - - // suppression de toutes les entrées du cache des opérations (et récupération des clefs) - Set<String> removedKeys = operationCache.removeAllWhereKeyStartingWith(fishingOperationId); - - if (log.isInfoEnabled()) { - log.info("Fishing operation: " + fishingOperationId + " removed from operationCache: " + operationCache.size()); - } - - removedKeys.forEach(totalCruiseCache::decrementObservationNb); - - if (log.isInfoEnabled()) { - log.info("Fishing operation: " + fishingOperationId + " removed from totalCruiseCache: " + totalCruiseCache.size()); - } - - Optional<Zone> optionalZone = tryFindZone(fishingOperation); - - if (optionalZone.isPresent()) { - String zoneId = optionalZone.get().getId(); - removedKeys.forEach(key -> zoneCache.decrementObservationNbIfExist(CruiseSamplingInternalCache.addPrefixKey(zoneId, key))); - - if (log.isInfoEnabled()) { - log.info("Fishing operation: " + fishingOperationId + " removed from zoneCache: " + zoneCache.size()); - } - } - - if (log.isInfoEnabled()) { - log.info("Fishing operation: " + fishingOperationId + " removed from CruiseSamplingCache: " + this); - } + removeSampling(calcifiedPiecesSamplingDefinition, fishingOperation.getIdAsInt(), optionalZone.orElse(null), species, gender, maturity, lengthStep); } @@ -533,16 +527,12 @@ public class CruiseSamplingCache implements Closeable { } - public Optional<Zone> tryFindZone(FishingOperation operation) { - Optional<Zone> result; - if (operation.getSubStrata() != null) { - result = tryFindZone(operation.getSubStrata()); - } else if (operation.getStrata() != null) { - result = tryFindZone(operation.getStrata()); - } else { - result = Optional.empty(); - } - return result; + public boolean isZoneChanged(FishingOperation operation1, FishingOperation operation2) { + + Optional<Zone> optionalZone1 = tryFindZone(operation1); + Optional<Zone> optionalZone2 = tryFindZone(operation2); + return !Objects.equals(optionalZone1, optionalZone2); + } public Boolean getMaturity(int speciesId, CaracteristicQualitativeValue maturityQualitativeValue) { @@ -554,12 +544,6 @@ public class CruiseSamplingCache implements Closeable { return maturity; } - public int getNextSamplingCodeId(int speciesId) { - MutableInt samplingCode = highestSamplingCodeBySpecies.get(speciesId); - return (samplingCode == null ? 0 : samplingCode.intValue()) + 1; -// return highestSamplingCodeBySpecies.getOrDefault(speciesId, 0) + 1; - } - public void addSamplingListener(SamplingListener listener) { listeners.add(SamplingListener.class, listener); } @@ -568,6 +552,18 @@ public class CruiseSamplingCache implements Closeable { listeners.remove(SamplingListener.class, listener); } + private Optional<Zone> tryFindZone(FishingOperation operation) { + Optional<Zone> result; + if (operation.getSubStrata() != null) { + result = tryFindZone(operation.getSubStrata()); + } else if (operation.getStrata() != null) { + result = tryFindZone(operation.getStrata()); + } else { + result = Optional.empty(); + } + return result; + } + private void fireSamplingNeeded(SamplingEvent event) { SamplingListener[] samplingListeners = listeners.getListeners(SamplingListener.class); @@ -746,7 +742,6 @@ public class CruiseSamplingCache implements Closeable { * @param gender le sexe de l'échantillon (peut-être null) * @param maturity la maturité de l'échantillon (peut-être null) * @param lengthStep la classe de taille de l'échantillon (en mm) - * @param samplingCode le code de prélèvement ajouté */ private void addSampling(CalcifiedPiecesSamplingDefinition calcifiedPiecesSamplingDefinition, int fishingOperationId, @@ -754,8 +749,7 @@ public class CruiseSamplingCache implements Closeable { Species species, CaracteristicQualitativeValue gender, Boolean maturity, - int lengthStep, - String samplingCode) { + int lengthStep) { Objects.requireNonNull(calcifiedPiecesSamplingDefinition); Objects.requireNonNull(fishingOperationId); @@ -784,27 +778,6 @@ public class CruiseSamplingCache implements Closeable { SamplingEvent event = new SamplingEvent(this, lengthStep, gender, maturity, calcifiedPiecesSamplingDefinition, zone, totalSamplingNb, zoneSamplingNb, operationSamplingNb); fireSummaryUpdated(event); - addSamplingCode(species.getReferenceTaxonId(), samplingCode); - - } - - private int addSamplingCode(int speciesId, String samplingCode) { - int code = SamplingCodePrefix.extractSamplingCodeIdFromSamplingCode(samplingCode); - - // increment the highest sampling code if it is this code -// return highestSamplingCodeBySpecies.compute(speciesId, -// (key, highestSamplingCode) -> highestSamplingCode == null ? code : Math.max(highestSamplingCode, code)); - - return highestSamplingCodeBySpecies.compute(speciesId, - (key, highestSamplingCode) -> { - if (highestSamplingCode == null) { - highestSamplingCode = new MutableInt(code); - } else { - int nexValue = Math.max(highestSamplingCode.intValue(), code); - highestSamplingCode.setValue(nexValue); - } - return highestSamplingCode; - }).intValue(); } /** @@ -816,7 +789,6 @@ public class CruiseSamplingCache implements Closeable { * @param gender le sexe de l'échantillon (peut-être null) * @param maturity la maturité de l'échantillon (peut-être null) * @param lengthStep la classe de taille de l'échantillon (en mm) - * @param samplingCode le code de prélèvement supprimé */ private void removeSampling(CalcifiedPiecesSamplingDefinition calcifiedPiecesSamplingDefinition, int fishingOperationId, @@ -824,8 +796,7 @@ public class CruiseSamplingCache implements Closeable { Species species, CaracteristicQualitativeValue gender, Boolean maturity, - int lengthStep, - String samplingCode) { + int lengthStep) { Objects.requireNonNull(calcifiedPiecesSamplingDefinition); Objects.requireNonNull(fishingOperationId); @@ -855,21 +826,6 @@ public class CruiseSamplingCache implements Closeable { SamplingEvent event = new SamplingEvent(this, lengthStep, gender, maturity, calcifiedPiecesSamplingDefinition, zone, totalSamplingNb, zoneSamplingNb, operationSamplingNb); fireSummaryUpdated(event); - removeSamplingCode(species.getReferenceTaxonId(), samplingCode); - - } - - - private void removeSamplingCode(int speciesId, String samplingCode) { - int code = SamplingCodePrefix.extractSamplingCodeIdFromSamplingCode(samplingCode); - - // decrement the highest sampling code if it is this code - MutableInt samplingCodeFound = highestSamplingCodeBySpecies.get(speciesId); - if (samplingCodeFound != null && code == samplingCodeFound.intValue()) { - samplingCodeFound.decrement(); - } -// return highestSamplingCodeBySpecies.computeIfPresent(speciesId, -// (key, highestSamplingCode) -> code.equals(highestSamplingCode) ? code - 1 : highestSamplingCode); } private Optional<CalcifiedPiecesSamplingDefinition> tryToFindCalcifiedPiecesSamplingDefinition(IndividualObservationBatch individualObservationBatch) { @@ -897,11 +853,10 @@ public class CruiseSamplingCache implements Closeable { } - return result; } - + private Optional<CalcifiedPiecesSamplingDefinition> tryToFindCalcifiedPiecesSamplingDefinition(Species species, Boolean maturity, int lengthStep, CaracteristicQualitativeValue gender) { Collection<CalcifiedPiecesSamplingDefinition> cpsDefinitions = cpsDefinitionsBySpecies.get(species.getReferenceTaxonId()); diff --git a/tutti-service/src/main/java/fr/ifremer/tutti/service/sampling/CruiseSamplingCacheLoader.java b/tutti-service/src/main/java/fr/ifremer/tutti/service/sampling/CruiseSamplingCacheLoader.java deleted file mode 100644 index ebe3107..0000000 --- a/tutti-service/src/main/java/fr/ifremer/tutti/service/sampling/CruiseSamplingCacheLoader.java +++ /dev/null @@ -1,156 +0,0 @@ -package fr.ifremer.tutti.service.sampling; - -/* - * #%L - * Tutti :: Service - * $Id:$ - * $HeadURL:$ - * %% - * Copyright (C) 2012 - 2016 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.ProgressionModel; -import fr.ifremer.tutti.persistence.entities.data.FishingOperation; -import fr.ifremer.tutti.persistence.entities.data.IndividualObservationBatch; -import fr.ifremer.tutti.persistence.entities.protocol.TuttiProtocol; -import fr.ifremer.tutti.persistence.entities.protocol.Zone; -import fr.ifremer.tutti.persistence.entities.referential.Caracteristic; -import fr.ifremer.tutti.service.DecoratorService; -import fr.ifremer.tutti.service.PersistenceService; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.decorator.Decorator; - -import java.util.Collection; -import java.util.List; - -import static org.nuiton.i18n.I18n.t; - -/** - * Pour charger le cache. - * - * Created on 20/03/16. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 4.5 - */ -public class CruiseSamplingCacheLoader { - - /** Logger. */ - private static final Log log = LogFactory.getLog(CruiseSamplingCacheLoader.class); - - private final PersistenceService persistenceService; - private final DecoratorService decoratorService; - private final ProgressionModel progressionModel; - - public CruiseSamplingCacheLoader(PersistenceService persistenceService, - DecoratorService decoratorService, - ProgressionModel progressionModel) { - this.persistenceService = persistenceService; - this.decoratorService = decoratorService; - this.progressionModel = progressionModel; - } - - public CruiseSamplingCache loadCruiseSamplingCache(TuttiProtocol protocol, Integer cruiseId) { - - Caracteristic sexCaracteristic = persistenceService.getSexCaracteristic(); - - Collection<Caracteristic> maturityCaracteristics = persistenceService.getMaturityCaracteristics(persistenceService.getAllCaracteristic()); - - CruiseSamplingCache cruiseSamplingCache = new CruiseSamplingCache(cruiseId, protocol, sexCaracteristic, maturityCaracteristics); - - cruiseSamplingCache.setLoading(true); - - try { - if (log.isInfoEnabled()) { - log.info("Loading cruise sampling cache: " + cruiseSamplingCache); - } - - Decorator<FishingOperation> fishingOperationDecorator = decoratorService.getDecoratorByType(FishingOperation.class); - - persistenceService.getAllFishingOperationIds(cruiseId).forEach(fishingOperationId -> { - - FishingOperation fishingOperation = persistenceService.getFishingOperation(fishingOperationId); - - progressionModel.increments(t("tutti.cruise.cacheLoader.loading.fishingOperation", fishingOperationDecorator.toString(fishingOperation))); - - List<IndividualObservationBatch> allIndividualObservationBatchsForFishingOperation = - persistenceService.getAllIndividualObservationBatchsForFishingOperation(fishingOperationId); - - Zone optionalZone = cruiseSamplingCache.tryFindZone(fishingOperation).orElse(null); - - cruiseSamplingCache.addIndividualObservations(fishingOperationId, - optionalZone, - allIndividualObservationBatchsForFishingOperation); - -// allIndividualObservationBatchsForFishingOperation.stream().filter(obs -> obs.getSize() != null).forEach( -// individualObservationBatch -> cruiseSamplingCache.addIndividualObservation(fishingOperationId, optionalZone, individualObservationBatch)); - - }); - - if (log.isInfoEnabled()) { - log.info("cruise sampling cache loaded: " + cruiseSamplingCache); - } - - return cruiseSamplingCache; - - } finally { - - cruiseSamplingCache.setLoading(false); - - } - - } - - public void loadCruiseSamplingCacheForFishingOperation(CruiseSamplingCache cruiseSamplingCache, FishingOperation fishingOperation) { - - cruiseSamplingCache.setLoading(true); - - try { - - Integer fishingOperationId = fishingOperation.getIdAsInt(); - - Zone optionalZone = cruiseSamplingCache.tryFindZone(fishingOperation).orElse(null); - - if (log.isInfoEnabled()) { - log.info("Loading cruise sampling cache for fishing operation: " + fishingOperationId + " - " + cruiseSamplingCache); - } - - List<IndividualObservationBatch> allIndividualObservationBatchsForFishingOperation = - persistenceService.getAllIndividualObservationBatchsForFishingOperation(fishingOperationId); - - cruiseSamplingCache.addIndividualObservations(fishingOperationId, - optionalZone, - allIndividualObservationBatchsForFishingOperation); - -// allIndividualObservationBatchsForFishingOperation.forEach( -// individualObservationBatch -> cruiseSamplingCache.addIndividualObservation(fishingOperationId, optionalZone, individualObservationBatch)); - - if (log.isInfoEnabled()) { - log.info("Cruise sampling cache loaded for fishing operation: " + fishingOperationId + " - " + cruiseSamplingCache); - } - - } finally { - - cruiseSamplingCache.setLoading(false); - - } - - } - -} diff --git a/tutti-service/src/main/java/fr/ifremer/tutti/service/sampling/SamplingCodeCache.java b/tutti-service/src/main/java/fr/ifremer/tutti/service/sampling/SamplingCodeCache.java new file mode 100644 index 0000000..149f8d2 --- /dev/null +++ b/tutti-service/src/main/java/fr/ifremer/tutti/service/sampling/SamplingCodeCache.java @@ -0,0 +1,113 @@ +package fr.ifremer.tutti.service.sampling; + +import fr.ifremer.tutti.persistence.entities.data.FishingOperation; +import fr.ifremer.tutti.persistence.entities.data.IndividualObservationBatch; +import org.apache.commons.lang3.mutable.MutableInt; + +import java.io.IOException; +import java.util.Collection; +import java.util.Map; +import java.util.Objects; +import java.util.TreeMap; + +/** + * Contient le cache des codes de prélèvement disponibles. + * + * Created on 16/04/16. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 4.5 + */ +public class SamplingCodeCache implements CruiseCacheAble { + + /** + * Le code prélèvement le plus grand pour chaque espèce. + */ + private final Map<Integer, MutableInt> highestSamplingCodeBySpecies; + + public SamplingCodeCache() { + this.highestSamplingCodeBySpecies = new TreeMap<>(); + } + + @Override + public void addFishingOperation(FishingOperation fishingOperation, Collection<IndividualObservationBatch> individualObservations) { + + Objects.requireNonNull(fishingOperation); + Objects.requireNonNull(individualObservations); + addIndividualObservations(fishingOperation, individualObservations); + + } + + @Override + public void removeFishingOperation(FishingOperation fishingOperation, Collection<IndividualObservationBatch> individualObservations) { + + Objects.requireNonNull(fishingOperation); + Objects.requireNonNull(individualObservations); + removeIndividualObservations(fishingOperation, individualObservations); + + } + + @Override + public void addIndividualObservations(FishingOperation fishingOperation, Collection<IndividualObservationBatch> individualObservations) { + + Objects.requireNonNull(fishingOperation); + Objects.requireNonNull(individualObservations); + + individualObservations + .stream() + .filter(batch -> batch.getSamplingCode() != null) + .forEach(batch -> addSamplingCode(batch.getSpecies().getReferenceTaxonId(), batch.getSamplingCode())); + + } + + @Override + public void removeIndividualObservations(FishingOperation fishingOperation, Collection<IndividualObservationBatch> individualObservations) { + + Objects.requireNonNull(fishingOperation); + Objects.requireNonNull(individualObservations); + + individualObservations + .stream() + .filter(batch -> batch.getSamplingCode() != null) + .forEach(batch -> removeSamplingCode(batch.getSpecies().getReferenceTaxonId(), batch.getSamplingCode())); + + } + + @Override + public void close() throws IOException { + highestSamplingCodeBySpecies.clear(); + } + + public int getNextSamplingCodeId(int speciesId) { + MutableInt samplingCode = highestSamplingCodeBySpecies.get(speciesId); + return (samplingCode == null ? 0 : samplingCode.intValue()) + 1; + } + + public int addSamplingCode(int speciesId, String samplingCode) { + int code = SamplingCodePrefix.extractSamplingCodeIdFromSamplingCode(samplingCode); + + return highestSamplingCodeBySpecies.compute(speciesId, + (key, highestSamplingCode) -> { + if (highestSamplingCode == null) { + highestSamplingCode = new MutableInt(code); + } else { + int nexValue = Math.max(highestSamplingCode.intValue(), code); + highestSamplingCode.setValue(nexValue); + } + return highestSamplingCode; + }).intValue(); + } + + public void removeSamplingCode(int speciesId, String samplingCode) { + + int code = SamplingCodePrefix.extractSamplingCodeIdFromSamplingCode(samplingCode); + + // decrement the highest sampling code if it is this code + MutableInt samplingCodeFound = highestSamplingCodeBySpecies.get(speciesId); + if (samplingCodeFound != null && code == samplingCodeFound.intValue()) { + samplingCodeFound.decrement(); + } + + } + +} -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.
This is an automated email from the git hooks/post-receive script. New commit to branch feature/8256 in repository tutti. See https://gitlab.nuiton.org/codelutin/tutti.git commit dbdef2da4edd97ac634bc5c4d42a60ae0c63c8cb Author: Tony CHEMIT <chemit@codelutin.com> Date: Sun Apr 17 07:35:51 2016 +0200 Revue du chargement des caches de campagne --- .../fr/ifremer/tutti/service/TuttiDataContext.java | 216 +++++++++------------ .../fr/ifremer/tutti/ui/swing/TuttiUIContext.java | 18 +- 2 files changed, 102 insertions(+), 132 deletions(-) diff --git a/tutti-service/src/main/java/fr/ifremer/tutti/service/TuttiDataContext.java b/tutti-service/src/main/java/fr/ifremer/tutti/service/TuttiDataContext.java index 58e748b..e35776a 100644 --- a/tutti-service/src/main/java/fr/ifremer/tutti/service/TuttiDataContext.java +++ b/tutti-service/src/main/java/fr/ifremer/tutti/service/TuttiDataContext.java @@ -40,8 +40,8 @@ import fr.ifremer.tutti.persistence.entities.referential.Species; import fr.ifremer.tutti.persistence.entities.referential.TaxonCache; import fr.ifremer.tutti.persistence.entities.referential.TaxonCaches; import fr.ifremer.tutti.persistence.entities.referential.Vessel; -import fr.ifremer.tutti.service.sampling.CruiseSamplingCache; -import fr.ifremer.tutti.service.sampling.CruiseSamplingCacheLoader; +import fr.ifremer.tutti.service.sampling.CruiseCache; +import fr.ifremer.tutti.service.sampling.CruiseCacheLoader; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -51,7 +51,6 @@ import java.io.Closeable; import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; @@ -131,9 +130,11 @@ public class TuttiDataContext extends AbstractBean implements Closeable { protected Cruise cruise; /** + * Le cache des données liées à la campagne sélectionnée. + * * @since 4.5 */ - protected CruiseSamplingCache cruiseSamplingCache; + protected CruiseCache cruiseCache; protected FishingOperation fishingOperation; @@ -171,29 +172,15 @@ public class TuttiDataContext extends AbstractBean implements Closeable { protected List<Caracteristic> defaultIndividualObservationCaracteristics; + protected TuttiValidationDataContextSupport validationContext = new TuttiValidationDataContext(this); + protected PersistenceService service; TuttiDataContext() { - addPropertyChangeListener(PROPERTY_PROGRAM_ID, evt -> program = null); - addPropertyChangeListener(PROPERTY_CRUISE_ID, evt -> cruise = null); - addPropertyChangeListener(PROPERTY_PROTOCOL_ID, evt -> { - resetProtocol(); - resetSpecies(); - }); - addPropertyChangeListener(PROPERTY_FISHING_OPERATION_ID, evt -> { - fishingOperation = null; - getValidationContext().resetExistingFishingOperations(); - }); - // Pour supprimer le cache d'échantillons - addPropertyChangeListener(evt -> { - String propertyName = evt.getPropertyName(); - if (PROPERTY_CRUISE_ID.equals(propertyName) || PROPERTY_PROGRAM_ID.equals(propertyName)) { - - if (getOptionalCruiseSamplingCache().isPresent()) { - closeCruiseSamplingCache(); - } - } - }); + addPropertyChangeListener(PROPERTY_PROGRAM_ID, evt -> resetProgram()); + addPropertyChangeListener(PROPERTY_CRUISE_ID, evt -> resetCruise()); + addPropertyChangeListener(PROPERTY_PROTOCOL_ID, evt -> resetProtocol()); + addPropertyChangeListener(PROPERTY_FISHING_OPERATION_ID, evt -> resetFishingOperation()); } public void setPersistenceService(PersistenceService service) { @@ -250,10 +237,7 @@ public class TuttiDataContext extends AbstractBean implements Closeable { } public void clearContext() { - program = null; - cruise = null; - fishingOperation = null; - //sampleCategoryModel = null; + resetProgram(); dirtySampleCategoryModel = true; resetProtocol(); resetVessels(); @@ -417,36 +401,60 @@ public class TuttiDataContext extends AbstractBean implements Closeable { return fishingOperationId; } + /** + * @return {@code true} si une campache est charfée. + */ public boolean isCruiseFilled() { return isProgramFilled() && cruiseId != null; } + /** + * @return {@code true} si un protocol est chargé. + */ public boolean isProtocolFilled() { return StringUtils.isNotBlank(protocolId); } + /** + * @return {@code true} si une série de campagne est chargée. + */ public boolean isProgramFilled() { return StringUtils.isNotBlank(programId); } + /** + * @return {@code true} si une opérationde pêche est chargée. + */ public boolean isFishingOperationFilled() { return fishingOperationId != null; } - public boolean isCanUseCruiseSamplingCache() { - return isProtocolFilled() - && isCruiseFilled() - && getProtocol().isUseCalcifiedPieceSampling(); + /** + * @return {@code true} si on peut utiliser le cache sur la campagne. + */ + public boolean isCanUseCruiseCache() { + return isCruiseFilled(); } - public boolean isCruiseSamplingCacheLoaded() { - return cruiseSamplingCache != null; + /** + * @return {@code true} si le cache de campagne est chargé. + */ + public boolean isCruiseCacheLoaded() { + return cruiseCache != null; } - public boolean isCruiseSamplingCacheUpToDate() { - return isCruiseSamplingCacheLoaded() - && Objects.equals(getCruiseId(), cruiseSamplingCache.getCruiseId()) - && Objects.equals(getProtocolId(), cruiseSamplingCache.getProtocolId()); + /** + * @return {@code true} si le cache de campagne est à jour. + */ + public boolean isCruiseCacheUpToDate() { + return isCruiseCacheLoaded() && cruiseCache.isCacheUpToDate(getCruiseId(), getProtocolId()); + } + + /** + * @return {@code true} si on peut utiliser le cache de prélèvement des pièces calcifiées. + */ + public boolean isCanUseCruiseSamplingCache() { + return isCanUseCruiseCache() && isProtocolFilled() && getProtocol().isUseCalcifiedPieceSampling(); } public void setProgramId(String programId) { @@ -559,45 +567,34 @@ public class TuttiDataContext extends AbstractBean implements Closeable { return service.getProtocol(); } - - public Optional<CruiseSamplingCache> getOptionalCruiseSamplingCache() { - return Optional.ofNullable(isCruiseSamplingCacheUpToDate() ? cruiseSamplingCache : null); + public Optional<CruiseCache> getOptionalCruiseCache() { + return Optional.ofNullable(isCruiseCacheUpToDate() ? cruiseCache : null); } - public void loadCruiseSamplingCache(CruiseSamplingCacheLoader cruiseSamplingCacheLoader) { + public void loadCruiseCache(CruiseCacheLoader cruiseCacheLoader) { + checkOpened(); - if (!isCanUseCruiseSamplingCache()) { + if (!isCanUseCruiseCache()) { throw new IllegalStateException("Pas autorisé à charger le cache d'échantillons"); } - if (isCruiseSamplingCacheLoaded() && !isCruiseSamplingCacheUpToDate()) { - closeCruiseSamplingCache(); + + if (isCruiseCacheLoaded() && !isCruiseCacheUpToDate()) { + closeCruiseCache(); } if (log.isInfoEnabled()) { log.info("Loading cruise sampling cache: {cruiseId:" + getCruiseId() + ", protocolId: " + getProtocolId() + "}"); } - cruiseSamplingCache = cruiseSamplingCacheLoader.loadCruiseSamplingCache(getProtocol(), getCruiseId()); + cruiseCache = cruiseCacheLoader.loadCruiseCache(); if (log.isInfoEnabled()) { - log.info("cruise sampling cache loaded: " + cruiseSamplingCache); + log.info("cruise sampling cache loaded: " + cruiseCache); } } - protected void closeCruiseSamplingCache() { - Objects.requireNonNull(cruiseSamplingCache); - - // on détruit le cache obsolète - if (log.isInfoEnabled()) { - log.info("Destroy obsolete cruise sampling cache: " + cruiseSamplingCache); - } - - cruiseSamplingCache.close(); - cruiseSamplingCache = null; - } - public List<Integer> getCruiseFishingOperationIds() { checkOpened(); if (!isCruiseFilled()) { @@ -677,61 +674,6 @@ public class TuttiDataContext extends AbstractBean implements Closeable { return maturityCaracteristics; } -// /** -// * Get the best possible first sample category for the given benthos. -// * -// * Will look inside the protocol if there is a row for the given benthos, -// * if so try then to use the first selected sample category. -// * -// * If selected category is null, then try to use the first one from the -// * given categories. -// * -// * @param categories list of possible categories -// * @param species species to use -// * @return the best first sample category to use for the given benthos -// * @since 3.0 -// */ -// public SampleCategoryModelEntry getBestFirstBenthosSampleCategory(List<SampleCategoryModelEntry> categories, -// Species species) { -// -// -// SpeciesProtocol speciesProtocol = null; -// -// if (isProtocolFilled()) { -// -// speciesProtocol = service.getBenthosProtocol(species); -// } -// -// return getBestFirstSampleCategory(categories, speciesProtocol); -// } -// -// /** -// * Get the best possible first sample category for the given species. -// * -// * Will look inside the protocol if there is a row for the given species, -// * if so try then to use the first selected sample category. -// * -// * If selected category is null, then try to use the first one from the -// * given categories. -// * -// * @param categories list of possible categories -// * @param species species to use -// * @return the best first sample category to use for the given species -// * @since 3.0 -// */ -// public SampleCategoryModelEntry getBestFirstSpeciesSampleCategory(List<SampleCategoryModelEntry> categories, -// Species species) { -// -// SpeciesProtocol speciesProtocol = null; -// -// if (isProtocolFilled()) { -// -// speciesProtocol = service.getSpeciesProtocol(species); -// } -// -// return getBestFirstSampleCategory(categories, speciesProtocol); -// } - public SampleCategoryModelEntry getBestFirstSampleCategory(List<SampleCategoryModelEntry> categories, SpeciesProtocol speciesProtocol) { @@ -964,9 +906,20 @@ public class TuttiDataContext extends AbstractBean implements Closeable { return defaultIndividualObservationCaracteristics; } + private void resetProgram() { + program = null; + resetCruise(); + } + public void resetCruise() { cruise = null; - resetCruiseSamplingCache(); + resetFishingOperation(); + closeCruiseCache(); + } + + public void resetFishingOperation() { + fishingOperation = null; + validationContext.resetExistingFishingOperations(); } public void resetProtocol() { @@ -978,11 +931,7 @@ public class TuttiDataContext extends AbstractBean implements Closeable { defaultIndividualObservationCaracteristics = null; // survey code must be refresh resetSpecies(); - resetCruiseSamplingCache(); - } - - public void resetCruiseSamplingCache() { - cruiseSamplingCache = null; + closeCruiseCache(); } public void resetGears() { @@ -1004,7 +953,6 @@ public class TuttiDataContext extends AbstractBean implements Closeable { referentSpecies = null; referentSpeciesWithSurveyCode = null; referentBenthosWithSurveyCode = null; - } public void resetCaracteristics() { @@ -1014,20 +962,14 @@ public class TuttiDataContext extends AbstractBean implements Closeable { deadOrAliveValues = null; } - protected void checkOpened() { - Preconditions.checkState(service != null, "No persistence service assigned!"); + public void resetValidationDataContext() { + validationContext.reset(); } public PersistenceService getService() { return service; } - protected TuttiValidationDataContextSupport validationContext = new TuttiValidationDataContext(this); - - public void resetValidationDataContext() { - validationContext.reset(); - } - public TuttiValidationDataContextSupport getValidationContext() { return validationContext; } @@ -1036,4 +978,20 @@ public class TuttiDataContext extends AbstractBean implements Closeable { Preconditions.checkNotNull(validationContext, "cant set a null validation context"); this.validationContext = validationContext; } + + protected void checkOpened() { + Preconditions.checkState(service != null, "No persistence service assigned!"); + } + + public void closeCruiseCache() { + if (!isCruiseCacheLoaded()) { + return; + } + if (log.isInfoEnabled()) { + log.info("Close cruise cache: " + cruiseCache); + } + + cruiseCache.close(); + cruiseCache = null; + } } diff --git a/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/TuttiUIContext.java b/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/TuttiUIContext.java index 55f1086..71e144e 100644 --- a/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/TuttiUIContext.java +++ b/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/TuttiUIContext.java @@ -27,6 +27,7 @@ import com.google.common.collect.Maps; import com.google.common.collect.Sets; import fr.ifremer.tutti.TuttiConfiguration; import fr.ifremer.tutti.ichtyometer.feed.FeedReader; +import fr.ifremer.tutti.persistence.ProgressionModel; import fr.ifremer.tutti.service.ClosedPersistenceService; import fr.ifremer.tutti.service.DecoratorService; import fr.ifremer.tutti.service.PersistenceService; @@ -56,6 +57,7 @@ import fr.ifremer.tutti.service.referential.ReferentialTemporarySpeciesService; import fr.ifremer.tutti.service.referential.ReferentialTemporaryVesselService; import fr.ifremer.tutti.service.referential.TuttiReferentialSynchronizeService; import fr.ifremer.tutti.service.report.ReportGenerationService; +import fr.ifremer.tutti.service.sampling.CruiseCacheLoader; import fr.ifremer.tutti.ui.swing.content.MainUI; import fr.ifremer.tutti.ui.swing.updater.DeleteHelper; import fr.ifremer.tutti.ui.swing.util.SoundEngine; @@ -526,7 +528,7 @@ public class TuttiUIContext extends AbstractBean implements Closeable, UIMessage } catch (Exception eee) { log.error("Failed to load help mapping file at '" + - mappingProperties + "'", eee); + mappingProperties + "'", eee); } if (log.isInfoEnabled()) { log.info(String.format("Starts help with locale at [%s]", @@ -850,6 +852,16 @@ public class TuttiUIContext extends AbstractBean implements Closeable, UIMessage } + public CruiseCacheLoader createCruiseCacheLoader(ProgressionModel progressionModel) { + + return CruiseCacheLoader.newCacheLoader(getPersistenceService(), + getDecoratorService(), + progressionModel, + getDataContext().getProtocol(), + getCruiseId()); + + } + //------------------------------------------------------------------------// //-- Db methods --// //------------------------------------------------------------------------// @@ -883,8 +895,8 @@ public class TuttiUIContext extends AbstractBean implements Closeable, UIMessage protected void saveContextToConfig() { if (log.isInfoEnabled()) { log.info("Save config (programId: " + getProgramId() + ", cruiseId: " + - getCruiseId() + ", protocolId: " + getProtocolId() + ", locale: " + - getLocale() + ")"); + getCruiseId() + ", protocolId: " + getProtocolId() + ", locale: " + + getLocale() + ")"); } config.setProgramId(getProgramId()); config.setCruiseId(getCruiseId()); -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.
This is an automated email from the git hooks/post-receive script. New commit to branch feature/8256 in repository tutti. See https://gitlab.nuiton.org/codelutin/tutti.git commit abb60a40e675965c84686ccbb512bd9d1328e61b Author: Tony CHEMIT <chemit@codelutin.com> Date: Sun Apr 17 07:36:09 2016 +0200 Utilisation des caches de campagnes --- .../ifremer/tutti/service/PersistenceService.java | 129 +++++++------ .../cps/CalcifiedPiecesSamplingExportService.java | 39 ++-- .../content/actions/EditCatchesSupportAction.java | 24 +-- .../content/cruise/actions/SaveCruiseAction.java | 7 +- .../CalcifiedPiecesSamplingReportAction.java | 30 +-- .../SamplingCodeCellEditor.java | 20 +- .../IndividualObservationBatchTableHandler.java | 38 +++- .../frequency/IndividualObservationUICache.java | 205 ++++++++++++--------- .../protocol/actions/SaveProtocolAction.java | 6 +- 9 files changed, 292 insertions(+), 206 deletions(-) diff --git a/tutti-service/src/main/java/fr/ifremer/tutti/service/PersistenceService.java b/tutti-service/src/main/java/fr/ifremer/tutti/service/PersistenceService.java index 7abb271..d72bfa5 100644 --- a/tutti-service/src/main/java/fr/ifremer/tutti/service/PersistenceService.java +++ b/tutti-service/src/main/java/fr/ifremer/tutti/service/PersistenceService.java @@ -49,10 +49,7 @@ import fr.ifremer.tutti.persistence.entities.data.SampleCategoryModel; import fr.ifremer.tutti.persistence.entities.data.SpeciesBatch; import fr.ifremer.tutti.persistence.entities.data.SpeciesBatchFrequency; import fr.ifremer.tutti.persistence.entities.protocol.MaturityCaracteristic; -import fr.ifremer.tutti.persistence.entities.protocol.SpeciesProtocol; import fr.ifremer.tutti.persistence.entities.protocol.TuttiProtocol; -import fr.ifremer.tutti.persistence.entities.protocol.TuttiProtocols; -import fr.ifremer.tutti.persistence.entities.protocol.Zone; import fr.ifremer.tutti.persistence.entities.protocol.Zones; import fr.ifremer.tutti.persistence.entities.referential.Caracteristic; import fr.ifremer.tutti.persistence.entities.referential.Gear; @@ -69,8 +66,9 @@ import fr.ifremer.tutti.persistence.entities.referential.Vessels; import fr.ifremer.tutti.persistence.model.ProgramDataModel; import fr.ifremer.tutti.persistence.service.TuttiPersistenceServiceLocator; import fr.ifremer.tutti.persistence.service.UpdateSchemaContextSupport; +import fr.ifremer.tutti.service.sampling.CruiseCache; +import fr.ifremer.tutti.service.sampling.CruiseCacheLoader; import fr.ifremer.tutti.service.sampling.CruiseSamplingCache; -import fr.ifremer.tutti.service.sampling.CruiseSamplingCacheLoader; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; @@ -568,27 +566,27 @@ public class PersistenceService extends AbstractTuttiService implements TuttiPer return result; } - /** - * Return the speciesProtocol corresponding to the species of the given protocol. - * - * @param species the species to filter - * @return the speciesProtocol corresponding to the species of the given protocol. - * @since 2.6 - */ - public SpeciesProtocol getSpeciesProtocol(Species species) { - return TuttiProtocols.getSpeciesProtocol(species, getProtocol().getSpecies()); - } - - /** - * Return the benthosProtocol corresponding to the species of the given protocol. - * - * @param species the species to filter - * @return the benthosProtocol corresponding to the species of the given protocol. - * @since 2.6 - */ - public SpeciesProtocol getBenthosProtocol(Species species) { - return TuttiProtocols.getSpeciesProtocol(species, getProtocol().getBenthos()); - } +// /** +// * Return the speciesProtocol corresponding to the species of the given protocol. +// * +// * @param species the species to filter +// * @return the speciesProtocol corresponding to the species of the given protocol. +// * @since 2.6 +// */ +// public SpeciesProtocol getSpeciesProtocol(Species species) { +// return TuttiProtocols.getSpeciesProtocol(species, getProtocol().getSpecies()); +// } + +// /** +// * Return the benthosProtocol corresponding to the species of the given protocol. +// * +// * @param species the species to filter +// * @return the benthosProtocol corresponding to the species of the given protocol. +// * @since 2.6 +// */ +// public SpeciesProtocol getBenthosProtocol(Species species) { +// return TuttiProtocols.getSpeciesProtocol(species, getProtocol().getBenthos()); +// } public static final TimeLog TIME_LOG = new TimeLog(PersistenceService.class); @@ -1356,65 +1354,78 @@ public class PersistenceService extends AbstractTuttiService implements TuttiPer if (Objects.equals(bean.getGearShootingStartDate(), bean.getGearShootingEndDate())) { bean.setGearShootingEndDate(null); } - Optional<CruiseSamplingCache> optionalCruiseSamplingCache = getOptionalCruiseSamplingCache(); + + Optional<CruiseCache> optionalCruiseCache = getOptionalCruiseCache(); boolean reloadSamplingCache = false; - if (optionalCruiseSamplingCache.isPresent()) { + CruiseCache cruiseCache = optionalCruiseCache.orElseGet(null); - FishingOperation oldFishingOperation = getFishingOperation(bean.getIdAsInt()); + if (optionalCruiseCache.isPresent()) { - CruiseSamplingCache cruiseSamplingCache = optionalCruiseSamplingCache.get(); + Optional<CruiseSamplingCache> optionalSamplingCruiseCache = cruiseCache.getSamplingCruiseCache(); - Optional<Zone> oldOptionalZone = cruiseSamplingCache.tryFindZone(oldFishingOperation); - Optional<Zone> newOptionalZone = cruiseSamplingCache.tryFindZone(bean); + if (optionalSamplingCruiseCache.isPresent()) { - if (!Objects.equals(oldOptionalZone, newOptionalZone)) { + // on doit vérifier si l'opération n'a pas changée de zone + CruiseSamplingCache cruiseSamplingCache = optionalSamplingCruiseCache.get(); + + FishingOperation oldFishingOperation = getFishingOperation(bean.getIdAsInt()); + + boolean zoneChanged = cruiseSamplingCache.isZoneChanged(oldFishingOperation, bean); + + if (zoneChanged) { + + // les strates ou sous-strates ont changées, il faut recalculer le cache des échantillons + if (log.isInfoEnabled()) { + log.info("Zone has changed for fishingOperation: " + bean + ", remove fishing operation from cruise cache."); + } + reloadSamplingCache = true; + + List<IndividualObservationBatch> individualObservations = getAllIndividualObservationBatchsForFishingOperation(bean.getIdAsInt()); + cruiseCache.removeFishingOperation(oldFishingOperation, individualObservations); - if (log.isInfoEnabled()) { - log.info("Zone has changed for fishingOperation: " + bean.getId() + ", remove fishing operation from cruiseSamplingCache."); } - // les strates ou sous-strates ont changées, il faut recalculer le cache des échantillons - reloadSamplingCache = true; - cruiseSamplingCache.removeFishingOperation(oldFishingOperation); } } + FishingOperation fishingOperation = driver.saveFishingOperation(bean); if (reloadSamplingCache) { if (log.isInfoEnabled()) { - log.info("Zone has changed for fishingOperation: " + bean.getId() + ", recompute fishing operation from cruiseSamplingCache."); + log.info("Zone has changed for fishingOperation: " + bean + ", recompute fishing operation from cruise cache."); } - CruiseSamplingCache cruiseSamplingCache = optionalCruiseSamplingCache.get(); - CruiseSamplingCacheLoader cruiseSamplingCacheLoader = new CruiseSamplingCacheLoader(this, context.getService(DecoratorService.class), null); - cruiseSamplingCacheLoader.loadCruiseSamplingCacheForFishingOperation(cruiseSamplingCache, fishingOperation); + CruiseCacheLoader cruiseCacheLoader = CruiseCacheLoader.newCacheLoader(this, context.getService(DecoratorService.class), null, cruiseCache); + cruiseCacheLoader.loadCruiseCacheForFishingOperation(fishingOperation); } return fishingOperation; } + //FIXME Remove this ? can't find where it is used... @Override public Collection<FishingOperation> saveFishingOperations(Collection<FishingOperation> beans) { - Collection<FishingOperation> fishingOperations = driver.saveFishingOperations(beans); - //FIXME Update samplingCache - return fishingOperations; + return driver.saveFishingOperations(beans); } @Override public void deleteFishingOperation(Integer id) { - Optional<CruiseSamplingCache> optionalCruiseSamplingCache = getOptionalCruiseSamplingCache(); - if (optionalCruiseSamplingCache.isPresent()) { + Optional<CruiseCache> optionalCruiseCache = getOptionalCruiseCache(); + if (optionalCruiseCache.isPresent()) { - CruiseSamplingCache cruiseSamplingCache = optionalCruiseSamplingCache.get(); + CruiseCache cruiseCache = optionalCruiseCache.get(); if (log.isInfoEnabled()) { - log.info("Remove fishing operation: " + id + " from cruiseSamplingCache: " + cruiseSamplingCache); + log.info("Remove fishing operation: " + id + " from cruiseSamplingCache: " + cruiseCache); } FishingOperation fishingOperation = getFishingOperation(id); - optionalCruiseSamplingCache.get().removeFishingOperation(fishingOperation); + + List<IndividualObservationBatch> individualObservations = getAllIndividualObservationBatchsForFishingOperation(id); + + optionalCruiseCache.get().removeFishingOperation(fishingOperation, individualObservations); } driver.deleteFishingOperation(id); } @@ -1691,14 +1702,12 @@ public class PersistenceService extends AbstractTuttiService implements TuttiPer protected void beforeDeleteBatch(Integer id, boolean addBatchId) { - Optional<CruiseSamplingCache> optionalCruiseSamplingCache = getOptionalCruiseSamplingCache(); - if (optionalCruiseSamplingCache.isPresent()) { + Optional<CruiseCache> optionalCruiseCache = getOptionalCruiseCache(); + if (optionalCruiseCache.isPresent()) { - CruiseSamplingCache cruiseSamplingCache = optionalCruiseSamplingCache.get(); + CruiseCache cruiseCache = optionalCruiseCache.get(); FishingOperation fishingOperation = context.getDataContext().getFishingOperation(); - Integer fishingOperationId = fishingOperation.getIdAsInt(); - Zone optionalZone = cruiseSamplingCache.tryFindZone(fishingOperation).orElse(null); Set<Integer> batchIds = new LinkedHashSet<>(); if (addBatchId) { @@ -1708,15 +1717,15 @@ public class PersistenceService extends AbstractTuttiService implements TuttiPer batchIds.forEach(speciesBatchId -> { - List<IndividualObservationBatch> allIndividualObservationBatchsForBatch = getAllIndividualObservationBatchsForBatch(speciesBatchId); + List<IndividualObservationBatch> individualObservations = getAllIndividualObservationBatchsForBatch(speciesBatchId); - if (!allIndividualObservationBatchsForBatch.isEmpty()) { + if (!individualObservations.isEmpty()) { if (log.isInfoEnabled()) { - log.info("Remove for species or benthos batch: " + speciesBatchId + " - " + allIndividualObservationBatchsForBatch.size() + " individual observations from cruiseSamplingCache: " + cruiseSamplingCache); + log.info("Remove for species or benthos batch: " + speciesBatchId + " - " + individualObservations.size() + " individual observations from cruiseSamplingCache: " + cruiseCache); } - cruiseSamplingCache.removeIndividualObservations(fishingOperationId, optionalZone, allIndividualObservationBatchsForBatch); + cruiseCache.removeIndividualObservations(fishingOperation, individualObservations); } @@ -1726,8 +1735,8 @@ public class PersistenceService extends AbstractTuttiService implements TuttiPer } - private Optional<CruiseSamplingCache> getOptionalCruiseSamplingCache() { - return context.getDataContext().getOptionalCruiseSamplingCache(); + private Optional<CruiseCache> getOptionalCruiseCache() { + return context.getDataContext().getOptionalCruiseCache(); } } diff --git a/tutti-service/src/main/java/fr/ifremer/tutti/service/export/cps/CalcifiedPiecesSamplingExportService.java b/tutti-service/src/main/java/fr/ifremer/tutti/service/export/cps/CalcifiedPiecesSamplingExportService.java index c4b9b92..58d2dac 100644 --- a/tutti-service/src/main/java/fr/ifremer/tutti/service/export/cps/CalcifiedPiecesSamplingExportService.java +++ b/tutti-service/src/main/java/fr/ifremer/tutti/service/export/cps/CalcifiedPiecesSamplingExportService.java @@ -24,9 +24,7 @@ package fr.ifremer.tutti.service.export.cps; * #L% */ -import com.google.common.base.Charsets; import com.google.common.base.Preconditions; -import com.google.common.io.Files; import fr.ifremer.tutti.persistence.ProgressionModel; import fr.ifremer.tutti.persistence.entities.referential.Species; import fr.ifremer.tutti.persistence.entities.referential.Speciess; @@ -36,7 +34,8 @@ import fr.ifremer.tutti.service.PersistenceService; import fr.ifremer.tutti.service.TuttiDataContext; import fr.ifremer.tutti.service.TuttiServiceContext; import fr.ifremer.tutti.service.sampling.CacheExtractedKey; -import org.apache.commons.io.IOUtils; +import fr.ifremer.tutti.service.sampling.CruiseCache; +import fr.ifremer.tutti.service.sampling.CruiseSamplingCache; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuiton.csv.Export; @@ -45,8 +44,11 @@ import org.nuiton.jaxx.application.ApplicationTechnicalException; import java.io.BufferedWriter; import java.io.File; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.util.List; import java.util.Map; +import java.util.Optional; import static org.nuiton.i18n.I18n.t; @@ -71,39 +73,48 @@ public class CalcifiedPiecesSamplingExportService extends AbstractTuttiService { /** * Export selected cruise with the csv sumatra format. * - * @param file where to generate report + * @param file where to generate report * @since 2.0 */ - public void exportCruiseCalcifiedPiecesSamplingsReport(File file, - ProgressionModel progressionModel) { + public void exportCruiseCalcifiedPiecesSamplingsReport(File file, ProgressionModel progressionModel) { Preconditions.checkNotNull(file, "Cannot export to a null file"); TuttiDataContext dataContext = context.getDataContext(); - Preconditions.checkState(dataContext.isCruiseSamplingCacheLoaded()); + Preconditions.checkState(dataContext.isCanUseCruiseSamplingCache() && dataContext.isCruiseCacheLoaded() && dataContext.isCruiseCacheUpToDate()); Decorator<Species> decorator = decoratorService.getDecoratorByType(Species.class, DecoratorService.WITH_SURVEY_CODE_NO_NAME); SamplingNumberRowModel csvModel = new SamplingNumberRowModel(context.getConfig().getCsvSeparator(), decorator); Map<String, Species> referenceSpeciesByReferenceTaxonId = Speciess.splitReferenceSpeciesByReferenceTaxonId(dataContext.getReferentSpecies()); - List<CacheExtractedKey> rows = context.getDataContext().getOptionalCruiseSamplingCache().get().getSamplingNumbers(referenceSpeciesByReferenceTaxonId); + Optional<CruiseCache> optionalCruiseCache = context.getDataContext().getOptionalCruiseCache(); + if (!optionalCruiseCache.isPresent()) { + throw new IllegalStateException("No cruise cache found"); + } + CruiseCache cruiseCache = optionalCruiseCache.get(); + + Optional<CruiseSamplingCache> optionalSamplingCruiseCache = cruiseCache.getSamplingCruiseCache(); + if (!optionalSamplingCruiseCache.isPresent()) { + throw new IllegalStateException("No sampling cruise cache found"); + } - BufferedWriter writer = null; - try { + List<CacheExtractedKey> rows = optionalSamplingCruiseCache.get().getSamplingNumbers(referenceSpeciesByReferenceTaxonId); + + if (log.isInfoEnabled()) { + log.info("Loaded " + rows.size() + " keys to export to " + file); + } + try (BufferedWriter writer = Files.newBufferedWriter(file.toPath(), StandardCharsets.UTF_8)) { progressionModel.increments(t("tutti.service.cpsExport.step.toFile", file.getName())); - writer = Files.newWriter(file, Charsets.UTF_8); Export export = Export.newExport(csvModel, rows); export.write(writer); - writer.close(); } catch (Exception e) { throw new ApplicationTechnicalException(t("tutti.service.cpsExport.error", file), e); - } finally { - IOUtils.closeQuietly(writer); } + } } diff --git a/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/actions/EditCatchesSupportAction.java b/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/actions/EditCatchesSupportAction.java index ff4a976..494a8c1 100644 --- a/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/actions/EditCatchesSupportAction.java +++ b/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/actions/EditCatchesSupportAction.java @@ -27,8 +27,9 @@ import fr.ifremer.tutti.persistence.ProgressionModel; import fr.ifremer.tutti.persistence.entities.data.FishingOperation; import fr.ifremer.tutti.service.TuttiDataContext; import fr.ifremer.tutti.service.ValidationService; -import fr.ifremer.tutti.service.sampling.CruiseSamplingCacheLoader; +import fr.ifremer.tutti.service.sampling.CruiseCacheLoader; import fr.ifremer.tutti.ui.swing.TuttiScreen; +import fr.ifremer.tutti.ui.swing.TuttiUIContext; import fr.ifremer.tutti.ui.swing.content.MainUIHandler; import fr.ifremer.tutti.ui.swing.content.operation.EditFishingOperationUI; import fr.ifremer.tutti.ui.swing.content.operation.FishingOperationsUI; @@ -57,7 +58,7 @@ public abstract class EditCatchesSupportAction extends AbstractChangeScreenActio protected abstract boolean isLoadReferential(); protected boolean loadReferential; - protected boolean loadSamplingCache; + protected boolean loadCruiseCache; @Override public boolean prepareAction() throws Exception { @@ -67,8 +68,7 @@ public abstract class EditCatchesSupportAction extends AbstractChangeScreenActio if (doAction) { loadReferential = isLoadReferential(); - loadSamplingCache = dataContext.isCanUseCruiseSamplingCache() && - !(dataContext.isCruiseSamplingCacheLoaded() && dataContext.isCruiseSamplingCacheUpToDate()); + loadCruiseCache = !(dataContext.isCruiseCacheLoaded() && dataContext.isCruiseCacheUpToDate()); int totalSteps = 1; @@ -76,7 +76,7 @@ public abstract class EditCatchesSupportAction extends AbstractChangeScreenActio totalSteps += 5; } - if (loadSamplingCache) { + if (loadCruiseCache) { // Calcul des étapes (nb de traits dans la campagne) long cruiseFishingOperationIds = getDataContext().getCruiseFishingOperationIds().stream().count(); @@ -99,22 +99,24 @@ public abstract class EditCatchesSupportAction extends AbstractChangeScreenActio @Override public void doAction() throws Exception { - Preconditions.checkState(getContext().isCruiseFilled()); + TuttiUIContext context = getContext(); + Preconditions.checkState(context.isCruiseFilled()); + Integer cruiseId = context.getCruiseId(); if (log.isInfoEnabled()) { - log.info("Edit operations of cruise: " + getContext().getCruiseId()); + log.info("Edit operations of cruise: " + cruiseId); } - getContext().setValidationContext(ValidationService.VALIDATION_CONTEXT_EDIT); + context.setValidationContext(ValidationService.VALIDATION_CONTEXT_EDIT); if (loadReferential) { loadReferantials(false); } - if (loadSamplingCache) { + if (loadCruiseCache) { ProgressionModel progressionModel = getProgressionModel(); - CruiseSamplingCacheLoader cruiseSamplingCacheLoader = new CruiseSamplingCacheLoader(getContext().getPersistenceService(), getContext().getDecoratorService(), progressionModel); - getDataContext().loadCruiseSamplingCache(cruiseSamplingCacheLoader); + CruiseCacheLoader cruiseCacheLoader = context.createCruiseCacheLoader(progressionModel); + getDataContext().loadCruiseCache(cruiseCacheLoader); progressionModel.increments("Chargement de l'interface graphique"); diff --git a/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/cruise/actions/SaveCruiseAction.java b/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/cruise/actions/SaveCruiseAction.java index 0a38c73..c0d52b6 100644 --- a/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/cruise/actions/SaveCruiseAction.java +++ b/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/cruise/actions/SaveCruiseAction.java @@ -30,12 +30,12 @@ import fr.ifremer.tutti.persistence.entities.referential.GearWithOriginalRankOrd import fr.ifremer.tutti.persistence.entities.referential.GearWithOriginalRankOrders; import fr.ifremer.tutti.service.PersistenceService; import fr.ifremer.tutti.ui.swing.TuttiUIContext; -import fr.ifremer.tutti.ui.swing.util.actions.LongActionSupport; import fr.ifremer.tutti.ui.swing.content.cruise.EditCruiseUI; import fr.ifremer.tutti.ui.swing.content.cruise.EditCruiseUIHandler; import fr.ifremer.tutti.ui.swing.content.cruise.EditCruiseUIModel; import fr.ifremer.tutti.ui.swing.util.AbstractTuttiUIHandler; import fr.ifremer.tutti.ui.swing.util.TuttiUIUtil; +import fr.ifremer.tutti.ui.swing.util.actions.LongActionSupport; import org.apache.commons.lang3.ObjectUtils; import javax.swing.ImageIcon; @@ -173,6 +173,8 @@ public class SaveCruiseAction extends LongActionSupport<EditCruiseUIModel, EditC getDataContext().reloadCruise(); } + getDataContext().closeCruiseCache(); + // update originalRankOrder for all gears of the cruise for (GearWithOriginalRankOrder gear : model.getGear()) { gear.setOriginalRankOrder(gear.getRankOrder()); @@ -185,8 +187,7 @@ public class SaveCruiseAction extends LongActionSupport<EditCruiseUIModel, EditC @Override public void postSuccessAction() { - getContext().getMainUI().getHandler().setBodyTitle( - EditCruiseUIHandler.getTitle(true)); + getContext().getMainUI().getHandler().setBodyTitle(EditCruiseUIHandler.getTitle(true)); ImageIcon icon = TuttiUIUtil.getCruiseIcon(getModel()); getContext().getMainUI().getBody().setLeftDecoration(new JLabel(icon)); diff --git a/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/home/actions/CalcifiedPiecesSamplingReportAction.java b/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/home/actions/CalcifiedPiecesSamplingReportAction.java index 28b80f7..41148e7 100644 --- a/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/home/actions/CalcifiedPiecesSamplingReportAction.java +++ b/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/home/actions/CalcifiedPiecesSamplingReportAction.java @@ -27,8 +27,10 @@ package fr.ifremer.tutti.ui.swing.content.home.actions; import com.google.common.base.Preconditions; import fr.ifremer.tutti.persistence.ProgressionModel; import fr.ifremer.tutti.persistence.entities.data.Cruise; +import fr.ifremer.tutti.service.TuttiDataContext; import fr.ifremer.tutti.service.export.cps.CalcifiedPiecesSamplingExportService; -import fr.ifremer.tutti.service.sampling.CruiseSamplingCacheLoader; +import fr.ifremer.tutti.service.sampling.CruiseCacheLoader; +import fr.ifremer.tutti.ui.swing.TuttiUIContext; import fr.ifremer.tutti.ui.swing.content.MainUIHandler; import fr.ifremer.tutti.ui.swing.content.actions.AbstractMainUITuttiAction; import org.apache.commons.logging.Log; @@ -47,13 +49,10 @@ import static org.nuiton.i18n.I18n.t; public class CalcifiedPiecesSamplingReportAction extends AbstractMainUITuttiAction { /** Logger. */ - private static final Log log = - LogFactory.getLog(CalcifiedPiecesSamplingReportAction.class); + private static final Log log = LogFactory.getLog(CalcifiedPiecesSamplingReportAction.class); protected File file; -// protected SumatraExportResult sumatraExportResult; - public CalcifiedPiecesSamplingReportAction(MainUIHandler handler) { super(handler, false); } @@ -99,30 +98,33 @@ public class CalcifiedPiecesSamplingReportAction extends AbstractMainUITuttiActi @Override public void doAction() throws Exception { - Cruise cruise = getDataContext().getCruise(); + + TuttiDataContext dataContext = getDataContext(); + Cruise cruise = dataContext.getCruise(); Preconditions.checkNotNull(cruise); Preconditions.checkNotNull(file); if (log.isInfoEnabled()) { - log.info("Will export cps for cruise " + cruise.getId() + - " to file: " + file); + log.info("Will export cps for cruise " + cruise.getId() + " to file: " + file); } ProgressionModel pm = new ProgressionModel(); setProgressionModel(pm); - long cruiseFishingOperationIds = getDataContext().getCruiseFishingOperationIds().stream().count(); + long cruiseFishingOperationIds = dataContext.getCruiseFishingOperationIds().size(); pm.setTotal((int) (1 + cruiseFishingOperationIds)); - if (!getDataContext().isCruiseSamplingCacheLoaded()) { - CruiseSamplingCacheLoader cruiseSamplingCacheLoader = new CruiseSamplingCacheLoader(getContext().getPersistenceService(), - getContext().getDecoratorService(), getProgressionModel()); - getDataContext().loadCruiseSamplingCache(cruiseSamplingCacheLoader); + TuttiUIContext context = getContext(); + if (!dataContext.isCruiseCacheLoaded() || !dataContext.isCruiseCacheUpToDate()) { + + // load (or reload) cache + CruiseCacheLoader cruiseCacheLoader = context.createCruiseCacheLoader(getProgressionModel()); + dataContext.loadCruiseCache(cruiseCacheLoader); } // export sampling report - CalcifiedPiecesSamplingExportService service = getContext().getCalcifiedPiecesSamplingExportService(); + CalcifiedPiecesSamplingExportService service = context.getCalcifiedPiecesSamplingExportService(); service.exportCruiseCalcifiedPiecesSamplingsReport(file, pm); } diff --git a/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/individualobservation/SamplingCodeCellEditor.java b/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/individualobservation/SamplingCodeCellEditor.java index 69e228f..3fdba0f 100644 --- a/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/individualobservation/SamplingCodeCellEditor.java +++ b/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/individualobservation/SamplingCodeCellEditor.java @@ -23,7 +23,8 @@ package fr.ifremer.tutti.ui.swing.content.operation.catches.individualobservatio */ import com.google.common.base.Preconditions; -import fr.ifremer.tutti.service.sampling.CruiseSamplingCache; +import fr.ifremer.tutti.service.sampling.CruiseCache; +import fr.ifremer.tutti.service.sampling.SamplingCodeCache; import fr.ifremer.tutti.ui.swing.TuttiUIContext; import fr.ifremer.tutti.ui.swing.content.operation.catches.species.frequency.IndividualObservationBatchRowModel; import fr.ifremer.tutti.ui.swing.content.operation.catches.species.frequency.IndividualObservationBatchTableModel; @@ -146,13 +147,22 @@ public class SamplingCodeCellEditor extends AbstractCellEditor implements TableC } protected void generateCode() { - Optional<CruiseSamplingCache> optionalCruiseSamplingCache = context.getDataContext().getOptionalCruiseSamplingCache(); - if (optionalCruiseSamplingCache.isPresent()) { - int i = optionalCruiseSamplingCache.get().getNextSamplingCodeId(getRow().getSpecies().getReferenceTaxonId()); - row.setSamplingCode(row.getSamplingCodePrefix().toSamplingCode(i)); + + Optional<CruiseCache> optionalCruiseCache = context.getDataContext().getOptionalCruiseCache(); + if (!optionalCruiseCache.isPresent()) { + throw new IllegalStateException("No cruise cache found!"); + } + SamplingCodeCache samplingCodeCache = optionalCruiseCache.get().getSamplingCodeCache(); + int i = samplingCodeCache.getNextSamplingCodeId(getRow().getSpecies().getReferenceTaxonId()); + String samplingCode = row.getSamplingCodePrefix().toSamplingCode(i); + if (log.isInfoEnabled()) { + log.info("Generated sampling code: " + samplingCode); } + row.setSamplingCode(samplingCode); + stopCellEditing(); } + } diff --git a/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/frequency/IndividualObservationBatchTableHandler.java b/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/frequency/IndividualObservationBatchTableHandler.java index 1c1c7f4..7a563e3 100644 --- a/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/frequency/IndividualObservationBatchTableHandler.java +++ b/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/frequency/IndividualObservationBatchTableHandler.java @@ -12,6 +12,8 @@ import fr.ifremer.tutti.persistence.entities.referential.Caracteristic; import fr.ifremer.tutti.persistence.entities.referential.CaracteristicQualitativeValue; import fr.ifremer.tutti.persistence.entities.referential.Species; import fr.ifremer.tutti.service.DecoratorService; +import fr.ifremer.tutti.service.TuttiDataContext; +import fr.ifremer.tutti.service.sampling.CruiseCache; import fr.ifremer.tutti.service.sampling.SamplingCodePrefix; import fr.ifremer.tutti.type.WeightUnit; import fr.ifremer.tutti.ui.swing.content.operation.catches.individualobservation.SamplingCodeCellEditor; @@ -95,12 +97,18 @@ public class IndividualObservationBatchTableHandler implements Closeable { this.model = ui.getModel(); this.model2 = ui.getModel().getIndividualObservationModel(); this.uiHandler = ui.getHandler(); - this.individualObservationUICache = new IndividualObservationUICache(uiHandler.getDataContext().getOptionalCruiseSamplingCache().orElse(null), model); + TuttiDataContext dataContext = uiHandler.getDataContext(); + + Optional<CruiseCache> optionalCruiseCache = dataContext.getOptionalCruiseCache(); + if (!optionalCruiseCache.isPresent()) { + throw new IllegalStateException("Can't find cruise cache"); + } + this.individualObservationUICache = new IndividualObservationUICache(optionalCruiseCache.get(), model); this.individualObservationTable = ui.getObsTable(); this.frequencyTableModel = uiHandler.getTableModel(); this.individualObservationToFrequencyEngine = new IndividualObservationToFrequencyEngine(model2.getIndividualObservationWeightUnit()); - List<Caracteristic> maturityCaracteristics = new ArrayList<>(uiHandler.getDataContext().getMaturityCaracteristics()); + List<Caracteristic> maturityCaracteristics = new ArrayList<>(dataContext.getMaturityCaracteristics()); this.maturityCaracteristics = TuttiEntities.splitById(maturityCaracteristics); @@ -264,19 +272,31 @@ public class IndividualObservationBatchTableHandler implements Closeable { break; case IndividualObservationBatchRowModel.PROPERTY_SAMPLING_CODE: + + String oldValue = (String) evt.getOldValue(); + String newValue = (String) evt.getNewValue(); + + boolean withOldSamplingCode = StringUtils.isNotBlank(oldValue); + boolean withNewSamplingCode = StringUtils.isNotBlank(newValue); + + if (withOldSamplingCode) { + individualObservationUICache.decrementsSamplingCode(oldValue); + } + if (withNewSamplingCode) { + individualObservationUICache.incrementsSamplingCode(newValue); + } + if (row.withSize()) { float size = row.getSize(); - String oldValue = (String) evt.getOldValue(); - String newValue = (String) evt.getNewValue(); - - if (StringUtils.isNotBlank(oldValue)) { - individualObservationUICache.decrementsSamplingNb(gender, maturity, size, oldValue); + if (withOldSamplingCode) { + individualObservationUICache.decrementsSamplingNb(gender, maturity, size); } - if (StringUtils.isNotBlank(newValue)) { - individualObservationUICache.incrementsSamplingNb(gender, maturity, size, newValue); + if (withNewSamplingCode) { + individualObservationUICache.incrementsSamplingNb(gender, maturity, size); } + } break; diff --git a/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/frequency/IndividualObservationUICache.java b/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/frequency/IndividualObservationUICache.java index ab01a3b..5a0bf0a 100644 --- a/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/frequency/IndividualObservationUICache.java +++ b/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/operation/catches/species/frequency/IndividualObservationUICache.java @@ -30,7 +30,9 @@ import fr.ifremer.tutti.persistence.entities.protocol.Zone; import fr.ifremer.tutti.persistence.entities.referential.CaracteristicQualitativeValue; import fr.ifremer.tutti.persistence.entities.referential.Species; import fr.ifremer.tutti.service.DecoratorService; +import fr.ifremer.tutti.service.sampling.CruiseCache; import fr.ifremer.tutti.service.sampling.CruiseSamplingCache; +import fr.ifremer.tutti.service.sampling.SamplingCodeCache; import fr.ifremer.tutti.service.sampling.SamplingCodePrefix; import fr.ifremer.tutti.service.sampling.SamplingEvent; import fr.ifremer.tutti.service.sampling.SamplingListener; @@ -65,13 +67,17 @@ public class IndividualObservationUICache implements Closeable { private static final Log log = LogFactory.getLog(IndividualObservationUICache.class); private final SamplingListener samplingListener; - private final CruiseSamplingCache samplingCache; + private final CruiseCache cruiseCache; + private final SamplingCodeCache samplingCodeCache; private final SpeciesFrequencyUIModel uiModel; private final IndividualObservationBatchUIModel individualObservationModel; + private final boolean withSamplingCache; + private final CruiseSamplingCache cruiseSamplingCache; private SpeciesBatchRowModel speciesEditRow; private FishingOperation fishingOperation; private Species species; + private SpeciesFrequencyUI ui; /** @@ -87,15 +93,16 @@ public class IndividualObservationUICache implements Closeable { * Dès qu'un code de prélèvement est ajouté ou modifié dans l'écran, on l'ajoute ici. */ private final Set<Integer> samplingCodesAvailable = new TreeSet<>(); - /** * Est-ce que le cache est actif ? */ private boolean on; - public IndividualObservationUICache(CruiseSamplingCache samplingCache, SpeciesFrequencyUIModel uiModel) { - - this.samplingCache = samplingCache; + public IndividualObservationUICache(CruiseCache cruiseCache, SpeciesFrequencyUIModel uiModel) { + this.cruiseCache = cruiseCache; + this.withSamplingCache = cruiseCache.useSamplingCache(); + this.cruiseSamplingCache = cruiseCache.getSamplingCruiseCache().orElse(null); + this.samplingCodeCache = cruiseCache.getSamplingCodeCache(); this.uiModel = uiModel; this.individualObservationModel = uiModel.getIndividualObservationModel(); @@ -115,7 +122,7 @@ public class IndividualObservationUICache implements Closeable { } else { // model no more loading, cache is on if data cache is present - on = withSamplingCache(); + on = true; if (log.isInfoEnabled()) { if (on) { log.info("Cache is on : ui model loading is done and sampling cache is present"); @@ -180,9 +187,10 @@ public class IndividualObservationUICache implements Closeable { this.speciesEditRow = speciesEditRow; this.species = speciesEditRow.getSpecies(); this.fishingOperation = fishingOperation; - if (withSamplingCache()) { - samplingCache.addSamplingListener(samplingListener); + if (withSamplingCache) { + cruiseSamplingCache.addSamplingListener(samplingListener); } + this.samplingCodesAvailable.clear(); this.samplingCodesNotAvailable.clear(); @@ -191,9 +199,6 @@ public class IndividualObservationUICache implements Closeable { .forEach(individualObservationRow -> addSamplingCodeNotAvailable(individualObservationRow.getSamplingCode())); } - protected boolean withSamplingCache() { - return samplingCache != null; - } @Override public void close() { @@ -201,8 +206,8 @@ public class IndividualObservationUICache implements Closeable { this.speciesEditRow = null; this.species = null; this.fishingOperation = null; - if (withSamplingCache()) { - samplingCache.removeSamplingListener(samplingListener); + if (withSamplingCache) { + cruiseSamplingCache.removeSamplingListener(samplingListener); } } @@ -233,6 +238,11 @@ public class IndividualObservationUICache implements Closeable { float lengthStep, String samplingCode) { + boolean withSamplingCode = samplingCode != null; + if (withSamplingCode) { + incrementsSamplingCode(samplingCode); + } + if (!on) { if (log.isDebugEnabled()) { log.debug("Cache is off, skip increments individual observations in cache."); @@ -240,15 +250,19 @@ public class IndividualObservationUICache implements Closeable { return; } - Boolean maturity = samplingCache.getMaturity(uiModel.getBatch().getSpecies().getReferenceTaxonId(), maturityQualitativeValue); - samplingCache.addIndividualObservation(fishingOperation, - species, - gender, - maturity, - uiModel.getLengthStepInMm(lengthStep)); + if (withSamplingCache) { + + Boolean maturity = cruiseSamplingCache.getMaturity(uiModel.getBatch().getSpecies().getReferenceTaxonId(), maturityQualitativeValue); + cruiseSamplingCache.addIndividualObservation(fishingOperation, + species, + gender, + maturity, + uiModel.getLengthStepInMm(lengthStep)); - if (samplingCode != null) { - incrementsSamplingNb(gender, maturityQualitativeValue, lengthStep, samplingCode); + } + + if (withSamplingCode) { + incrementsSamplingNb(gender, maturityQualitativeValue, lengthStep); } } @@ -258,12 +272,10 @@ public class IndividualObservationUICache implements Closeable { * @param gender le sexe * @param maturityQualitativeValue l'état de maturité * @param lengthStep la classe de taille - * @param samplingCode le code de prélèvement ajouté */ public void incrementsSamplingNb(CaracteristicQualitativeValue gender, CaracteristicQualitativeValue maturityQualitativeValue, - float lengthStep, - String samplingCode) { + float lengthStep) { if (!on) { if (log.isDebugEnabled()) { @@ -272,17 +284,18 @@ public class IndividualObservationUICache implements Closeable { return; } - Boolean maturity = samplingCache.getMaturity(uiModel.getBatch().getSpecies().getReferenceTaxonId(), maturityQualitativeValue); - int lengthStepInMm = uiModel.getLengthStepInMm(lengthStep); - samplingCache.addSampling(fishingOperation, - species, - gender, - maturity, - lengthStepInMm, - samplingCode); + if (withSamplingCache) { + + Boolean maturity = cruiseSamplingCache.getMaturity(uiModel.getBatch().getSpecies().getReferenceTaxonId(), maturityQualitativeValue); + int lengthStepInMm = uiModel.getLengthStepInMm(lengthStep); + cruiseSamplingCache.addSampling(fishingOperation, + species, + gender, + maturity, + lengthStepInMm); + + } - // Le code n'est plus utilisable - addSamplingCodeNotAvailable(samplingCode); } @@ -332,30 +345,31 @@ public class IndividualObservationUICache implements Closeable { return; } - Boolean maturity = samplingCache.getMaturity(uiModel.getBatch().getSpecies().getReferenceTaxonId(), maturityQualitativeValue); - samplingCache.removeIndividualObservation(fishingOperation, - species, - gender, - maturity, - uiModel.getLengthStepInMm(lengthStep)); + boolean withSamplingCode = samplingCode != null; + + if (withSamplingCode) { + decrementsSamplingCode(samplingCode); + } + + if (withSamplingCache) { + + Boolean maturity = cruiseSamplingCache.getMaturity(uiModel.getBatch().getSpecies().getReferenceTaxonId(), maturityQualitativeValue); + cruiseSamplingCache.removeIndividualObservation(fishingOperation, + species, + gender, + maturity, + uiModel.getLengthStepInMm(lengthStep)); - if (samplingCode != null) { - decrementsSamplingNb(gender, maturityQualitativeValue, lengthStep, samplingCode); + if (withSamplingCode) { + decrementsSamplingNb(gender, maturityQualitativeValue, lengthStep); + } } + } - /** - * Ajoute une observation individuelle via ses composantes (sexe, maturité, classe de taille) dans le cache. - * - * @param gender le sexe - * @param maturityQualitativeValue l'état de maturité - * @param lengthStep la classe de taille - * @param samplingCode le code de prélèvement supprimé - */ public void decrementsSamplingNb(CaracteristicQualitativeValue gender, CaracteristicQualitativeValue maturityQualitativeValue, - Float lengthStep, - String samplingCode) { + Float lengthStep) { if (!on) { if (log.isDebugEnabled()) { @@ -364,16 +378,16 @@ public class IndividualObservationUICache implements Closeable { return; } - Boolean maturity = samplingCache.getMaturity(uiModel.getBatch().getSpecies().getReferenceTaxonId(), maturityQualitativeValue); - samplingCache.removeSampling(fishingOperation, - species, - gender, - maturity, - uiModel.getLengthStepInMm(lengthStep), - samplingCode); + if (withSamplingCache) { - addSamplingCodeAvailable(samplingCode); + Boolean maturity = cruiseSamplingCache.getMaturity(uiModel.getBatch().getSpecies().getReferenceTaxonId(), maturityQualitativeValue); + cruiseSamplingCache.removeSampling(fishingOperation, + species, + gender, + maturity, + uiModel.getLengthStepInMm(lengthStep)); + } } /** @@ -431,41 +445,20 @@ public class IndividualObservationUICache implements Closeable { return samplingCodesAvailable.contains(samplingCode); } - public void addSamplingCodeAvailable(String samplingCode) { - - int samplingCodeNumber = SamplingCodePrefix.extractSamplingCodeIdFromSamplingCode(samplingCode); - if (log.isDebugEnabled()) { - log.debug(String.format("Make samplingCode: %s (%d) available", samplingCode, samplingCodeNumber)); - } - samplingCodesNotAvailable.remove(samplingCodeNumber); - samplingCodesAvailable.add(samplingCodeNumber); - - } - - public void addSamplingCodeNotAvailable(String samplingCode) { - - int samplingCodeNumber = SamplingCodePrefix.extractSamplingCodeIdFromSamplingCode(samplingCode); - if (log.isDebugEnabled()) { - log.debug(String.format("Make samplingCode: %s (%d) not available", samplingCode, samplingCodeNumber)); - } - samplingCodesNotAvailable.add(samplingCodeNumber); - samplingCodesAvailable.remove(samplingCodeNumber); - - } - public void updateSelectedRow(IndividualObservationBatchRowModel selectedRow) { SamplingEvent event = null; - if (withSamplingCache() && selectedRow != null && selectedRow.withSize()) { + if (withSamplingCache && selectedRow != null && selectedRow.withSize()) { CaracteristicQualitativeValue maturityQualitativeValue = individualObservationModel.getMaturityValue(selectedRow); - Boolean maturity = samplingCache.getMaturity(selectedRow.getSpecies().getReferenceTaxonId(), maturityQualitativeValue); + Boolean maturity = cruiseSamplingCache.getMaturity(selectedRow.getSpecies().getReferenceTaxonId(), maturityQualitativeValue); int lengthstep = uiModel.getLengthStepInMm(selectedRow.getSize()); - event = samplingCache.getEventForSummary(fishingOperation, species, maturity, individualObservationModel.getGender(selectedRow), lengthstep).orElse(null); + event = cruiseSamplingCache.getEventForSummary(fishingOperation, species, maturity, individualObservationModel.getGender(selectedRow), lengthstep).orElse(null); } + displaySummary(event); } @@ -523,9 +516,49 @@ public class IndividualObservationUICache implements Closeable { return ui != null; } - protected String getLabelForSamplingNumber(int value, Integer max) { + private String getLabelForSamplingNumber(int value, Integer max) { Decorator<Integer> valueDecorator = ui.getHandler().getDecorator(Integer.class, DecoratorService.NULL_INFINITE); return "<strong>" + valueDecorator.toString(value) + "</strong> (" + valueDecorator.toString(max) + ")"; } + public void decrementsSamplingCode(String samplingCode) { + + samplingCodeCache.removeSamplingCode(uiModel.getBatch().getSpecies().getReferenceTaxonId(), samplingCode); + + // Le code est utilisable + addSamplingCodeAvailable(samplingCode); + + } + + public void incrementsSamplingCode(String samplingCode) { + + samplingCodeCache.addSamplingCode(uiModel.getBatch().getSpecies().getReferenceTaxonId(), samplingCode); + + // Le code n'est plus utilisable + addSamplingCodeNotAvailable(samplingCode); + + } + + private void addSamplingCodeNotAvailable(String samplingCode) { + + int samplingCodeNumber = SamplingCodePrefix.extractSamplingCodeIdFromSamplingCode(samplingCode); + if (log.isDebugEnabled()) { + log.debug(String.format("Make samplingCode: %s (%d) not available", samplingCode, samplingCodeNumber)); + } + samplingCodesNotAvailable.add(samplingCodeNumber); + samplingCodesAvailable.remove(samplingCodeNumber); + + } + + private void addSamplingCodeAvailable(String samplingCode) { + + int samplingCodeNumber = SamplingCodePrefix.extractSamplingCodeIdFromSamplingCode(samplingCode); + if (log.isDebugEnabled()) { + log.debug(String.format("Make samplingCode: %s (%d) available", samplingCode, samplingCodeNumber)); + } + samplingCodesNotAvailable.remove(samplingCodeNumber); + samplingCodesAvailable.add(samplingCodeNumber); + + } + } diff --git a/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/protocol/actions/SaveProtocolAction.java b/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/protocol/actions/SaveProtocolAction.java index 5329a11..fa18d0f 100644 --- a/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/protocol/actions/SaveProtocolAction.java +++ b/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/protocol/actions/SaveProtocolAction.java @@ -65,7 +65,6 @@ public class SaveProtocolAction extends LongActionSupport<EditProtocolUIModel, E if (log.isInfoEnabled()) { log.info("bean zones " + bean.getZone()); - log.info("bean zones " + bean.getZone()); } if (log.isDebugEnabled()) { @@ -86,15 +85,14 @@ public class SaveProtocolAction extends LongActionSupport<EditProtocolUIModel, E context.setProtocolId(saved.getId()); - getDataContext().resetCruiseSamplingCache(); + getDataContext().closeCruiseCache(); model.setModify(false); } @Override public void postSuccessAction() { - getContext().getMainUI().getHandler().setBodyTitle( - EditProtocolUIHandler.getTitle(true)); + getContext().getMainUI().getHandler().setBodyTitle(EditProtocolUIHandler.getTitle(true)); getUI().getSaveWarningContainer().setVisible(false); } -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.
participants (1)
-
codelutin.com scm