/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.financial.marketdatasnapshot;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.opengamma.core.marketdatasnapshot.SnapshotDataBundle;
import com.opengamma.core.marketdatasnapshot.ValueSnapshot;
import com.opengamma.core.marketdatasnapshot.impl.ManageableUnstructuredMarketDataSnapshot;
import com.opengamma.core.value.MarketDataRequirementNames;
import com.opengamma.engine.depgraph.DependencyGraph;
import com.opengamma.engine.depgraph.DependencyNode;
import com.opengamma.engine.value.ValueProperties;
import com.opengamma.engine.value.ValueSpecification;
import com.opengamma.engine.view.ViewComputationResultModel;
import com.opengamma.engine.view.cycle.ComputationCacheResponse;
import com.opengamma.engine.view.cycle.ComputationCycleQuery;
import com.opengamma.engine.view.cycle.ViewCycle;
import com.opengamma.id.ExternalIdBundle;
import com.opengamma.util.tuple.Pair;
/**
* Extracts some type of structured object from a cycle
*
* @param <TKey> the key by which these snaps are ided
* @param <TCalculatedValue> The type of value which comes out of the engine
* @param <TSnapshot> The type of value which is stored in the snapshots
*/
public abstract class StructuredSnapper<TKey, TCalculatedValue, TSnapshot> {
private static final Logger s_logger = LoggerFactory.getLogger(StructuredSnapper.class);
private final String _requirementName;
public StructuredSnapper(final String requirementName) {
super();
_requirementName = requirementName.intern();
}
public String getRequirementName() {
return _requirementName;
}
public Map<TKey, TSnapshot> getValues(final ViewComputationResultModel results, final Map<String, DependencyGraph> graphs,
final ViewCycle viewCycle) {
final Map<TKey, TCalculatedValue> calculatedValues = getValues(viewCycle, graphs);
final Map<TKey, TSnapshot> ret = new HashMap<TKey, TSnapshot>();
for (final Entry<TKey, TCalculatedValue> entry : calculatedValues.entrySet()) {
final TSnapshot snapshot = buildSnapshot(results, entry.getKey(), entry.getValue());
ret.put(entry.getKey(), snapshot);
}
return ret;
}
protected static String getSingleProperty(final ValueSpecification spec, final String propertyName) {
final ValueProperties properties = spec.getProperties();
final Set<String> curves = properties.getValues(propertyName);
if (curves.size() != 1) {
throw new IllegalArgumentException("Couldn't find curve property from " + spec);
}
final String curve = Iterables.get(curves, 0);
return curve;
}
private Map<TKey, TCalculatedValue> getValues(final ViewCycle viewCycle, final Map<String, DependencyGraph> dependencyGraphs) {
final Map<String, Collection<ValueSpecification>> values = getMatchingSpecifications(dependencyGraphs, _requirementName);
final Map<TKey, TCalculatedValue> ts = new HashMap<TKey, TCalculatedValue>();
for (final Entry<String, Collection<ValueSpecification>> entry : values.entrySet()) {
final Iterable<ValueSpecification> requiredSpecsIt = Iterables.filter(entry.getValue(),
new Predicate<ValueSpecification>() {
@Override
public boolean apply(final ValueSpecification input) {
return !ts.containsKey(getKey(input));
}
});
final Collection<ValueSpecification> requiredSpecs = Lists.newArrayList(requiredSpecsIt);
if (requiredSpecs.isEmpty()) {
continue;
}
final ComputationCycleQuery cacheQuery = new ComputationCycleQuery();
cacheQuery.setCalculationConfigurationName(entry.getKey());
cacheQuery.setValueSpecifications(requiredSpecs);
final ComputationCacheResponse computationCacheResponse = viewCycle.queryComputationCaches(cacheQuery);
if (computationCacheResponse.getResults().size() != requiredSpecs.size()) {
s_logger.debug("Failed to get all results from computation cache");
}
final Map<TKey, Pair<ValueSpecification, Object>> infos = Maps.uniqueIndex(computationCacheResponse.getResults(),
new Function<Pair<ValueSpecification, Object>, TKey>() {
@Override
public TKey apply(final Pair<ValueSpecification, Object> from) {
return getKey(from.getFirst());
}
});
for (final Entry<TKey, Pair<ValueSpecification, Object>> result : infos.entrySet()) {
@SuppressWarnings("unchecked")
final TCalculatedValue calcValue = (TCalculatedValue) result.getValue().getSecond();
ts.put(result.getKey(), calcValue);
}
}
return ts;
}
private Map<String, Collection<ValueSpecification>> getMatchingSpecifications(final Map<String, DependencyGraph> graphs,
final String specName) {
final Map<String, Collection<ValueSpecification>> ret = new HashMap<String, Collection<ValueSpecification>>();
for (final Entry<String, DependencyGraph> kvp : graphs.entrySet()) {
final String config = kvp.getKey();
final DependencyGraph graph = kvp.getValue();
final Set<DependencyNode> nodes = graph.getDependencyNodes();
final Iterable<Iterable<ValueSpecification>> specs = Iterables.transform(nodes,
new Function<DependencyNode, Iterable<ValueSpecification>>() {
@Override
public Iterable<ValueSpecification> apply(final DependencyNode input) {
return Iterables.filter(input.getOutputValues(), new Predicate<ValueSpecification>() {
@Override
public boolean apply(final ValueSpecification input) {
return input.getValueName() == _requirementName; // Should be interned
}
});
}
});
final Set<ValueSpecification> specsSet = new HashSet<ValueSpecification>();
for (final Iterable<ValueSpecification> group : specs) {
for (final ValueSpecification valueSpecification : group) {
specsSet.add(valueSpecification);
}
}
ret.put(config, specsSet);
}
return ret;
}
protected static ManageableUnstructuredMarketDataSnapshot getUnstructured(final SnapshotDataBundle bundle) {
final Set<Entry<ExternalIdBundle, Double>> bundlePoints = bundle.getDataPointSet();
final ManageableUnstructuredMarketDataSnapshot snapshot = new ManageableUnstructuredMarketDataSnapshot();
for (final Map.Entry<ExternalIdBundle, Double> bundlePoint : bundle.getDataPointSet()) {
snapshot.putValue(bundlePoint.getKey(), MarketDataRequirementNames.MARKET_VALUE, new ValueSnapshot(bundlePoint.getValue()));
}
return snapshot;
}
abstract TKey getKey(ValueSpecification spec);
abstract TSnapshot buildSnapshot(ViewComputationResultModel resultModel, TKey key, TCalculatedValue calculated);
}