package de.ovgu.cide.typing.model;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import de.ovgu.cide.features.IFeature;
import de.ovgu.cide.features.IFeatureModel;
public abstract class AbstractCachingEvaluationStrategy implements
IEvaluationStrategy {
private final WeakHashMap<IFeatureModel, Map<Set<IFeature>, Map<Set<IFeature>, Boolean>>> impliesCache = new WeakHashMap<IFeatureModel, Map<Set<IFeature>, Map<Set<IFeature>, Boolean>>>();
private final WeakHashMap<IFeatureModel, Map<Set<IFeature>, Boolean>> existsCache = new WeakHashMap<IFeatureModel, Map<Set<IFeature>, Boolean>>();
// debug and profiling only
public void clearCache() {
impliesCache.clear();
existsCache.clear();
DebugTyping.profiling_resetSATCaches = false;
}
/**
* non-caching, delegated to implies. override if necessary
*/
public boolean equal(IFeatureModel featureModel, Set<IFeature> source,
Set<IFeature> target) {
return implies(featureModel, source, target)
&& implies(featureModel, target, source);
}
/**
* caching, delegates to calcImplies which must be implemented by
* subclasses. this method should usually not be overridden
*/
public boolean implies(IFeatureModel featureModel, Set<IFeature> source,
Set<IFeature> target) {
if (DebugTyping.profiling_resetSATCaches)
clearCache();
Map<Set<IFeature>, Map<Set<IFeature>, Boolean>> cacheForFeatureModel = impliesCache
.get(featureModel);
if (cacheForFeatureModel != null) {
Map<Set<IFeature>, Boolean> cacheForSource = cacheForFeatureModel
.get(source);
if (cacheForSource != null) {
Boolean cachedValue = cacheForSource.get(target);
if (cachedValue != null) {
return cachedValue.booleanValue();
}
}
}
boolean result = calcImplies(featureModel, source, target);
storeInImpliesCache(featureModel, source, target, result);
return result;
}
public boolean exists(IFeatureModel featureModel, Set<IFeature> features) {
if (DebugTyping.profiling_resetSATCaches)
clearCache();
Map<Set<IFeature>, Boolean> cacheForFeatureModel = existsCache
.get(featureModel);
if (cacheForFeatureModel != null) {
Boolean exists = cacheForFeatureModel.get(features);
if (exists != null)
return exists.booleanValue();
}
boolean result = calcExists(featureModel, features);
storeInExistsCache(featureModel, features, result);
return result;
}
private void storeInImpliesCache(IFeatureModel featureModel,
Set<IFeature> source, Set<IFeature> target, boolean result) {
Map<Set<IFeature>, Map<Set<IFeature>, Boolean>> cacheForFeatureModel = impliesCache
.get(featureModel);
if (cacheForFeatureModel == null) {
cacheForFeatureModel = new HashMap<Set<IFeature>, Map<Set<IFeature>, Boolean>>();
impliesCache.put(featureModel, cacheForFeatureModel);
}
Map<Set<IFeature>, Boolean> cacheForSource = cacheForFeatureModel
.get(source);
if (cacheForSource == null) {
cacheForSource = new HashMap<Set<IFeature>, Boolean>();
cacheForFeatureModel.put(source, cacheForSource);
}
cacheForSource.put(target, new Boolean(result));
}
private void storeInExistsCache(IFeatureModel featureModel,
Set<IFeature> features, boolean result) {
Map<Set<IFeature>, Boolean> cacheForFeatureModel = existsCache
.get(featureModel);
if (cacheForFeatureModel == null) {
cacheForFeatureModel = new HashMap<Set<IFeature>, Boolean>();
existsCache.put(featureModel, cacheForFeatureModel);
}
cacheForFeatureModel.put(features, result);
}
protected abstract boolean calcImplies(IFeatureModel featureModel,
Set<IFeature> source, Set<IFeature> target);
protected abstract boolean calcExists(IFeatureModel featureModel,
Set<IFeature> features);
public void clearCache(IFeatureModel featureModel) {
impliesCache.remove(featureModel);
existsCache.remove(featureModel);
}
}