/**
* Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.engine.view.helper;
import java.util.List;
import org.threeten.bp.Instant;
import com.opengamma.DataNotFoundException;
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.core.security.SecuritySource;
import com.opengamma.engine.function.CompiledFunctionRepository;
import com.opengamma.engine.function.CompiledFunctionService;
import com.opengamma.engine.function.exclusion.FunctionExclusionGroups;
import com.opengamma.engine.marketdata.availability.MarketDataAvailabilityFilter;
import com.opengamma.engine.marketdata.availability.OptimisticMarketDataAvailabilityFilter;
import com.opengamma.engine.view.compilation.PortfolioCompiler;
import com.opengamma.id.UniqueId;
import com.opengamma.id.VersionCorrection;
import com.opengamma.util.ArgumentChecker;
/**
* Default implementation of {@code AvailableOutputsProvider} against a local function repository.
*/
public class DefaultAvailableOutputsProvider implements AvailableOutputsProvider {
private final CompiledFunctionService _compiledFunctions;
private final FunctionExclusionGroups _functionExclusionGroups;
private final PositionSource _positionSource;
private final SecuritySource _securitySource;
private final MarketDataAvailabilityFilter _marketDataAvailability;
private final String _wildcardIndicator;
public DefaultAvailableOutputsProvider(final CompiledFunctionService compiledFunctionService, final FunctionExclusionGroups functionExclusionGroups, final PositionSource positionSource,
final SecuritySource securitySource, final String wildcardIndicator) {
this(compiledFunctionService, functionExclusionGroups, new OptimisticMarketDataAvailabilityFilter(), positionSource, securitySource, wildcardIndicator);
}
public DefaultAvailableOutputsProvider(final CompiledFunctionService compiledFunctionService, final FunctionExclusionGroups functionExclusionGroups,
final MarketDataAvailabilityFilter marketDataAvailability, final PositionSource positionSource, final SecuritySource securitySource, final String wildcardIndicator) {
ArgumentChecker.notNull(compiledFunctionService, "compiledFunctionService");
ArgumentChecker.notNull(marketDataAvailability, "marketDataAvailability");
ArgumentChecker.notNull(positionSource, "positionSource");
ArgumentChecker.notNull(securitySource, "securitySource");
_compiledFunctions = compiledFunctionService;
_functionExclusionGroups = functionExclusionGroups;
_marketDataAvailability = marketDataAvailability;
_positionSource = positionSource;
_securitySource = securitySource;
_wildcardIndicator = wildcardIndicator;
}
//------------------------------------------------------------------------
@Override
public AvailableOutputs getPortfolioOutputs(final Portfolio portfolio, final Instant instant) {
return getPortfolioOutputs(portfolio, instant, null, null);
}
@Override
public AvailableOutputs getPortfolioOutputs(Portfolio portfolio, final Instant instant, final Integer maxNodes, final Integer maxPositions) {
portfolio = preparePortfolio(portfolio, maxNodes, maxPositions);
final Instant compileInstant = (instant != null ? instant : Instant.now());
final CompiledFunctionRepository functionRepository = getCompiledFunctionService().compileFunctionRepository(compileInstant);
return new AvailablePortfolioOutputs(portfolio, functionRepository, getFunctionExclusionGroups(), getMarketDataAvailability(), getWildcardIndicator());
}
@Override
public AvailableOutputs getPortfolioOutputs(final UniqueId portfolioId, final Instant instant) {
return getPortfolioOutputs(portfolioId, instant, null, null);
}
@Override
public AvailableOutputs getPortfolioOutputs(final UniqueId portfolioId, final Instant instant, final Integer maxNodes, final Integer maxPositions) {
Portfolio portfolio = getPortfolio(portfolioId);
portfolio = preparePortfolio(portfolio, maxNodes, maxPositions);
final Instant compileInstant = (instant != null ? instant : Instant.now());
final CompiledFunctionRepository functionRepository = getCompiledFunctionService().compileFunctionRepository(compileInstant);
return new AvailablePortfolioOutputs(portfolio, functionRepository, getFunctionExclusionGroups(), getMarketDataAvailability(), getWildcardIndicator());
}
//------------------------------------------------------------------------
private CompiledFunctionService getCompiledFunctionService() {
return _compiledFunctions;
}
private FunctionExclusionGroups getFunctionExclusionGroups() {
return _functionExclusionGroups;
}
private PositionSource getPositionSource() {
return _positionSource;
}
private SecuritySource getSecuritySource() {
return _securitySource;
}
private MarketDataAvailabilityFilter getMarketDataAvailability() {
return _marketDataAvailability;
}
private String getWildcardIndicator() {
return _wildcardIndicator;
}
//------------------------------------------------------------------------
private static SimplePortfolioNode copyNode(final PortfolioNode node, final Integer maxNodes, final Integer maxPositions) {
final SimplePortfolioNode copy = new SimplePortfolioNode(node.getUniqueId(), node.getName());
if (maxNodes != null && maxNodes > 0) {
final List<PortfolioNode> childNodes = node.getChildNodes();
int size = childNodes.size();
if (size > 0) {
if (size > maxNodes) {
size = maxNodes;
}
for (int i = 0; i < size; i++) {
copy.addChildNode(copyNode(childNodes.get(i), maxNodes, maxPositions));
}
}
} else if (maxNodes == null) {
for (final PortfolioNode child : node.getChildNodes()) {
copy.addChildNode(copyNode(child, maxNodes, maxPositions));
}
}
if (maxPositions != null && maxPositions > 0) {
final List<Position> positions = node.getPositions();
int size = positions.size();
if (size > 0) {
if (size > maxPositions) {
size = maxPositions;
}
for (int i = 0; i < size; i++) {
copy.addPosition(positions.get(i));
}
}
} else if (maxPositions == null) {
copy.addPositions(node.getPositions());
}
return copy;
}
/**
* Fetches a portfolio by its unique identifier.
*
* @param portfolioId the unique identifier of the portfolio, not null
* @return the portfolio, not null
* @throws DataNotFoundException if the portfolio identifier is invalid or cannot be resolved to a portfolio
*/
protected Portfolio getPortfolio(final UniqueId portfolioId) {
ArgumentChecker.notNull(portfolioId, "portfolioId");
return getPositionSource().getPortfolio(portfolioId, VersionCorrection.LATEST);
}
/**
* Prepares the portfolio, truncating the number of sub-nodes and positions if required and resolving its securities.
*
* @param portfolio the portfolio, not null
* @param maxNodes the maximum number of child nodes under each node, null for unlimited
* @param maxPositions the maximum number of positions, null for unlimited
* @return the resolved portfolio, truncated as requested
*/
protected Portfolio preparePortfolio(Portfolio portfolio, final Integer maxNodes, final Integer maxPositions) {
ArgumentChecker.notNull(portfolio, "portfolio");
if (maxNodes != null) {
ArgumentChecker.notNegative(maxNodes, "maxNodes");
}
if (maxPositions != null) {
ArgumentChecker.notNegative(maxPositions, "maxPositions");
}
if ((maxNodes != null) || (maxPositions != null)) {
final SimplePortfolio copy = new SimplePortfolio(portfolio.getName());
copy.setRootNode(copyNode(portfolio.getRootNode(), maxNodes, maxPositions));
portfolio = copy;
}
return PortfolioCompiler.resolvePortfolio(portfolio, getCompiledFunctionService().getExecutorService().asService(), getSecuritySource());
}
}