/** * Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.engine.view.compilation; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.apache.commons.lang.ObjectUtils; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; import com.opengamma.engine.ComputationTargetSpecification; import com.opengamma.engine.depgraph.DependencyGraph; import com.opengamma.engine.depgraph.DependencyNode; import com.opengamma.engine.function.FunctionParameters; import com.opengamma.engine.function.MarketDataAliasingFunction; import com.opengamma.engine.function.MarketDataSourcingFunction; import com.opengamma.engine.marketdata.manipulator.DistinctMarketDataSelector; import com.opengamma.engine.value.ValueProperties; import com.opengamma.engine.value.ValueRequirement; import com.opengamma.engine.value.ValueSpecification; import com.opengamma.util.ArgumentChecker; import com.opengamma.util.tuple.Pair; import com.opengamma.util.tuple.Pairs; /** * Default implementation of {@link CompiledViewCalculationConfiguration}. */ public class CompiledViewCalculationConfigurationImpl implements CompiledViewCalculationConfiguration, Serializable { private static final long serialVersionUID = 1L; private final String _name; private final Set<ComputationTargetSpecification> _computationTargets; private final Map<ValueSpecification, Set<ValueRequirement>> _terminalOutputSpecifications; private final Map<ValueSpecification, Collection<ValueSpecification>> _marketDataAliases; private final Map<DistinctMarketDataSelector, Set<ValueSpecification>> _marketDataSelections; private final Map<DistinctMarketDataSelector, FunctionParameters> _marketDataSelectionFunctionParameters; /** * Constructs an instance * * @param name the name of the view calculation configuration, not null * @param computationTargets the computation targets, not null * @param terminalOutputSpecs the output specifications, not null * @param marketDataSpecs the market data specifications, not null */ public CompiledViewCalculationConfigurationImpl(String name, Set<ComputationTargetSpecification> computationTargets, Map<ValueSpecification, Set<ValueRequirement>> terminalOutputSpecs, Map<ValueSpecification, Collection<ValueSpecification>> marketDataSpecs) { this(name, computationTargets, terminalOutputSpecs, marketDataSpecs, Collections.<DistinctMarketDataSelector, Set<ValueSpecification>>emptyMap(), Collections.<DistinctMarketDataSelector, FunctionParameters>emptyMap()); } /** * Constructs an instance * * @param name the name of the view calculation configuration, not null * @param computationTargets the computation targets, not null * @param terminalOutputSpecifications the output specifications, not null * @param marketDataSpecifications the market data specifications, not null * @param marketDataSelections the market data selections that have been made to, not null * @param marketDataSelectionFunctionParameters the function parameters to be used for the market data selections, not null */ public CompiledViewCalculationConfigurationImpl( String name, Set<ComputationTargetSpecification> computationTargets, Map<ValueSpecification, Set<ValueRequirement>> terminalOutputSpecifications, Map<ValueSpecification, Collection<ValueSpecification>> marketDataSpecifications, Map<DistinctMarketDataSelector, Set<ValueSpecification>> marketDataSelections, Map<DistinctMarketDataSelector, FunctionParameters> marketDataSelectionFunctionParameters) { ArgumentChecker.notNull(name, "name"); ArgumentChecker.notNull(computationTargets, "computationTargets"); ArgumentChecker.notNull(terminalOutputSpecifications, "terminalOutputSpecifications"); ArgumentChecker.notNull(marketDataSpecifications, "marketDataSpecifications"); ArgumentChecker.notNull(marketDataSelections, "marketDataSelections"); ArgumentChecker.notNull(marketDataSelectionFunctionParameters, "marketDataSelectionFunctionParameters"); _name = name; _computationTargets = ImmutableSet.copyOf(computationTargets); _terminalOutputSpecifications = ImmutableMap.copyOf(terminalOutputSpecifications); _marketDataAliases = ImmutableMap.copyOf(marketDataSpecifications); _marketDataSelections = ImmutableMap.copyOf(marketDataSelections); _marketDataSelectionFunctionParameters = ImmutableMap.copyOf(marketDataSelectionFunctionParameters); } /** * Constructs an instance from a dependency graph * * @param dependencyGraph the dependency graph, not null * @return the new instance, not null */ public static CompiledViewCalculationConfigurationImpl of(final DependencyGraph dependencyGraph) { return of(dependencyGraph, Collections.<DistinctMarketDataSelector, Set<ValueSpecification>>emptyMap(), Collections.<DistinctMarketDataSelector, FunctionParameters>emptyMap()); } /** * Constructs an instance from a dependency graph with market data manipulation selections and function parameters * * @param graph the dependency graph, not null * @param marketDataSelections the market data selections that have been made to support manipulation of the structured market data, not null * @param marketDataSelectionFunctionParameters the function params to be used for the market data selections, not null * @return the new instance, not null */ public static CompiledViewCalculationConfigurationImpl of(final DependencyGraph graph, final Map<DistinctMarketDataSelector, Set<ValueSpecification>> marketDataSelections, final Map<DistinctMarketDataSelector, FunctionParameters> marketDataSelectionFunctionParameters) { ArgumentChecker.notNull(graph, "graph"); final Map<ValueSpecification, ?> terminals = graph.getTerminalOutputs(); final Set<ComputationTargetSpecification> targets = new HashSet<ComputationTargetSpecification>(); final Map<ValueSpecification, Collection<ValueSpecification>> marketData = new HashMap<ValueSpecification, Collection<ValueSpecification>>(); final Set<DependencyNode> visited = Sets.newHashSetWithExpectedSize(graph.getSize()); final int rootCount = graph.getRootCount(); for (int i = 0; i < rootCount; i++) { final DependencyNode root = graph.getRootNode(i); processNode(root, terminals, targets, marketData, visited); } return new CompiledViewCalculationConfigurationImpl(graph.getCalculationConfigurationName(), targets, graph.getTerminalOutputs(), marketData, marketDataSelections, marketDataSelectionFunctionParameters); } private static void processNode(final DependencyNode node, final Map<ValueSpecification, ?> terminals, final Set<ComputationTargetSpecification> targets, final Map<ValueSpecification, Collection<ValueSpecification>> marketData, final Set<DependencyNode> visited) { if (!visited.add(node)) { return; } targets.add(node.getTarget()); final int inputs = node.getInputCount(); if (inputs == 1) { if (MarketDataAliasingFunction.UNIQUE_ID.equals(node.getFunction().getFunctionId())) { final ValueSpecification marketDataSpec = node.getInputValue(0); Collection<ValueSpecification> aliases = marketData.get(marketDataSpec); final int outputs = node.getOutputCount(); if (aliases == null) { aliases = new ArrayList<ValueSpecification>(outputs); marketData.put(marketDataSpec, aliases); } for (int i = 0; i < outputs; i++) { aliases.add(node.getOutputValue(i)); } if (visited.add(node.getInputNode(0))) { if (terminals.containsKey(marketDataSpec)) { aliases.add(marketDataSpec); } } return; } } else if (inputs == 0) { if (MarketDataSourcingFunction.UNIQUE_ID.equals(node.getFunction().getFunctionId())) { final ValueSpecification marketDataSpec = node.getOutputValue(0); Collection<ValueSpecification> aliases = marketData.get(marketDataSpec); if (aliases == null) { aliases = new ArrayList<ValueSpecification>(1); marketData.put(marketDataSpec, aliases); } aliases.add(node.getOutputValue(0)); } return; } for (int i = 0; i < inputs; i++) { processNode(node.getInputNode(i), terminals, targets, marketData, visited); } } // CompiledViewCalculationConfiguration @Override public String getName() { return _name; } @Override public Map<ValueSpecification, Set<ValueRequirement>> getTerminalOutputSpecifications() { return Collections.unmodifiableMap(_terminalOutputSpecifications); } @Override public Set<Pair<String, ValueProperties>> getTerminalOutputValues() { final Set<Pair<String, ValueProperties>> valueNames = new HashSet<>(); for (final ValueSpecification spec : getTerminalOutputSpecifications().keySet()) { valueNames.add(Pairs.of(spec.getValueName(), spec.getProperties())); } return valueNames; } @Override public Map<DistinctMarketDataSelector, Set<ValueSpecification>> getMarketDataSelections() { return _marketDataSelections; } @Override public Map<DistinctMarketDataSelector, FunctionParameters> getMarketDataSelectionFunctionParameters() { return _marketDataSelectionFunctionParameters; } @Override public Set<ComputationTargetSpecification> getComputationTargets() { return _computationTargets; } @Override public Set<ValueSpecification> getMarketDataRequirements() { return getMarketDataAliases().keySet(); } @Override public Map<ValueSpecification, Collection<ValueSpecification>> getMarketDataAliases() { return _marketDataAliases; } // Object @Override public boolean equals(final Object o) { if (o == this) { return true; } if (!(o instanceof CompiledViewCalculationConfiguration)) { return false; } final CompiledViewCalculationConfiguration other = (CompiledViewCalculationConfiguration) o; return ObjectUtils.equals(getName(), other.getName()) && ObjectUtils.equals(getTerminalOutputSpecifications(), other.getTerminalOutputSpecifications()) && ObjectUtils.equals(getComputationTargets(), other.getComputationTargets()) && ObjectUtils.equals(getMarketDataRequirements(), other.getMarketDataRequirements()); } @Override public int hashCode() { int hc = ObjectUtils.hashCode(getName()); hc += (hc << 4) + ObjectUtils.hashCode(getTerminalOutputSpecifications()); hc += (hc << 4) + ObjectUtils.hashCode(getComputationTargets()); hc += (hc << 4) + ObjectUtils.hashCode(getMarketDataRequirements()); return hc; } }