/** * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.engine.function; import com.opengamma.core.position.PortfolioNode; import com.opengamma.core.position.PositionSource; import com.opengamma.core.position.impl.PositionAccumulator; import com.opengamma.engine.ComputationTarget; import com.opengamma.engine.target.ComputationTargetType; import com.opengamma.id.UniqueId; import com.opengamma.id.VersionCorrection; import com.opengamma.util.ArgumentChecker; import com.opengamma.util.PublicAPI; /** * Service to interrogate the portfolio structure. * <p> * The {@link PortfolioNode} object only contains the unique identifier of its parent nodes, requiring additional resolution steps and queries to a {@link PositionSource}. This is exposed to functions * as part of the {@link FunctionExecutionContext} to allow such queries. At function execution, all child nodes, positions, trades and referenced securities will be resolved and can be queried * directly from the node object or using utility methods from {@link PositionAccumulator}. */ @PublicAPI public class PortfolioStructure { /** * The portfolio source. */ private final PositionSource _positionSource; /** * Constructs a portfolio structure querying service using the underlying position source for portfolio information. * * @param positionSource the underlying position source, not null */ public PortfolioStructure(final PositionSource positionSource) { ArgumentChecker.notNull(positionSource, "positionSource"); _positionSource = positionSource; } /** * Returns the position source used by the querying service. * * @return the position source */ public PositionSource getPositionSource() { return _positionSource; } //------------------------------------------------------------------------- /** * Returns the portfolio node that is the immediate parent of the given node. This is equivalent to resolving the unique identifier reported by a portfolio node as its parent. * * @param node the node to search for, not null * @return the parent node, null if the parent cannot be resolved or the node is a root node */ public PortfolioNode getParentNode(final PortfolioNode node) { ArgumentChecker.notNull(node, "node"); return getParentNodeImpl(node); } private PortfolioNode getParentNodeImpl(final PortfolioNode node) { final UniqueId parent = node.getParentNodeId(); if (parent == null) { return null; } return getPositionSource().getPortfolioNode(parent, VersionCorrection.LATEST); } /** * Returns the portfolio node that a position is underneath. The position must be in a {@link ComputationTarget} of type {@code PORTFOLIO_NODE/POSITION}. * * @param position the position to search for, not null * @return the portfolio node, null if the node cannot be resolved */ public PortfolioNode getParentNode(final ComputationTarget position) { ArgumentChecker.notNull(position, "position"); ArgumentChecker.isTrue(ComputationTargetType.PORTFOLIO_NODE.containing(ComputationTargetType.POSITION).isCompatible(position.getType()), "position"); return getPositionSource().getPortfolioNode(position.getContextSpecification().getSpecification().getUniqueId(), VersionCorrection.LATEST); } /** * Returns the root node for the portfolio containing the given node. This is equivalent to traversing up the tree until the root is found. * * @param node the node to search for, not null * @return the root node, null if parent node hierarchy incomplete * @deprecated This is broken as it assumes the "latest" version of the node returned */ @Deprecated public PortfolioNode getRootPortfolioNode(final PortfolioNode node) { ArgumentChecker.notNull(node, "node"); return getRootPortfolioNodeImpl(node); } /** * Returns the root node for the portfolio containing the given position. The position must be in a {@link ComputationTarget} of type {@code PORTFOLIO_NODE/POSITION}. This is equivalent to * traversing up the tree from the position's portfolio node until the root is found. * * @param position the position to search for, not null * @return the root node, null if parent node hierarchy incomplete * @deprecated This is broken as it assumes the "latest" version of the node returned */ @Deprecated public PortfolioNode getRootPortfolioNode(final ComputationTarget position) { final PortfolioNode node = getParentNode(position); if (node == null) { return null; } return getRootPortfolioNodeImpl(node); } /** * @deprecated This is broken as it assumes the "latest" version of the node returned */ @Deprecated private PortfolioNode getRootPortfolioNodeImpl(PortfolioNode node) { UniqueId parent = node.getParentNodeId(); while (parent != null) { node = getPositionSource().getPortfolioNode(parent, VersionCorrection.LATEST); if (node == null) { // Position source is broken return null; } parent = node.getParentNodeId(); } return node; } }