This is an automated email from the git hooks/post-receive script. New commit to branch feature/8043 in repository tutti. See http://git.codelutin.com/tutti.git commit b21ab75ed8881053288e32b49a069dae3986a0bb Author: Kevin Morin <morin@codelutin.com> Date: Fri Mar 11 16:17:10 2016 +0100 création du cache des prélèvements (refs #8043) --- ...dualObservationBatchPersistenceServiceImpl.java | 1 + .../fr/ifremer/tutti/service/TuttiDataContext.java | 55 ++++++++ .../service/samplingCache/CruiseSamplingCache.java | 152 +++++++++++++++++++++ .../EditCatchesForSelectedCruiseAction.java | 1 + .../content/home/actions/EditCatchesAction.java | 1 + .../protocol/actions/SaveProtocolAction.java | 2 + 6 files changed, 212 insertions(+) diff --git a/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/IndividualObservationBatchPersistenceServiceImpl.java b/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/IndividualObservationBatchPersistenceServiceImpl.java index bd5d230..e6850ac 100644 --- a/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/IndividualObservationBatchPersistenceServiceImpl.java +++ b/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/service/IndividualObservationBatchPersistenceServiceImpl.java @@ -279,6 +279,7 @@ public class IndividualObservationBatchPersistenceServiceImpl extends AbstractPe // Link to parent batch target.setBatch(batch); + target.setFishingOperation(fishingOperation); // Label String label = batch.getId() + "_" + source.getSpecies().getReferenceTaxonId(); 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 0c6dd65..5d4803b 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 @@ -26,6 +26,7 @@ import com.google.common.base.Preconditions; import fr.ifremer.tutti.TuttiConfiguration; import fr.ifremer.tutti.persistence.entities.data.Cruise; import fr.ifremer.tutti.persistence.entities.data.FishingOperation; +import fr.ifremer.tutti.persistence.entities.data.IndividualObservationBatch; import fr.ifremer.tutti.persistence.entities.data.Program; import fr.ifremer.tutti.persistence.entities.data.SampleCategoryModel; import fr.ifremer.tutti.persistence.entities.data.SampleCategoryModelEntry; @@ -40,6 +41,7 @@ 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.samplingCache.CruiseSamplingCache; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -126,6 +128,11 @@ public class TuttiDataContext extends AbstractBean implements Closeable { protected Cruise cruise; + /** + * @since 4.5 + */ + protected CruiseSamplingCache cruiseSamplingCache; + protected FishingOperation fishingOperation; protected List<Caracteristic> caracteristics; @@ -414,6 +421,10 @@ public class TuttiDataContext extends AbstractBean implements Closeable { return fishingOperationId!=null; } + public boolean isCruiseSamplingCacheLoaded() { + return cruiseSamplingCache != null; + } + public void setProgramId(String programId) { boolean oldProgramFilled = isProgramFilled(); boolean oldCruiseFilled = isCruiseFilled(); @@ -524,6 +535,44 @@ public class TuttiDataContext extends AbstractBean implements Closeable { return service.getProtocol(); } + public CruiseSamplingCache getCruiseSamplingCache() { + return cruiseSamplingCache; + } + + public void loadCruiseSamplingCache() { + checkOpened(); + if (!isCruiseSamplingCacheLoaded() + && isProtocolFilled() && isCruiseFilled()) { + + TuttiProtocol protocol = getProtocol(); + + if (protocol.isUseCalcifiedPieceSampling()) { + + cruiseSamplingCache = new CruiseSamplingCache(protocol); + + service.getAllFishingOperationIds(getCruiseId()).stream().forEach(operationId -> { + + FishingOperation operation = service.getFishingOperation(operationId); + + List<IndividualObservationBatch> allIndividualObservationBatchsForFishingOperation = + service.getAllIndividualObservationBatchsForFishingOperation(operationId); + + allIndividualObservationBatchsForFishingOperation.forEach( + obs -> cruiseSamplingCache.increment(operation, + obs.getSpecies(), + (CaracteristicQualitativeValue) obs.getCaracteristics().get(service.getSexCaracteristic()), + null, + obs.getSize())); + }); + + if (log.isInfoEnabled()) { + log.info("cruise sampling cache loaded"); + } + } + + } + } + public FishingOperation getFishingOperation() { checkOpened(); if (fishingOperation == null) { @@ -888,6 +937,7 @@ public class TuttiDataContext extends AbstractBean implements Closeable { public void resetCruise() { cruise = null; + resetCruiseSamplingCache(); } public void resetProtocol() { @@ -899,6 +949,11 @@ public class TuttiDataContext extends AbstractBean implements Closeable { defaultIndividualObservationCaracteristics = null; // survey code must be refresh resetSpecies(); + resetCruiseSamplingCache(); + } + + public void resetCruiseSamplingCache() { + cruiseSamplingCache = null; } public void resetGears() { diff --git a/tutti-service/src/main/java/fr/ifremer/tutti/service/samplingCache/CruiseSamplingCache.java b/tutti-service/src/main/java/fr/ifremer/tutti/service/samplingCache/CruiseSamplingCache.java new file mode 100644 index 0000000..ee8a917 --- /dev/null +++ b/tutti-service/src/main/java/fr/ifremer/tutti/service/samplingCache/CruiseSamplingCache.java @@ -0,0 +1,152 @@ +package fr.ifremer.tutti.service.samplingCache; + +import fr.ifremer.tutti.persistence.entities.data.FishingOperation; +import fr.ifremer.tutti.persistence.entities.protocol.SubStrata; +import fr.ifremer.tutti.persistence.entities.protocol.TuttiProtocol; +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.persistence.entities.referential.TuttiLocation; +import org.apache.commons.lang3.mutable.MutableInt; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.TreeMap; +import java.util.stream.Collectors; + +/** + * @author Kevin Morin (Code Lutin) + * @since 4.5 + */ +public class CruiseSamplingCache { + + /** Logger. */ + private static final Log log = LogFactory.getLog(CruiseSamplingCache.class); + + protected static final String KEY_SEPARATOR = "#"; + + protected final Map<String, MutableInt> totalCruiseCache = new TreeMap<>(); + protected final Map<String, MutableInt> zoneCache = new TreeMap<>(); + protected final Map<String, MutableInt> operationCache = new TreeMap<>(); + + protected final Map<TuttiLocation, Zone> zonesByLocations = new HashMap<>(); + + public CruiseSamplingCache(TuttiProtocol protocol) { + + // fill the zones by location + protocol.getZone().forEach(zone -> { + Map<TuttiLocation, Zone> zoneByLocations = zone.getStrata().stream() + .map(strata -> { + if (strata.isSubstrataEmpty()) { + return Collections.singleton(strata.getLocation()); + } + return strata.getSubstrata().stream() + .map(SubStrata::getLocation) + .collect(Collectors.toSet()); + }) + .flatMap(Collection::stream) + .collect(Collectors.toMap(location -> location, location -> zone)); + + zonesByLocations.putAll(zoneByLocations); + }); + } + + public void increment(FishingOperation operation, + Species species, + CaracteristicQualitativeValue gender, + Boolean maturity, + Float lengthStep) { + + Optional<Zone> zone = findZone(operation); + String samplingKey = toKey(species, gender, maturity, lengthStep); + + increment(totalCruiseCache, samplingKey); + if (zone.isPresent()) { + increment(zoneCache, toKey(zone.get(), samplingKey)); + } + increment(operationCache, toKey(operation, samplingKey)); + } + + public void decrement(FishingOperation operation, + Species species, + CaracteristicQualitativeValue gender, + Boolean maturity, + Float lengthStep) { + + Optional<Zone> zone = findZone(operation); + String samplingKey = toKey(species, gender, maturity, lengthStep); + + decrement(totalCruiseCache, samplingKey); + if (zone.isPresent()) { + decrement(zoneCache, toKey(zone.get(), samplingKey)); + } + decrement(operationCache, toKey(operation, samplingKey)); + } + + protected String toKey(Species species, + CaracteristicQualitativeValue gender, + Boolean maturity, + Float lengthStep) { + + Objects.requireNonNull(species); + Objects.requireNonNull(lengthStep); + + return species.getReferenceTaxonId() + KEY_SEPARATOR + + (gender != null ? gender.getId() : null) + KEY_SEPARATOR + + maturity + KEY_SEPARATOR + + lengthStep; + } + + protected String toKey(FishingOperation operation, String samplingKey) { + + Objects.requireNonNull(operation); + Objects.requireNonNull(samplingKey); + + return operation.getId() + KEY_SEPARATOR + samplingKey; + } + + protected String toKey(Zone zone, String samplingKey) { + + //FIXME should never be null +// Objects.requireNonNull(zone); + Objects.requireNonNull(samplingKey); + + return (zone == null ? null : zone.getId()) + KEY_SEPARATOR + samplingKey; + } + + protected void increment(Map<String, MutableInt> map, String samplingKey) { + MutableInt value = map.computeIfAbsent(samplingKey, s -> new MutableInt(0)); + value.increment(); + } + + protected void decrement(Map<String, MutableInt> map, String samplingKey) { + MutableInt value = map.get(samplingKey); + value.decrement(); + } + + protected Optional<Zone> findZone(FishingOperation operation) { + + Optional<Zone> result; + + if (operation.getSubStrata() != null) { + + result = Optional.ofNullable(zonesByLocations.get(operation.getSubStrata())); + + } else if (operation.getStrata() != null) { + + result = Optional.ofNullable(zonesByLocations.get(operation.getStrata())); + + } else { + result = Optional.empty(); + } + + return result; + } + +} diff --git a/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/actions/EditCatchesForSelectedCruiseAction.java b/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/actions/EditCatchesForSelectedCruiseAction.java index f19860c..f0899fc 100644 --- a/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/actions/EditCatchesForSelectedCruiseAction.java +++ b/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/actions/EditCatchesForSelectedCruiseAction.java @@ -59,6 +59,7 @@ public class EditCatchesForSelectedCruiseAction extends AbstractChangeScreenActi } getContext().setValidationContext(ValidationService.VALIDATION_CONTEXT_EDIT); loadReferantials(true); + getDataContext().loadCruiseSamplingCache(); super.doAction(); } diff --git a/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/home/actions/EditCatchesAction.java b/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/home/actions/EditCatchesAction.java index a814c02..c1c4712 100644 --- a/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/home/actions/EditCatchesAction.java +++ b/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/home/actions/EditCatchesAction.java @@ -60,6 +60,7 @@ public class EditCatchesAction extends AbstractChangeScreenAction { log.info("Edit operations of cruise: " + getContext().getCruiseId()); } getContext().setValidationContext(ValidationService.VALIDATION_CONTEXT_EDIT); + getDataContext().loadCruiseSamplingCache(); super.doAction(); } 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 583ab54..5329a11 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 @@ -86,6 +86,8 @@ public class SaveProtocolAction extends LongActionSupport<EditProtocolUIModel, E context.setProtocolId(saved.getId()); + getDataContext().resetCruiseSamplingCache(); + model.setModify(false); } -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.