AbstractLimitsComputerWithCache.java
/**
* Copyright (c) 2024, RTE (http://www.rte-france.com)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* SPDX-License-Identifier: MPL-2.0
*/
package com.powsybl.iidm.network.limitmodification;
import com.powsybl.iidm.network.LimitType;
import com.powsybl.iidm.network.ThreeSides;
import com.powsybl.iidm.network.limitmodification.result.LimitsContainer;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
/**
* <p>Abstract class responsible for computing limits (potentially altered from the ones declared on
* the network element).</p>
* <p>Already computed altered limits are stored in an internal cache to avoid unnecessary computations.
* This cache should be cleared with {@link #clearCache()} when the reductions to apply are changed.</p>
*
* @author Olivier Perrin {@literal <olivier.perrin at rte-france.com>}
*/
public abstract class AbstractLimitsComputerWithCache<P, L> implements LimitsComputer<P, L> {
private final Map<CacheKey<P>, LimitsContainer<L>> reducedLimitsCache;
protected AbstractLimitsComputerWithCache() {
this.reducedLimitsCache = new HashMap<>();
}
/**
* {@inheritDoc}
* <p>Resulting limits are stored in an internal cache, by (identifier's ID, limit type, side), in order to avoid
* unnecessary re-computation. If needed, this cache can be cleared using {@link #clearCache()}.</p>
*
* @param processable The network element for which the reduced limits must be computed
* @param limitType The type of the limits to process
* @param side The side of <code>processable</code> on which the limits should be retrieved
* @param monitoringOnly If <code>true</code>, compute the limits to use for a monitoring only use case.
* If <code>false</code>, compute the limits to use for a monitoring + action use case.
* @return an object containing the original limits and the altered ones
*/
@Override
public Optional<LimitsContainer<L>> computeLimits(P processable, LimitType limitType, ThreeSides side, boolean monitoringOnly) {
Objects.requireNonNull(processable);
// Look into the cache to avoid recomputing reduced limits if they were already computed
// with the same limit reductions
CacheKey<P> cacheKey = new CacheKey<>(processable, limitType, side, monitoringOnly);
if (reducedLimitsCache.containsKey(cacheKey)) {
return Optional.of(reducedLimitsCache.get(cacheKey));
}
return computeUncachedLimits(processable, limitType, side, monitoringOnly);
}
/**
* <p>Retrieve the limits on <code>processable</code> then apply modifications on them.</p>
* <p>If no modifications applies on the resulting {@link LimitsContainer} must contains the same object for
* the original and the reduced limits.</p>
* <p>This function is called when the corresponding limits were not found in the cache.</p>
* <p>This function is responsible for the addition of the computed limit in the cache
* (via the {@link #putInCache} method).</p>
*
* @param processable the network element for which the limits must be retrieved and modified
* @param limitType the type of limits to process
* @param side the side of the network element where to retrieve the original limits
* @param monitoringOnly If <code>true</code>, compute the limits to use for a monitoring only use case.
* If <code>false</code>, compute the limits to use for a monitoring + action use case.
* @return an object containing both the original and the modified limits.
*/
protected abstract Optional<LimitsContainer<L>> computeUncachedLimits(P processable, LimitType limitType, ThreeSides side, boolean monitoringOnly);
protected void putInCache(P processable, LimitType limitType, ThreeSides side, boolean monitoringOnly,
LimitsContainer<L> limitsContainer) {
reducedLimitsCache.put(new CacheKey<>(processable, limitType, side, monitoringOnly), limitsContainer);
}
/**
* <p>Clear the cache containing the already computed limits.</p>
* <p>This method must be called when the modifications to apply on the original limits of a network element
* are changed.</p>
*/
public void clearCache() {
reducedLimitsCache.clear();
}
/**
* <p>Key for the cache of already computed limits.</p>
* @param processable the processable object
* @param type the limits type corresponding to the limits to cache
* @param side the side corresponding to the limits to cache
* @param monitoringOnly If <code>true</code>, the limits are for a monitoring only use case.
* If <code>false</code>, the limits are for a monitoring + action use case.
*/
private record CacheKey<P>(P processable, LimitType type, ThreeSides side, boolean monitoringOnly) {
}
}