/**
* Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.integration.viewer.status.impl;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.SetMultimap;
import com.google.common.collect.Sets;
import com.google.common.collect.TreeMultimap;
import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.engine.marketdata.spec.MarketDataSpecification;
import com.opengamma.engine.view.helper.AvailableOutput;
import com.opengamma.engine.view.helper.AvailableOutputs;
import com.opengamma.engine.view.helper.AvailableOutputsProvider;
import com.opengamma.financial.tool.ToolContext;
import com.opengamma.id.UniqueId;
import com.opengamma.integration.viewer.status.ViewStatusKey;
import com.opengamma.integration.viewer.status.ViewStatusOption;
import com.opengamma.integration.viewer.status.ViewStatusResultAggregator;
import com.opengamma.livedata.UserPrincipal;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.NamedThreadPoolFactory;
/**
* Executes the View status calculation task with the default Executor service
*/
public class ViewStatusCalculationWorker {
private static final Logger s_logger = LoggerFactory.getLogger(ViewStatusCalculationWorker.class);
private static final ExecutorService DEFAULT_EXECUTOR = NamedThreadPoolFactory.newCachedThreadPool("ViewStatus");
private final ExecutorService _executor;
private final Map<String, Collection<String>> _valueRequirementBySecType;
private final ToolContext _toolContext;
private final UniqueId _portfolioId;
private final UserPrincipal _user;
private final MarketDataSpecification _marketDataSpecification;
public ViewStatusCalculationWorker(final ToolContext toolContext, final UniqueId portfolioId, final ViewStatusOption option) {
this(toolContext, portfolioId, option, DEFAULT_EXECUTOR);
}
public ViewStatusCalculationWorker(final ToolContext toolContext, UniqueId portfolioId, final ViewStatusOption option, final ExecutorService executorService) {
ArgumentChecker.notNull(toolContext, "toolContex");
ArgumentChecker.notNull(portfolioId, "portfolioId");
ArgumentChecker.notNull(option, "option");
ArgumentChecker.notNull(option.getUser(), "option.user");
ArgumentChecker.notNull(option.getMarketDataSpecification(), "option.marketDataSpecification");
ArgumentChecker.notNull(executorService, "executorService");
validateComponentsInToolContext(toolContext);
_portfolioId = portfolioId;
_user = option.getUser();
_marketDataSpecification = option.getMarketDataSpecification();
Map<String, Collection<String>> valueRequirementBySecType = scanValueRequirementBySecType(portfolioId, toolContext);
if (s_logger.isDebugEnabled()) {
StringBuilder strBuf = new StringBuilder();
for (String securityType : Sets.newTreeSet(valueRequirementBySecType.keySet())) {
Set<String> valueNames = Sets.newTreeSet(valueRequirementBySecType.get(securityType));
strBuf.append(String.format("%s\t%s\n", StringUtils.rightPad(securityType, 40), valueNames.toString()));
}
s_logger.debug("\n{}\n", strBuf.toString());
}
_toolContext = toolContext;
_executor = executorService;
_valueRequirementBySecType = valueRequirementBySecType;
}
private void validateComponentsInToolContext(ToolContext toolContext) {
if (toolContext.getViewProcessor() == null) {
throw new OpenGammaRuntimeException("Missing view processor in given toolcontext");
}
if (toolContext.getSecuritySource() == null) {
throw new OpenGammaRuntimeException("Missing security source in given toolcontext");
}
if (toolContext.getConfigMaster() == null) {
throw new OpenGammaRuntimeException("Missing config master in given toolcontext");
}
if (toolContext.getPositionSource() == null) {
throw new OpenGammaRuntimeException("Missing position source in given toolcontext");
}
}
private Map<String, Collection<String>> scanValueRequirementBySecType(UniqueId portfolioId, ToolContext toolContext) {
AvailableOutputsProvider availableOutputsProvider = toolContext.getAvaliableOutputsProvider();
if (availableOutputsProvider == null) {
throw new OpenGammaRuntimeException("AvailableOutputsProvider missing from ToolContext");
}
final SetMultimap<String, String> valueNamesBySecurityType = TreeMultimap.create();
AvailableOutputs portfolioOutputs = availableOutputsProvider.getPortfolioOutputs(portfolioId, null);
Set<String> securityTypes = portfolioOutputs.getSecurityTypes();
for (String securityType : securityTypes) {
Set<AvailableOutput> positionOutputs = portfolioOutputs.getPositionOutputs(securityType);
for (AvailableOutput availableOutput : positionOutputs) {
valueNamesBySecurityType.put(securityType, availableOutput.getValueName());
}
}
return valueNamesBySecurityType.asMap();
}
public ViewStatusResultAggregator run() {
ViewStatusResultAggregator aggregator = new ViewStatusResultAggregatorImpl();
CompletionService<PerViewStatusResult> completionService = new ExecutorCompletionService<PerViewStatusResult>(_executor);
//submit task to executor to run partitioned by security type
for (String securityType : _valueRequirementBySecType.keySet()) {
Collection<String> valueRequirements = _valueRequirementBySecType.get(securityType);
completionService.submit(new ViewStatusCalculationTask(_toolContext, _portfolioId, _user, securityType, valueRequirements, _marketDataSpecification));
}
try {
// process all completed task
for (int i = 0; i < _valueRequirementBySecType.size(); i++) {
Future<PerViewStatusResult> futureTask = completionService.take();
PerViewStatusResult perViewStatusResult = futureTask.get();
for (ViewStatusKey viewStatusKey : perViewStatusResult.keySet()) {
aggregator.putStatus(viewStatusKey, perViewStatusResult.get(viewStatusKey));
}
}
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
} catch (ExecutionException ex) {
throw new OpenGammaRuntimeException("Error running View status report", ex.getCause());
}
return aggregator;
}
}