/** * Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.engine.depgraph.builder; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import com.opengamma.engine.ComputationTargetSpecification; import com.opengamma.engine.depgraph.DependencyGraph; import com.opengamma.engine.depgraph.DependencyNode; import com.opengamma.engine.depgraph.DependencyNodeFunction; import com.opengamma.engine.depgraph.impl.DependencyGraphImpl; import com.opengamma.engine.depgraph.impl.DependencyNodeFunctionImpl; import com.opengamma.engine.depgraph.impl.DependencyNodeImpl; import com.opengamma.engine.function.EmptyFunctionParameters; import com.opengamma.engine.function.FunctionDefinition; import com.opengamma.engine.test.MockFunction; import com.opengamma.engine.value.ValueProperties; import com.opengamma.engine.value.ValuePropertyNames; import com.opengamma.engine.value.ValueRequirement; import com.opengamma.engine.value.ValueSpecification; /** * Trivial dependency graph builder for use in test cases. */ public class TestDependencyGraphBuilder { /** * Represents a partially built node. */ public final class NodeBuilder { private final DependencyNodeFunction _function; private final ComputationTargetSpecification _target; private final Set<ValueSpecification> _inputs = new HashSet<ValueSpecification>(); private final Set<ValueSpecification> _outputs = new HashSet<ValueSpecification>(); private NodeBuilder(final DependencyNodeFunction function, final ComputationTargetSpecification target) { _function = function; _target = target; } public void addInput(final ValueSpecification value) { _inputs.add(value); } private ValueSpecification createOutput(final String name) { return new ValueSpecification(name, _target, ValueProperties.with(ValuePropertyNames.FUNCTION, _function.getFunctionId()).get()); } public ValueSpecification addOutput(final String name) { final ValueSpecification output = createOutput(name); addOutput(output); return output; } public void addOutput(final ValueSpecification value) { assert _target.equals(value.getTargetSpecification()); _outputs.add(value); } public ValueSpecification addTerminalOutput(final String name) { final ValueSpecification output = createOutput(name); final ValueRequirement requirement = new ValueRequirement(name, output.getTargetSpecification(), output.getProperties().withoutAny(ValuePropertyNames.FUNCTION)); addTerminalOutput(output, requirement); return output; } public void addTerminalOutput(final ValueSpecification value, final ValueRequirement requirement) { addOutput(value); _terminals.put(value, Collections.singleton(requirement)); } } private final String _calcConfig; private final List<NodeBuilder> _nodes = new ArrayList<NodeBuilder>(); private final Map<ValueSpecification, Set<ValueRequirement>> _terminals = new HashMap<ValueSpecification, Set<ValueRequirement>>(); public TestDependencyGraphBuilder(final String calcConfig) { _calcConfig = calcConfig; } public NodeBuilder getNode(final int index) { return _nodes.get(index); } public NodeBuilder addNode(final DependencyNodeFunction function, final ComputationTargetSpecification target) { final NodeBuilder n = new NodeBuilder(function, target); _nodes.add(n); return n; } public NodeBuilder addNode(final String function, final ComputationTargetSpecification target) { return addNode(DependencyNodeFunctionImpl.of(function, EmptyFunctionParameters.INSTANCE), target); } public NodeBuilder addNode(final FunctionDefinition function, final ComputationTargetSpecification target) { return addNode(DependencyNodeFunctionImpl.of(function.getUniqueId(), function.getDefaultParameters()), target); } public NodeBuilder addNode(final MockFunction function) { return addNode(function, function.getTarget().toSpecification()); } public void addTerminalOutput(final ValueSpecification valueSpecification, final Set<ValueRequirement> valueRequirements) { _terminals.put(valueSpecification, valueRequirements); } private DependencyNode buildNode(final ValueSpecification valueSpec, final Map<ValueSpecification, NodeBuilder> builders, final Map<ValueSpecification, DependencyNode> nodes) { DependencyNode node = nodes.get(valueSpec); if (node == null) { final NodeBuilder builder = builders.get(valueSpec); if (builder == null) { throw new IllegalArgumentException(); } node = buildNode(builder, builders, nodes); for (ValueSpecification output : builder._outputs) { nodes.put(output, node); } } return node; } private DependencyNode buildNode(final NodeBuilder builder, final Map<ValueSpecification, NodeBuilder> builders, final Map<ValueSpecification, DependencyNode> nodes) { final Map<ValueSpecification, DependencyNode> inputs = new HashMap<ValueSpecification, DependencyNode>(); for (ValueSpecification input : builder._inputs) { inputs.put(input, buildNode(input, builders, nodes)); } return new DependencyNodeImpl(builder._function, builder._target, builder._outputs, inputs); } public DependencyGraph buildGraph() { final Map<ValueSpecification, NodeBuilder> nodeBuilders = new HashMap<ValueSpecification, NodeBuilder>(); final Map<ValueSpecification, DependencyNode> nodes = new HashMap<ValueSpecification, DependencyNode>(); final Set<ValueSpecification> intermediates = new HashSet<ValueSpecification>(); for (NodeBuilder node : _nodes) { for (ValueSpecification output : node._outputs) { nodeBuilders.put(output, node); } intermediates.addAll(node._inputs); } final Collection<DependencyNode> roots = new ArrayList<DependencyNode>(); nodeLoop: for (NodeBuilder node : _nodes) { //CSIGNORE for (ValueSpecification output : node._outputs) { if (intermediates.contains(output)) { continue nodeLoop; } } roots.add(buildNode(node, nodeBuilders, nodes)); } return new DependencyGraphImpl(_calcConfig, roots, _nodes.size(), _terminals); } }