This is an automated email from the git hooks/post-receive script. New commit to branch feature/8145 in repository tutti. See https://gitlab.nuiton.org/codelutin/tutti.git commit 0c63c73a7a09cbcdd7827035ad99096e85f50e7e Author: Tony CHEMIT <chemit@codelutin.com> Date: Sat Mar 19 16:33:11 2016 +0100 Revue du cache --- .../service/samplingCache/CruiseSamplingCache.java | 171 ++++++++++----------- .../samplingCache/CruiseSamplingInternalCache.java | 146 ++++++++++++++++++ 2 files changed, 226 insertions(+), 91 deletions(-) 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 index ec5a295..0d67031 100644 --- 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 @@ -34,56 +34,52 @@ 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.ArrayList; +import javax.swing.event.EventListenerList; +import java.io.Closeable; import java.util.Collection; import java.util.Collections; import java.util.HashMap; -import java.util.List; 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 { +public class CruiseSamplingCache implements Closeable { /** 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 CruiseSamplingInternalCache totalCruiseCache = new CruiseSamplingInternalCache(); + protected final CruiseSamplingInternalCache zoneCache = new CruiseSamplingInternalCache(); + protected final CruiseSamplingInternalCache operationCache = new CruiseSamplingInternalCache(); protected final Map<TuttiLocation, Zone> zonesByLocations = new HashMap<>(); protected final Multimap<Integer, CalcifiedPiecesSamplingDefinition> cpsDefinitionsBySpecies = HashMultimap.create(); - protected final List<SamplingListener> listeners = new ArrayList<>(); + protected final EventListenerList listeners = new EventListenerList(); 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)); + .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); }); @@ -93,6 +89,22 @@ public class CruiseSamplingCache { speciesProtocol.getCalcifiedPiecesSamplingDefinition())); } + @Override + public void close() { + if (log.isInfoEnabled()) { + log.info("Closing cruise sampling cache."); + } + totalCruiseCache.close(); + zoneCache.close(); + operationCache.close(); + zonesByLocations.clear(); + cpsDefinitionsBySpecies.clear(); + SamplingListener[] samplingListeners = listeners.getListeners(SamplingListener.class); + for (SamplingListener listener : samplingListeners) { + removeSamplingListener(listener); + } + } + public void increment(FishingOperation operation, Species species, CaracteristicQualitativeValue gender, @@ -107,6 +119,10 @@ public class CruiseSamplingCache { if (cpsDefinitionOpt.isPresent()) { CalcifiedPiecesSamplingDefinition cpsDefinition = cpsDefinitionOpt.get(); + + if (log.isInfoEnabled()) { + log.info("Found matching sampling definition: " + cpsDefinition); + } int samplingInterval = cpsDefinition.getSamplingInterval(); // on ne prend pas en compte les intervales à 0, ni quand l'espece doit etre sexee et que le sexe est nul @@ -115,28 +131,30 @@ public class CruiseSamplingCache { if (!cpsDefinition.isSex()) { gender = null; } + CruiseSamplingInternalCache.CruiseSamplingInternalCacheKey samplingKey = CruiseSamplingInternalCache.newCruiseSamplingInternalCacheKey(species, gender, maturity, lengthStep); + Optional<Zone> zone = findZone(operation); - String samplingKey = toKey(species, gender, maturity, lengthStep); - int totalValue = increment(totalCruiseCache, samplingKey); + int totalValue = totalCruiseCache.increment(samplingKey); int zoneValue = 0; if (zone.isPresent()) { - zoneValue = increment(zoneCache, toKey(zone.get(), samplingKey)); + CruiseSamplingInternalCache.ZoneCruiseSamplingInternalCacheKey zoneKey = samplingKey.toZoneKey(zone.get()); + zoneValue = zoneCache.increment(zoneKey); } - int operationValue = increment(operationCache, toKey(operation, samplingKey)); + CruiseSamplingInternalCache.FishingOperationCruiseSamplingInternalCacheKey operationKey = samplingKey.toFishingOperationKey(operation); + int operationValue = operationCache.increment(operationKey); if (log.isInfoEnabled()) { log.info("increment " + samplingKey + " => op " + operationValue + " / zone " + zoneValue + " / cruise " + totalValue); } - if (!listeners.isEmpty()) { - if (totalValue == 1 || totalValue % samplingInterval == 1) { - if (log.isInfoEnabled()) { - log.info("-> needs sampling"); - } - fireSamplingNeeded(lengthStep, gender, maturity, cpsDefinition, samplingInterval, totalValue, zoneValue, operationValue); + if (totalValue == 1 || totalValue % samplingInterval == 1) { + if (log.isInfoEnabled()) { + log.info("-> needs sampling"); } + fireSamplingNeeded(lengthStep, gender, maturity, cpsDefinition, samplingInterval, totalValue, zoneValue, operationValue); } + } } } @@ -156,6 +174,9 @@ public class CruiseSamplingCache { if (cpsDefinitionOpt.isPresent()) { CalcifiedPiecesSamplingDefinition cpsDefinition = cpsDefinitionOpt.get(); + if (log.isInfoEnabled()) { + log.info("Found matching sampling definition: " + cpsDefinition); + } int samplingInterval = cpsDefinition.getSamplingInterval(); // on ne prend pas en compte les intervales à 0, ni quand l'espece doit etre sexee et que le sexe est nul @@ -165,16 +186,18 @@ public class CruiseSamplingCache { gender = null; } + CruiseSamplingInternalCache.CruiseSamplingInternalCacheKey samplingKey = CruiseSamplingInternalCache.newCruiseSamplingInternalCacheKey(species, gender, maturity, lengthStep); + Optional<Zone> zone = findZone(operation); - String samplingKey = toKey(species, gender, maturity, lengthStep); - int totalValue = decrement(totalCruiseCache, samplingKey); + int totalValue = totalCruiseCache.decrement(samplingKey); int zoneValue = 0; if (zone.isPresent()) { - zoneValue = decrement(zoneCache, toKey(zone.get(), samplingKey)); + CruiseSamplingInternalCache.ZoneCruiseSamplingInternalCacheKey zoneKey = samplingKey.toZoneKey(zone.get()); + zoneValue = zoneCache.decrement(zoneKey); } - int operationValue = decrement(operationCache, toKey(operation, samplingKey)); - + CruiseSamplingInternalCache.FishingOperationCruiseSamplingInternalCacheKey operationKey = samplingKey.toFishingOperationKey(operation); + int operationValue = operationCache.decrement(operationKey); if (log.isInfoEnabled()) { log.info("decrement " + samplingKey + " => op " + operationValue + " / zone " + zoneValue + " / cruise " + totalValue); @@ -184,64 +207,21 @@ public class CruiseSamplingCache { } public void addSamplingListener(SamplingListener listener) { - listeners.add(listener); + listeners.add(SamplingListener.class, listener); } public void removeSamplingListener(SamplingListener listener) { - listeners.remove(listener); - } - - 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 int increment(Map<String, MutableInt> map, String samplingKey) { - MutableInt value = map.computeIfAbsent(samplingKey, s -> new MutableInt(0)); - value.increment(); - return value.intValue(); - } - - protected int decrement(Map<String, MutableInt> map, String samplingKey) { - MutableInt value = map.get(samplingKey); - value.decrement(); - return value.intValue(); + listeners.remove(SamplingListener.class, listener); } protected Optional<CalcifiedPiecesSamplingDefinition> getCalcifiedPiecesSamplingDefinition(Species species, Boolean maturity, float lengthStep) { Collection<CalcifiedPiecesSamplingDefinition> cpsDefinitions = cpsDefinitionsBySpecies.get(species.getReferenceTaxonId()); return cpsDefinitions.stream() - .filter(cpsDef -> Objects.equals(cpsDef.getMaturity(), maturity) - && lengthStep >= cpsDef.getMinSize() - && (cpsDef.getMaxSize() == null - || lengthStep <= cpsDef.getMaxSize())) - .findFirst(); + .filter(cpsDef -> Objects.equals(cpsDef.getMaturity(), maturity) + && lengthStep >= cpsDef.getMinSize() + && (cpsDef.getMaxSize() == null + || lengthStep <= cpsDef.getMaxSize())) + .findFirst(); } protected Optional<Zone> findZone(FishingOperation operation) { @@ -270,12 +250,21 @@ public class CruiseSamplingCache { protected void fireSamplingNeeded(float lengthStep, CaracteristicQualitativeValue gender, Boolean maturity, CalcifiedPiecesSamplingDefinition cpsDefinition, int samplingInterval, int totalValue, int zoneValue, int operationValue) { - int nbForCruise = getSamplingNumber(totalValue, samplingInterval); - int nbForZone = getSamplingNumber(zoneValue, samplingInterval); - int nbForOperation = getSamplingNumber(operationValue, samplingInterval); - SamplingEvent event = new SamplingEvent(this, lengthStep, gender, maturity, cpsDefinition, nbForCruise, nbForZone, nbForOperation); - listeners.forEach(listener -> listener.samplingNeeded(event)); + SamplingListener[] samplingListeners = listeners.getListeners(SamplingListener.class); + if (samplingListeners.length > 0) { + + int nbForCruise = getSamplingNumber(totalValue, samplingInterval); + int nbForZone = getSamplingNumber(zoneValue, samplingInterval); + int nbForOperation = getSamplingNumber(operationValue, samplingInterval); + + SamplingEvent event = new SamplingEvent(this, lengthStep, gender, maturity, cpsDefinition, nbForCruise, nbForZone, nbForOperation); + for (SamplingListener listener : samplingListeners) { + listener.samplingNeeded(event); + } + + } + } } diff --git a/tutti-service/src/main/java/fr/ifremer/tutti/service/samplingCache/CruiseSamplingInternalCache.java b/tutti-service/src/main/java/fr/ifremer/tutti/service/samplingCache/CruiseSamplingInternalCache.java new file mode 100644 index 0000000..97f51c9 --- /dev/null +++ b/tutti-service/src/main/java/fr/ifremer/tutti/service/samplingCache/CruiseSamplingInternalCache.java @@ -0,0 +1,146 @@ +package fr.ifremer.tutti.service.samplingCache; + +import fr.ifremer.tutti.persistence.entities.data.FishingOperation; +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 org.apache.commons.lang3.mutable.MutableInt; + +import java.io.Closeable; +import java.util.Map; +import java.util.Objects; +import java.util.TreeMap; + +/** + * Created on 19/03/16. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 4.5 + */ +class CruiseSamplingInternalCache implements Closeable { + + protected final Map<String, MutableInt> data = new TreeMap<>(); + + public int increment(CruiseSamplingInternalCacheKey samplingKey) { + MutableInt value = data.computeIfAbsent(samplingKey.toString(), s -> new MutableInt(0)); + value.increment(); + return value.intValue(); + } + + public int decrement(CruiseSamplingInternalCacheKey samplingKey) { + MutableInt value = data.get(samplingKey.toString()); + value.decrement(); + return value.intValue(); + } + + @Override + public void close() { + data.clear(); + } + + public static CruiseSamplingInternalCacheKey newCruiseSamplingInternalCacheKey(Species species, CaracteristicQualitativeValue gender, Boolean maturity, Float lengthStep) { + Objects.requireNonNull(species); + Objects.requireNonNull(lengthStep); + return new CruiseSamplingInternalCacheKey(species, gender, maturity, lengthStep); + } + + /** + * Représente la clef d'un objet du cache. + * + * Created on 19/03/16. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 4.5 + */ + static class CruiseSamplingInternalCacheKey { + + protected static final String KEY_SEPARATOR = "#"; + + private final Species species; + private final CaracteristicQualitativeValue gender; + private final Boolean maturity; + private final Float lengthStep; + + CruiseSamplingInternalCacheKey(Species species, CaracteristicQualitativeValue gender, Boolean maturity, Float lengthStep) { + Objects.requireNonNull(species); + Objects.requireNonNull(lengthStep); + + this.species = species; + this.gender = gender; + this.maturity = maturity; + this.lengthStep = lengthStep; + } + + CruiseSamplingInternalCacheKey(CruiseSamplingInternalCacheKey cruiseSamplingInternalCacheKey) { + this(cruiseSamplingInternalCacheKey.species, + cruiseSamplingInternalCacheKey.gender, + cruiseSamplingInternalCacheKey.maturity, + cruiseSamplingInternalCacheKey.lengthStep); + } + + public ZoneCruiseSamplingInternalCacheKey toZoneKey(Zone zone) { + Objects.requireNonNull(zone); + return new ZoneCruiseSamplingInternalCacheKey(this, zone); + } + + public FishingOperationCruiseSamplingInternalCacheKey toFishingOperationKey(FishingOperation fishingOperation) { + Objects.requireNonNull(fishingOperation); + return new FishingOperationCruiseSamplingInternalCacheKey(this, fishingOperation); + } + + @Override + public String toString() { + return species.getReferenceTaxonId() + + KEY_SEPARATOR + (gender != null ? gender.getId() : null) + + KEY_SEPARATOR + maturity + + KEY_SEPARATOR + lengthStep; + } + + } + + /** + * Représente la clef d'un objet du cache. + * + * Created on 19/03/16. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 4.5 + */ + static class FishingOperationCruiseSamplingInternalCacheKey extends CruiseSamplingInternalCacheKey { + + private final FishingOperation fishingOperation; + + FishingOperationCruiseSamplingInternalCacheKey(CruiseSamplingInternalCacheKey cruiseSamplingInternalCacheKey, FishingOperation fishingOperation) { + super(cruiseSamplingInternalCacheKey); + this.fishingOperation = fishingOperation; + } + + @Override + public String toString() { + return fishingOperation.getId() + KEY_SEPARATOR + super.toString(); + } + } + + /** + * Représente la clef d'un objet du cache. + * + * Created on 19/03/16. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 4.5 + */ + static class ZoneCruiseSamplingInternalCacheKey extends CruiseSamplingInternalCacheKey { + + private final Zone zone; + + ZoneCruiseSamplingInternalCacheKey(CruiseSamplingInternalCacheKey cruiseSamplingInternalCacheKey, Zone zone) { + super(cruiseSamplingInternalCacheKey); + this.zone = zone; + } + + @Override + public String toString() { + return zone.getId() + KEY_SEPARATOR + super.toString(); + } + } +} -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.