/**
* Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.integration.tool.cli;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.threeten.bp.LocalDate;
import org.threeten.bp.format.DateTimeFormatter;
import com.google.common.collect.Iterables;
import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.engine.marketdata.spec.FixedHistoricalMarketDataSpecification;
import com.opengamma.engine.marketdata.spec.LatestHistoricalMarketDataSpecification;
import com.opengamma.engine.marketdata.spec.LiveMarketDataSpecification;
import com.opengamma.engine.marketdata.spec.MarketData;
import com.opengamma.engine.marketdata.spec.MarketDataSpecification;
import com.opengamma.engine.marketdata.spec.UserMarketDataSpecification;
import com.opengamma.id.UniqueId;
import com.opengamma.master.marketdatasnapshot.MarketDataSnapshotDocument;
import com.opengamma.master.marketdatasnapshot.MarketDataSnapshotMaster;
import com.opengamma.master.marketdatasnapshot.MarketDataSnapshotSearchRequest;
import com.opengamma.master.marketdatasnapshot.MarketDataSnapshotSearchResult;
import com.opengamma.util.ArgumentChecker;
/**
* Market Data Source command line interface
* <pre>
* There are 3 supported types, live, historical and snapshot.
* input formats are
* live:dataSourceName dataSourceName is option, if missing MarketData.live() is used
* historical:resolverkey:date optional resolverkey and date(format is yyyymmdd), if missing LatestHistoricalMarketDataSpecification is used
* snapshot:snapshotName
* </pre>
* <p>
* Order is based on order of options from the command line e.g --dataSource live --dataSource snapshot:test --dataSource historical
* will build a layered data source of
* <p>
* marketdata live then user snapshot with name = test and then latest historical
*/
public class MarketDataSourceCli {
private static final Logger s_logger = LoggerFactory.getLogger(MarketDataSourceCli.class);
/** Market data source option */
private static final String MARKET_DATA_SOURCE_OPTION = "dataSource";
private static final Pattern s_dsOptionPattern = Pattern.compile("(live|historical|snapshot)(:(.*))?");
private static final Pattern s_historicalPattern = Pattern.compile("([^:]+)((:)([0-9]{8}))?");
/**
* Market data source command line option definition
*/
private final Option _option;
public MarketDataSourceCli() {
final Option option = new Option("ds", MARKET_DATA_SOURCE_OPTION, true, "the market data source name " +
"format is \nlive:<dataSourceName> or \nhistorical:<resolverkey>~<date> date in yyyymmdd or \nsnapshot:snapshotName");
option.setArgName("data source");
_option = option;
}
/**
* Gets the option.
* @return the option
*/
public Option getOption() {
return _option;
}
public List<MarketDataSpecification> getMarketDataSpecs(final CommandLine commandLine, final MarketDataSnapshotMaster mktDataSnapshotMaster) {
ArgumentChecker.notNull(commandLine, "commandLine");
ArgumentChecker.notNull(mktDataSnapshotMaster, "mktDataSnapshotMaster");
List<MarketDataSpecification> marketDataSpecs = new ArrayList<>();
String[] optionValues = commandLine.getOptionValues(MARKET_DATA_SOURCE_OPTION);
if (optionValues == null) {
s_logger.info("Missing {} option from command line", MARKET_DATA_SOURCE_OPTION);
return marketDataSpecs;
}
for (String optionValue : optionValues) {
optionValue = StringUtils.trimToNull(optionValue);
if (optionValue == null) {
throw new OpenGammaRuntimeException("Empty market data source option not allowed");
}
Matcher optionMatcher = s_dsOptionPattern.matcher(optionValue);
if (!optionMatcher.matches()) {
throw new OpenGammaRuntimeException(String.format("Invalid data source option value [%s] in command line option", optionValue));
}
String type = optionMatcher.group(1);
String dataSourceStr = StringUtils.trimToNull(optionMatcher.group(2));
switch (type) {
case "live":
if (dataSourceStr == null) {
marketDataSpecs.add(MarketData.live());
} else {
marketDataSpecs.add(LiveMarketDataSpecification.of(optionMatcher.group(3)));
}
break;
case "historical":
if (dataSourceStr == null) {
marketDataSpecs.add(new LatestHistoricalMarketDataSpecification());
} else {
Matcher historicalMatcher = s_historicalPattern.matcher(optionMatcher.group(3));
if (!historicalMatcher.matches()) {
throw new OpenGammaRuntimeException(String.format("Invalid historical data source option value [%s] in command line option", optionValue));
}
String resolverKey = historicalMatcher.group(1);
if (StringUtils.trimToNull(historicalMatcher.group(2)) == null) {
marketDataSpecs.add(new LatestHistoricalMarketDataSpecification(resolverKey));
} else {
String dateStr = StringUtils.trimToNull(historicalMatcher.group(4));
LocalDate snapshotDate = LocalDate.parse(dateStr, DateTimeFormatter.ofPattern("yyyyMMdd"));
marketDataSpecs.add(new FixedHistoricalMarketDataSpecification(resolverKey, snapshotDate));
}
}
break;
case "snapshot":
if (dataSourceStr == null || StringUtils.trimToNull(optionMatcher.group(3)) == null) {
throw new OpenGammaRuntimeException(String.format("Invalid historical data source option value [%s] in command line option", optionValue));
}
String snapshotName = optionMatcher.group(3);
UniqueId uniqueId = getSnapshotUniqueId(snapshotName, mktDataSnapshotMaster);
if (uniqueId == null) {
s_logger.warn("Snapshot with name {} can not be found", snapshotName);
} else {
marketDataSpecs.add(UserMarketDataSpecification.of(uniqueId));
}
break;
default:
throw new OpenGammaRuntimeException(String.format("Unsupported market data source type [%s] in command line option", type));
}
}
return marketDataSpecs;
}
private UniqueId getSnapshotUniqueId(String snapshotName, MarketDataSnapshotMaster mktDataSnapshotMaster) {
MarketDataSnapshotSearchRequest request = new MarketDataSnapshotSearchRequest();
request.setName(snapshotName);
MarketDataSnapshotSearchResult snapshotSearchResult = mktDataSnapshotMaster.search(request);
MarketDataSnapshotDocument snapshotDoc = Iterables.getFirst(snapshotSearchResult.getDocuments(), null);
if (snapshotDoc != null) {
return snapshotDoc.getUniqueId();
}
return null;
}
}