/**
* Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.financial.analytics.curve;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import javax.inject.Inject;
import org.threeten.bp.Instant;
import org.threeten.bp.LocalDate;
import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.core.config.ConfigSource;
import com.opengamma.engine.function.FunctionCompilationContext;
import com.opengamma.engine.function.FunctionDefinition;
import com.opengamma.financial.analytics.curve.credit.ConfigDBCurveDefinitionSource;
import com.opengamma.financial.analytics.curve.credit.CurveDefinitionSource;
import com.opengamma.financial.analytics.curve.credit.CurveSpecificationBuilder;
import com.opengamma.financial.analytics.ircurve.strips.CurveNode;
import com.opengamma.financial.analytics.ircurve.strips.CurveNodeWithIdentifier;
import com.opengamma.financial.config.ConfigSourceQuery;
import com.opengamma.id.VersionCorrection;
import com.opengamma.util.ArgumentChecker;
/**
* Builds a curve specification from a curve definition and curve node id mapper
* stored in a configuration source.
*/
public class ConfigDBCurveSpecificationBuilder implements CurveSpecificationBuilder {
/** The curve node id mapper */
private final ConfigSourceQuery<CurveNodeIdMapper> _queryCurveNodeIdMapper;
/** The curve definition source */
private final CurveDefinitionSource _definitionSource;
/**
* @param configSource The config source, not null
* @deprecated Use {@link #ConfigDBCurveSpecificationBuilder(ConfigSource,VersionCorrection)} or {@link #init} instead
*/
@Deprecated
public ConfigDBCurveSpecificationBuilder(final ConfigSource configSource) {
this(configSource, VersionCorrection.LATEST);
}
/**
* @param configSource the config source, not null
* @param versionCorrection the version/correction timestamp, not null
*/
@Inject
public ConfigDBCurveSpecificationBuilder(final ConfigSource configSource, final VersionCorrection versionCorrection) {
this(new ConfigSourceQuery<>(configSource, CurveNodeIdMapper.class, versionCorrection), new ConfigDBCurveDefinitionSource(configSource, versionCorrection));
}
private ConfigDBCurveSpecificationBuilder(final ConfigSourceQuery<CurveNodeIdMapper> queryCurveNodeIdMapper, final CurveDefinitionSource definitionSource) {
_queryCurveNodeIdMapper = queryCurveNodeIdMapper;
_definitionSource = definitionSource;
}
public static ConfigDBCurveSpecificationBuilder init(final FunctionCompilationContext context, final FunctionDefinition function) {
return new ConfigDBCurveSpecificationBuilder(ConfigSourceQuery.init(context, function, CurveNodeIdMapper.class), ConfigDBCurveDefinitionSource.init(context, function));
}
@Override
public CurveSpecification buildCurve(final Instant valuationTime, final LocalDate curveDate, final CurveDefinition curveDefinition) {
ArgumentChecker.notNull(valuationTime, "valuation time");
ArgumentChecker.notNull(curveDate, "curve date");
ArgumentChecker.notNull(curveDefinition, "curve definition");
if (curveDefinition instanceof InterpolatedCurveDefinition) {
return getInterpolatedCurveSpecification(valuationTime, curveDate, (InterpolatedCurveDefinition) curveDefinition);
}
return getCurveSpecification(valuationTime, curveDate, curveDefinition);
}
@Override
public AbstractCurveSpecification buildSpecification(final Instant valuationTime, final LocalDate curveDate, final AbstractCurveDefinition curveDefinition) {
ArgumentChecker.notNull(valuationTime, "valuation time");
ArgumentChecker.notNull(curveDate, "curve date");
ArgumentChecker.notNull(curveDefinition, "curve definition");
if (curveDefinition instanceof InterpolatedCurveDefinition) {
return getInterpolatedCurveSpecification(valuationTime, curveDate, (InterpolatedCurveDefinition) curveDefinition);
} else if (curveDefinition instanceof CurveDefinition) {
return getCurveSpecification(valuationTime, curveDate, (CurveDefinition) curveDefinition);
} else if (curveDefinition instanceof ConstantCurveDefinition) {
return getConstantCurveSpecification(valuationTime, curveDate, (ConstantCurveDefinition) curveDefinition);
// } else if (curveDefinition instanceof SpreadCurveDefinition) {
// return getSpreadCurveSpecification(valuationTime, curveDate, (SpreadCurveDefinition) curveDefinition);
}
throw new UnsupportedOperationException("Cannot handle curve definitions of type " + curveDefinition.getClass());
}
/**
* Creates a {@link CurveSpecification}.
*
* @param valuationTime The valuation time
* @param curveDate The curve date
* @param curveDefinition The curve definition
* @return The curve specification
*/
private CurveSpecification getCurveSpecification(final Instant valuationTime, final LocalDate curveDate, final CurveDefinition curveDefinition) {
final Map<String, CurveNodeIdMapper> cache = new HashMap<>();
final Collection<CurveNodeWithIdentifier> identifiers = new ArrayList<>();
final String curveName = curveDefinition.getName();
for (final CurveNode node : curveDefinition.getNodes()) {
final String curveSpecificationName = node.getCurveNodeIdMapperName();
final CurveNodeIdMapper builderConfig = getCurveNodeIdMapper(valuationTime, cache, curveSpecificationName);
if (builderConfig == null) {
throw new OpenGammaRuntimeException("Could not get curve node id mapper " + curveSpecificationName + " for curve named " + curveName);
}
final CurveNodeWithIdentifierBuilder identifierBuilder = new CurveNodeWithIdentifierBuilder(curveDate, builderConfig);
identifiers.add(node.accept(identifierBuilder));
}
return new CurveSpecification(curveDate, curveName, identifiers);
}
/**
* Creates a {@link InterpolatedCurveSpecification}.
*
* @param valuationTime The valuation time
* @param curveDate The curve date
* @param curveDefinition The curve definition
* @return The interpolated curve specification
*/
private InterpolatedCurveSpecification getInterpolatedCurveSpecification(final Instant valuationTime, final LocalDate curveDate, final InterpolatedCurveDefinition curveDefinition) {
final Map<String, CurveNodeIdMapper> cache = new HashMap<>();
final Collection<CurveNodeWithIdentifier> identifiers = new ArrayList<>();
final String curveName = curveDefinition.getName();
for (final CurveNode node : curveDefinition.getNodes()) {
final String curveSpecificationName = node.getCurveNodeIdMapperName();
final CurveNodeIdMapper builderConfig = getCurveNodeIdMapper(valuationTime, cache, curveSpecificationName);
if (builderConfig == null) {
throw new OpenGammaRuntimeException("Could not get curve node id mapper for curve named " + curveName + " for node " + node);
}
final CurveNodeWithIdentifierBuilder identifierBuilder = new CurveNodeWithIdentifierBuilder(curveDate, builderConfig);
identifiers.add(node.accept(identifierBuilder));
}
final String interpolatorName = curveDefinition.getInterpolatorName();
final String rightExtrapolatorName = curveDefinition.getRightExtrapolatorName();
final String leftExtrapolatorName = curveDefinition.getLeftExtrapolatorName();
return new InterpolatedCurveSpecification(curveDate, curveName, identifiers, interpolatorName, rightExtrapolatorName, leftExtrapolatorName);
}
/**
* Creates a {@link ConstantCurveSpecification}.
*
* @param valuationTime The valuation time
* @param curveDate The curve date
* @param curveDefinition The curve definition
* @return The curve specification
*/
private static AbstractCurveSpecification getConstantCurveSpecification(final Instant valuationTime, final LocalDate curveDate, final ConstantCurveDefinition curveDefinition) {
final String curveName = curveDefinition.getName();
return new ConstantCurveSpecification(curveDate, curveName, curveDefinition.getExternalId(), curveDefinition.getDataField());
}
// /**
// * Creates a {@link ConstantSpreadCurveSpecification}
// *
// * @param valuationTime The valuation time
// * @param curveDate The curve date
// * @param curveDefinition The curve definition
// * @return The curve specification
// */
// private AbstractCurveSpecification getConstantSpreadCurveSpecification(final Instant valuationTime, final LocalDate curveDate,
// final ConstantSpreadCurveDefinition curveDefinition) {
// if (curveDefinition.getSpread() != null) {
// final AbstractCurveDefinition definition = _definitionSource.getDefinition(curveDefinition.getFirstCurve());
// final AbstractCurveSpecification specification = buildSpecification(valuationTime, curveDate, definition);
// return new SpreadCurveSpecification(curveDate, curveDefinition.getName(), specification, curveDefinition.getSpread(),
// curveDefinition.getUnits(), curveDefinition.getOperationName());
// }
//
// }
//
// /**
// * Creates a {@link SpreadCurveSpecification}
// *
// * @param valuationTime The valuation time
// * @param curveDate The curve date
// * @param curveDefinition The curve definition
// * @return The curve specification
// */
// private AbstractCurveSpecification getSpreadCurveSpecification(final Instant valuationTime, final LocalDate curveDate, final SpreadCurveDefinition curveDefinition) {
// final AbstractCurveDefinition firstDefinition = _definitionSource.getDefinition(curveDefinition.getFirstCurve());
// final AbstractCurveDefinition secondDefinition = _definitionSource.getDefinition(curveDefinition.getSecondCurve());
// final AbstractCurveSpecification firstSpecification = buildSpecification(valuationTime, curveDate, firstDefinition);
// final AbstractCurveSpecification secondSpecification = buildSpecification(valuationTime, curveDate, secondDefinition);
// return new SpreadCurveSpecification(curveDate, curveDefinition.getName(), firstSpecification, secondSpecification, curveDefinition.getOperationName());
// }
/**
* Gets a {@link CurveNodeIdMapper} from the config source.
*
* @param valuationTime The valuation time
* @param cache A cache of names to curve node id mappers
* @param curveSpecificationName The curve specification name
* @return The curve node id mapper
*/
private CurveNodeIdMapper getCurveNodeIdMapper(final Instant valuationTime, final Map<String, CurveNodeIdMapper> cache, final String curveSpecificationName) {
CurveNodeIdMapper builderSpecDoc = cache.get(curveSpecificationName);
if (builderSpecDoc != null) {
return builderSpecDoc;
}
builderSpecDoc = _queryCurveNodeIdMapper.get(curveSpecificationName);
if (builderSpecDoc != null) {
cache.put(curveSpecificationName, builderSpecDoc);
}
return builderSpecDoc;
}
}