/**
* Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.engine.function.exclusion;
import java.util.Collection;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import com.google.common.collect.MapMaker;
import com.google.common.collect.Sets;
import com.opengamma.engine.function.FunctionDefinition;
/**
* Partial implementation of {@link FunctionExclusionGroups} that caches the lookups.
*/
public abstract class AbstractFunctionExclusionGroups implements FunctionExclusionGroups {
/**
* Placeholder for null as the concurrent map implementation doesn't let us use null keys or values.
*/
private static final FunctionExclusionGroup NULL = new FunctionExclusionGroup();
private final ConcurrentMap<Object, FunctionExclusionGroup> _groupsByKey = new ConcurrentHashMap<Object, FunctionExclusionGroup>();
private final ConcurrentMap<FunctionDefinition, FunctionExclusionGroup> _groupsByFunction = new MapMaker().weakKeys().makeMap();
/**
* Returns a key that identifies the exclusion group, if any.
*
* @param function the function to test
* @return the key or null if the function is not part of a group
*/
protected abstract Object getKey(FunctionDefinition function);
protected FunctionExclusionGroup createExclusionGroup(final Object key, final String displayName) {
return new FunctionExclusionGroup(key, displayName);
}
protected String createDisplayName(final Object key) {
return key.toString();
}
protected FunctionExclusionGroup createExclusionGroup(final Object key) {
return createExclusionGroup(key, createDisplayName(key));
}
protected Object getKey(final FunctionExclusionGroup group) {
return group.getKey();
}
protected String getDisplayName(final FunctionExclusionGroup group) {
return group.getDisplayName();
}
@Override
public FunctionExclusionGroup getExclusionGroup(final FunctionDefinition function) {
FunctionExclusionGroup group = _groupsByFunction.get(function);
if (group == null) {
final Object key = getKey(function);
if (key == null) {
_groupsByFunction.putIfAbsent(function, NULL);
return null;
} else {
group = _groupsByKey.get(key);
if (group == null) {
group = createExclusionGroup(key);
final FunctionExclusionGroup existing = _groupsByKey.putIfAbsent(key, group);
if (existing == null) {
_groupsByFunction.putIfAbsent(function, group);
} else {
group = existing;
}
}
return group;
}
} else {
if (group != NULL) {
return group;
} else {
return null;
}
}
}
@Override
public boolean isExcluded(final FunctionExclusionGroup group, final Collection<FunctionExclusionGroup> existing) {
return existing.contains(group);
}
@Override
public Collection<FunctionExclusionGroup> withExclusion(final Collection<FunctionExclusionGroup> existing, final FunctionExclusionGroup newGroup) {
final Set<FunctionExclusionGroup> result = Sets.newHashSetWithExpectedSize(existing.size() + 1);
result.addAll(existing);
result.add(newGroup);
return result;
}
}