/**
* Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.integration.tool.marketdata;
import static java.lang.String.format;
import static org.threeten.bp.temporal.ChronoUnit.SECONDS;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionGroup;
import org.apache.commons.cli.Options;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.threeten.bp.Instant;
import org.threeten.bp.LocalTime;
import org.threeten.bp.ZonedDateTime;
import org.threeten.bp.format.DateTimeFormatter;
import com.opengamma.component.tool.AbstractTool;
import com.opengamma.engine.marketdata.snapshot.MarketDataSnapshotter;
import com.opengamma.engine.marketdata.snapshot.MarketDataSnapshotter.Mode;
import com.opengamma.engine.marketdata.spec.LatestHistoricalMarketDataSpecification;
import com.opengamma.engine.marketdata.spec.MarketDataSpecification;
import com.opengamma.financial.tool.ToolContext;
import com.opengamma.financial.tool.marketdata.MarketDataSnapshotSaver;
import com.opengamma.financial.view.rest.RemoteViewProcessor;
import com.opengamma.id.UniqueId;
import com.opengamma.integration.tool.cli.MarketDataSourceCli;
import com.opengamma.master.marketdatasnapshot.MarketDataSnapshotMaster;
import com.opengamma.scripts.Scriptable;
/**
* The entry point for running OpenGamma batches.
*/
@Scriptable
public class MarketDataSnapshotTool extends AbstractTool<ToolContext> {
/** Logger. */
private static final Logger s_logger = LoggerFactory.getLogger(MarketDataSnapshotTool.class);
/** Snapshot name command line option. */
private static final String SNAPSHOT_NAME_OPTION = "s";
/** View name command line option. */
private static final String VIEW_NAME_OPTION = "v";
/** Existing view process unique identifier option. */
private static final String VIEW_PROCESS_ID_OPTION = "p";
/** Snapshotter timeout option when awaiting market data. */
private static final String TIMEOUT_OPTION = "o";
/** Valuation time command line option. */
private static final String VALUATION_TIME_OPTION = "t";
/** Take data from historical timeseries */
private static final String HISTORICAL_OPTION = "historical";
/** Take an unstructured only snapshot */
private static final String UNSTRUCTURED_OPTION = "u";
/** Time format: yyyyMMdd */
private static final DateTimeFormatter VALUATION_TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss");
private static ToolContext s_context;
private static MarketDataSourceCli s_mktDataSourceCli = new MarketDataSourceCli();
//-------------------------------------------------------------------------
/**
* Main method to run the tool.
*
* @param args the standard tool arguments, not null
*/
public static void main(final String[] args) { // CSIGNORE
new MarketDataSnapshotTool().invokeAndTerminate(args);
}
//-------------------------------------------------------------------------
@Override
protected void doRun() throws Exception {
s_context = getToolContext();
final RemoteViewProcessor viewProcessor = (RemoteViewProcessor) s_context.getViewProcessor();
if (viewProcessor == null) {
s_logger.warn("No view processors found at {}", s_context);
return;
}
final MarketDataSnapshotMaster marketDataSnapshotMaster = s_context.getMarketDataSnapshotMaster();
if (marketDataSnapshotMaster == null) {
s_logger.warn("No market data snapshot masters found at {}", s_context);
return;
}
final MarketDataSnapshotter marketDataSnapshotter;
if (getCommandLine().hasOption(UNSTRUCTURED_OPTION)) {
marketDataSnapshotter = viewProcessor.getMarketDataSnapshotter(Mode.UNSTRUCTURED);
} else {
marketDataSnapshotter = viewProcessor.getMarketDataSnapshotter(Mode.STRUCTURED);
}
Long marketDataTimeoutSeconds = getCommandLine().hasOption(TIMEOUT_OPTION) ? Long.parseLong(getCommandLine().getOptionValue(TIMEOUT_OPTION)) : null;
Long marketDataTimeoutMillis = marketDataTimeoutSeconds != null ? TimeUnit.SECONDS.toMillis(marketDataTimeoutSeconds) : null;
final MarketDataSnapshotSaver snapshotSaver = MarketDataSnapshotSaver.of(marketDataSnapshotter, viewProcessor, s_context.getConfigMaster(), marketDataSnapshotMaster, marketDataTimeoutMillis);
if (getCommandLine().hasOption(VIEW_PROCESS_ID_OPTION)) {
final UniqueId viewProcessId = UniqueId.parse(getCommandLine().getOptionValue(VIEW_PROCESS_ID_OPTION));
s_logger.info("Creating snapshot from existing view process " + viewProcessId);
try {
snapshotSaver.createSnapshot(null, viewProcessId);
} catch (Exception e) {
endWithError(e.getMessage());
}
} else {
final String viewDefinitionName = StringUtils.trimToNull(getCommandLine().getOptionValue(VIEW_NAME_OPTION));
if (viewDefinitionName == null) {
s_logger.warn("Given view definition name is blank");
return;
}
final String valuationTimeArg = StringUtils.trimToNull(getCommandLine().getOptionValue(VALUATION_TIME_OPTION));
Instant valuationInstant;
if (valuationTimeArg != null) {
final LocalTime valuationTime = LocalTime.parse(valuationTimeArg, VALUATION_TIME_FORMATTER);
valuationInstant = ZonedDateTime.now().with(valuationTime.truncatedTo(SECONDS)).toInstant();
} else {
valuationInstant = Instant.now();
}
List<MarketDataSpecification> marketDataSpecs = new ArrayList<>();
if (getCommandLine().hasOption(HISTORICAL_OPTION)) {
marketDataSpecs.add(new LatestHistoricalMarketDataSpecification());
} else {
marketDataSpecs.addAll(getMarketDataSpecs());
}
s_logger.info("Creating snapshot for view definition " + viewDefinitionName);
try {
String snapshotName = StringUtils.trimToNull(getCommandLine().getOptionValue(SNAPSHOT_NAME_OPTION));
if (snapshotName == null) {
s_logger.warn("Given snapshot name is blank, using {}/{}", viewDefinitionName, valuationInstant);
snapshotName = viewDefinitionName + "/" + valuationInstant;
}
snapshotSaver.createSnapshot(snapshotName, viewDefinitionName, valuationInstant, marketDataSpecs);
} catch (Exception e) {
endWithError(e.getMessage());
}
}
}
private List<MarketDataSpecification> getMarketDataSpecs() {
return s_mktDataSourceCli.getMarketDataSpecs(getCommandLine(), s_context.getMarketDataSnapshotMaster());
}
private void endWithError(String message, Object... messageArgs) {
String formattedMessage = format(message, messageArgs);
System.err.println(formattedMessage);
s_logger.error(formattedMessage);
System.exit(1);
}
//-------------------------------------------------------------------------
@Override
protected Options createOptions(boolean mandatoryConfig) {
final Options options = super.createOptions(mandatoryConfig);
options.addOptionGroup(createViewOptionGroup());
options.addOption(createSnapshotNameOption());
options.addOption(createValuationTimeOption());
options.addOption(createTimeoutOption());
options.addOptionGroup(createMarketDataSourceOptionGroup());
options.addOption(createUnstructuredSnapshot());
return options;
}
private OptionGroup createMarketDataSourceOptionGroup() {
final OptionGroup optionGroup = new OptionGroup();
optionGroup.addOption(createHistoricalOption());
optionGroup.addOption(s_mktDataSourceCli.getOption());
optionGroup.setRequired(true);
return optionGroup;
}
private static OptionGroup createViewOptionGroup() {
final OptionGroup optionGroup = new OptionGroup();
optionGroup.addOption(createViewNameOption());
optionGroup.addOption(createViewProcessIdOption());
optionGroup.setRequired(true);
return optionGroup;
}
private static Option createViewNameOption() {
final Option option = new Option(VIEW_NAME_OPTION, "viewName", true, "the view definition name");
option.setArgName("view name");
return option;
}
private static Option createSnapshotNameOption() {
final Option option = new Option(SNAPSHOT_NAME_OPTION, "snapshotName", true, "the name to use when persisting the snapshot. (defaults to '<view name>/<valuation time>' )");
option.setArgName("snapshot name");
return option;
}
private static Option createViewProcessIdOption() {
final Option option = new Option(VIEW_PROCESS_ID_OPTION, "viewProcessId", true, "the unique identifier of an existing view process e.g ViewProcess~1234");
option.setArgName("unique identifier");
return option;
}
private static Option createValuationTimeOption() {
final Option option = new Option(VALUATION_TIME_OPTION, "valuationTime", true, "the valuation time, HH:mm[:ss] (defaults to now)");
option.setArgName("valuation time");
return option;
}
private static Option createTimeoutOption() {
final Option option = new Option(TIMEOUT_OPTION, "timeout", true, "the timeout, in seconds, for market data to populate the snapshot (defaults to the engine default)");
option.setArgName("seconds");
return option;
}
private static Option createHistoricalOption() {
return new Option("hts", HISTORICAL_OPTION, false, "if true use data from latest hts");
}
private static Option createUnstructuredSnapshot() {
return new Option(UNSTRUCTURED_OPTION, "unstructured", false, "if set, do not capture structures and include data for those in unstructured section");
}
}