/**
* Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.master.position.impl;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.Maps;
import com.opengamma.DataNotFoundException;
import com.opengamma.core.change.ChangeManager;
import com.opengamma.core.change.ChangeProvider;
import com.opengamma.core.change.DummyChangeManager;
import com.opengamma.core.change.PassthroughChangeManager;
import com.opengamma.core.position.Portfolio;
import com.opengamma.core.position.PortfolioNode;
import com.opengamma.core.position.Position;
import com.opengamma.core.position.PositionSource;
import com.opengamma.core.position.impl.SimplePortfolio;
import com.opengamma.core.position.impl.SimplePortfolioNode;
import com.opengamma.id.ObjectId;
import com.opengamma.id.UniqueId;
import com.opengamma.id.VersionCorrection;
import com.opengamma.master.portfolio.ManageablePortfolio;
import com.opengamma.master.portfolio.ManageablePortfolioNode;
import com.opengamma.master.portfolio.PortfolioMaster;
import com.opengamma.master.position.PositionSearchRequest;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.PublicSPI;
/**
* An abstract PositionSource built on top of an underlying master with possibly a PositionMaster and or PositionSource to
* resolve the positions in the portfolio.
*
*/
@PublicSPI
public abstract class AbstractMasterPositionSource implements PositionSource {
private static final Logger s_logger = LoggerFactory.getLogger(AbstractMasterPositionSource.class);
private final PortfolioMaster _portfolioMaster;
public AbstractMasterPositionSource(PortfolioMaster portfolioMaster) {
ArgumentChecker.notNull(portfolioMaster, "portfolioMaster");
_portfolioMaster = portfolioMaster;
}
/**
* Get collection of Position referenced in the Portfolio.
*
* @param positionSearch the positionSearch populated with positionIds referenced in the portfolio.
* @return the collection of positions referenced in the portfolio, not-null.
*/
protected abstract Collection<Position> positions(PositionSearchRequest positionSearch);
protected abstract ChangeProvider[] changeProviders();
@Override
public ChangeManager changeManager() {
ChangeProvider[] changeProviders = changeProviders();
if (changeProviders != null) {
return new PassthroughChangeManager(changeProviders());
} else {
return DummyChangeManager.INSTANCE;
}
}
@Override
public Portfolio getPortfolio(UniqueId uniqueId, VersionCorrection versionCorrection) {
ArgumentChecker.notNull(uniqueId, "uniqueId");
final ManageablePortfolio manPrt = getPortfolioMaster().get(uniqueId).getPortfolio();
final SimplePortfolio prt = new SimplePortfolio(manPrt.getUniqueId(), manPrt.getName());
convertNode(manPrt.getRootNode(), prt.getRootNode(), versionCorrection);
copyAttributes(manPrt, prt);
return prt;
}
/**
* Converts a manageable node to a source node.
*
* @param manNode the manageable node, not null
* @param sourceNode the source node, not null
* @param versionCorrection the version/correction time for resolving the constituent positions, not null
*/
protected void convertNode(final ManageablePortfolioNode manNode, final SimplePortfolioNode sourceNode, final VersionCorrection versionCorrection) {
final PositionSearchRequest positionSearch = new PositionSearchRequest();
final Map<ObjectId, Position> positionCache;
final int positionCount = populatePositionSearchRequest(positionSearch, manNode);
if (positionCount > 0) {
positionCache = Maps.newHashMapWithExpectedSize(positionCount);
positionSearch.setVersionCorrection(versionCorrection);
Collection<Position> positions = positions(positionSearch);
if (positions != null) {
for (Position position : positions) {
positionCache.put(position.getUniqueId().getObjectId(), position);
}
}
} else {
positionCache = null;
}
convertNode(manNode, sourceNode, positionCache);
}
private void copyAttributes(final ManageablePortfolio manPrt, final SimplePortfolio prt) {
if (manPrt.getAttributes() != null) {
for (final Entry<String, String> entry : manPrt.getAttributes().entrySet()) {
if (entry.getKey() != null && entry.getValue() != null) {
prt.addAttribute(entry.getKey(), entry.getValue());
}
}
}
}
private static int populatePositionSearchRequest(final PositionSearchRequest positionSearch, final ManageablePortfolioNode node) {
int count = 0;
for (final ObjectId positionId : node.getPositionIds()) {
positionSearch.addPositionObjectId(positionId);
count++;
}
for (final ManageablePortfolioNode child : node.getChildNodes()) {
count += populatePositionSearchRequest(positionSearch, child);
}
return count;
}
/**
* Converts a manageable node to a source node.
*
* @param manNode the manageable node, not null
* @param sourceNode the source node, not null
* @param positionCache the positions, not null
*/
protected void convertNode(final ManageablePortfolioNode manNode, final SimplePortfolioNode sourceNode, final Map<ObjectId, Position> positionCache) {
final UniqueId nodeId = manNode.getUniqueId();
sourceNode.setUniqueId(nodeId);
sourceNode.setName(manNode.getName());
sourceNode.setParentNodeId(manNode.getParentNodeId());
if (manNode.getPositionIds().size() > 0) {
for (final ObjectId positionId : manNode.getPositionIds()) {
final Position foundPosition = positionCache.get(positionId);
if (foundPosition != null) {
sourceNode.addPosition(foundPosition);
} else {
s_logger.warn("Position {} not found for portfolio node {}", positionId, nodeId);
}
}
}
for (final ManageablePortfolioNode child : manNode.getChildNodes()) {
final SimplePortfolioNode childNode = new SimplePortfolioNode();
convertNode(child, childNode, positionCache);
sourceNode.addChildNode(childNode);
}
}
@Override
public Portfolio getPortfolio(ObjectId objectId, VersionCorrection versionCorrection) {
ArgumentChecker.notNull(objectId, "objectId");
ArgumentChecker.notNull(versionCorrection, "versionCorrection");
final ManageablePortfolio manPrt = getPortfolioMaster().get(objectId, versionCorrection).getPortfolio();
final SimplePortfolio prt = new SimplePortfolio(manPrt.getUniqueId(), manPrt.getName());
convertNode(manPrt.getRootNode(), prt.getRootNode(), versionCorrection);
copyAttributes(manPrt, prt);
return prt;
}
@Override
public PortfolioNode getPortfolioNode(UniqueId uniqueId, VersionCorrection versionCorrection) {
ArgumentChecker.notNull(uniqueId, "uniqueId");
final ManageablePortfolioNode manNode = getPortfolioMaster().getNode(uniqueId);
if (manNode == null) {
throw new DataNotFoundException("Unable to find node: " + uniqueId);
}
final SimplePortfolioNode node = new SimplePortfolioNode();
convertNode(manNode, node, versionCorrection);
return node;
}
/**
* Gets the portfolioMaster.
* @return the portfolioMaster
*/
public PortfolioMaster getPortfolioMaster() {
return _portfolioMaster;
}
}