/**
* Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.sesame.engine;
import java.util.Set;
import org.threeten.bp.ZonedDateTime;
import com.opengamma.sesame.Environment;
import com.opengamma.sesame.SimpleEnvironment;
import com.opengamma.sesame.function.scenarios.FilteredScenarioDefinition;
import com.opengamma.sesame.marketdata.GatheringMarketDataBundle;
import com.opengamma.sesame.marketdata.MarketDataEnvironment;
import com.opengamma.sesame.marketdata.MarketDataEnvironmentBuilder;
import com.opengamma.sesame.marketdata.MarketDataRequirement;
import com.opengamma.sesame.marketdata.builders.MarketDataEnvironmentFactory;
import com.opengamma.sesame.marketdata.scenarios.SingleScenarioDefinition;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.function.Function;
/**
* Runs individual functions in the same way they are run by the engine.
* <p>
* Functions are run in a three step process:
* <ol>
* <li>Run function with no market data, record requests for data</li>
* <li>Build data that was requested by the functions but not supplied by the user</li>
* <li>Run function with market data and return the result</li>
* </ol>
* This is intended for use in tests that test individual functions.
*/
public class FunctionRunner {
/** Builds market data in response to requirements gathered from the functions. */
private final MarketDataEnvironmentFactory _environmentFactory;
/**
* @param environmentFactory builds market data that is required by functions but not provided by the user
*/
public FunctionRunner(MarketDataEnvironmentFactory environmentFactory) {
_environmentFactory = ArgumentChecker.notNull(environmentFactory, "environmentFactory");
}
/**
* Builds the required market data and uses it to run an individual function.
* <p>
* This is primarily intended for use in tests. It allows the engine to take care of building
* the market data environment without requiring the caller to provide the configuration for an
* entire view.
*
* @param calculationArguments options used when invoking the function
* @param fn the function
* @param <R> the return type of the function
* @return the value returned by the function
*/
public <R> R runFunction(CalculationArguments calculationArguments, Function<Environment, R> fn) {
MarketDataEnvironment marketDataEnvironment =
new MarketDataEnvironmentBuilder().valuationTime(calculationArguments.getValuationTime()).build();
return runFunction(calculationArguments, marketDataEnvironment, fn);
}
/**
* Builds the required market data and uses it to run an individual function.
* <p>
* This is primarily intended for use in tests. It allows the engine to take care of building
* the market data environment without requiring the caller to provide the configuration for an
* entire view.
*
* @param calculationArguments options used when invoking the function
* @param suppliedData pre-built market data to be used in the calculations. If market data is required by the
* functions that isn't supplied, the engine will attempt to build it.
* @param fn the function
* @param <R> the return type of the function
* @return the value returned by the function
*/
public <R> R runFunction(CalculationArguments calculationArguments,
MarketDataEnvironment suppliedData,
Function<Environment, R> fn) {
GatheringMarketDataBundle gatheringBundle = GatheringMarketDataBundle.create(suppliedData.toBundle());
ZonedDateTime valuationTime = valuationTime(calculationArguments, suppliedData);
GatheringMarketDataEnvironment gatheringEnvironment = new GatheringMarketDataEnvironment(gatheringBundle,
valuationTime);
// The purpose of the first run is gathering market data requirements and no market data is provided.
// Therefore the results of the first run are likely to be all failures and are ignored
fn.apply(new SimpleEnvironment(valuationTime, gatheringEnvironment.toBundle(), FilteredScenarioDefinition.EMPTY));
Set<MarketDataRequirement> requirements = gatheringBundle.getRequirements();
MarketDataEnvironment marketData =
_environmentFactory.build(suppliedData,
requirements,
SingleScenarioDefinition.base(),
calculationArguments.getMarketDataSpecification(),
valuationTime);
return fn.apply(new SimpleEnvironment(valuationTime, marketData.toBundle(), FilteredScenarioDefinition.EMPTY));
}
private static ZonedDateTime valuationTime(CalculationArguments calcArgs, MarketDataEnvironment marketData) {
if (calcArgs.getValuationTime() != null) {
return calcArgs.getValuationTime();
} else {
return marketData.getValuationTime();
}
}
}