/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.engine.marketdata.historical;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Set;
import org.apache.commons.lang.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.threeten.bp.LocalDate;
import com.opengamma.core.historicaltimeseries.HistoricalTimeSeriesAdjustment;
import com.opengamma.core.historicaltimeseries.HistoricalTimeSeriesResolutionResult;
import com.opengamma.core.historicaltimeseries.HistoricalTimeSeriesResolver;
import com.opengamma.core.historicaltimeseries.HistoricalTimeSeriesSource;
import com.opengamma.core.value.MarketDataRequirementNames;
import com.opengamma.engine.ComputationTargetSpecification;
import com.opengamma.engine.marketdata.AbstractMarketDataProvider;
import com.opengamma.engine.marketdata.MarketDataPermissionProvider;
import com.opengamma.engine.marketdata.PermissiveMarketDataPermissionProvider;
import com.opengamma.engine.marketdata.availability.AbstractMarketDataAvailabilityProvider;
import com.opengamma.engine.marketdata.availability.MarketDataAvailabilityProvider;
import com.opengamma.engine.marketdata.spec.HistoricalMarketDataSpecification;
import com.opengamma.engine.marketdata.spec.MarketDataSpecification;
import com.opengamma.engine.value.ValueProperties;
import com.opengamma.engine.value.ValuePropertyNames;
import com.opengamma.engine.value.ValueRequirement;
import com.opengamma.engine.value.ValueSpecification;
import com.opengamma.id.ExternalId;
import com.opengamma.id.ExternalIdBundle;
import com.opengamma.id.UniqueId;
import com.opengamma.util.ArgumentChecker;
/**
* Market data provider that sources data from historical time-series.
*/
public abstract class AbstractHistoricalMarketDataProvider extends AbstractMarketDataProvider {
private static final Logger s_logger = LoggerFactory.getLogger(AbstractHistoricalMarketDataProvider.class);
/**
* The property put onto the value specifications created.
*/
protected static final String NORMALIZATION_PROPERTY = "Normalization";
private final HistoricalTimeSeriesSource _historicalTimeSeriesSource;
private final HistoricalTimeSeriesResolver _historicalTimeSeriesResolver;
private final String _timeSeriesResolverKey;
private final MarketDataPermissionProvider _permissionProvider;
/**
* Creates a new market data provider.
*
* @param historicalTimeSeriesSource the underlying source of historical data, not null
* @param historicalTimeSeriesResolver the resolver to identifier historical data, not null
* @param timeSeriesResolverKey the source resolver key, or null to use the source default
*/
public AbstractHistoricalMarketDataProvider(final HistoricalTimeSeriesSource historicalTimeSeriesSource, final HistoricalTimeSeriesResolver historicalTimeSeriesResolver,
final String timeSeriesResolverKey) {
ArgumentChecker.notNull(historicalTimeSeriesSource, "historicalTimeSeriesSource");
ArgumentChecker.notNull(historicalTimeSeriesResolver, "historicalTimeSeriesResolver");
_historicalTimeSeriesSource = historicalTimeSeriesSource;
_historicalTimeSeriesResolver = historicalTimeSeriesResolver;
_timeSeriesResolverKey = timeSeriesResolverKey;
_permissionProvider = new PermissiveMarketDataPermissionProvider();
}
public AbstractHistoricalMarketDataProvider(final HistoricalTimeSeriesSource historicalTimeSeriesSource, final HistoricalTimeSeriesResolver historicalTimeSeriesResolver) {
this(historicalTimeSeriesSource, historicalTimeSeriesResolver, null);
}
@Override
public void subscribe(final ValueSpecification valueSpecification) {
s_logger.debug("Added subscriptions to {}", valueSpecification);
subscriptionSucceeded(valueSpecification);
}
@Override
public void subscribe(final Set<ValueSpecification> valueSpecifications) {
s_logger.debug("Added subscriptions to {}", valueSpecifications);
subscriptionsSucceeded(valueSpecifications);
}
@Override
public void unsubscribe(final ValueSpecification valueSpecification) {
s_logger.debug("Removed subscription from {}", valueSpecification);
}
@Override
public void unsubscribe(final Set<ValueSpecification> valueSpecifications) {
s_logger.debug("Removed subscriptions from {}", valueSpecifications);
}
protected abstract LocalDate getHistoricalResolutionDate(final MarketDataSpecification marketDataSpec);
@Override
public MarketDataAvailabilityProvider getAvailabilityProvider(final MarketDataSpecification marketDataSpec) {
final LocalDate date = getHistoricalResolutionDate(marketDataSpec);
return new AbstractMarketDataAvailabilityProvider() {
@Override
protected ValueSpecification getAvailability(final ComputationTargetSpecification targetSpec, final ExternalId identifier, final ValueRequirement desiredValue) {
return getAvailability(targetSpec, identifier.toBundle(), desiredValue);
}
@Override
protected ValueSpecification getAvailability(final ComputationTargetSpecification targetSpec, final ExternalIdBundle identifiers, final ValueRequirement desiredValue) {
HistoricalTimeSeriesResolutionResult resolved = getTimeSeriesResolver().resolve(identifiers, date, null, null, desiredValue.getValueName(), getTimeSeriesResolverKey());
if (resolved == null) {
if (s_logger.isDebugEnabled() && desiredValue.getValueName().equals(MarketDataRequirementNames.MARKET_VALUE)) {
s_logger.debug("Missing market data {}", desiredValue);
}
return null;
} else {
final ValueProperties.Builder properties = ValueProperties.with(ValuePropertyNames.FUNCTION, getSyntheticFunctionName());
if (resolved.getAdjuster() != null) {
final ExternalIdBundle resolvedIdentifiers = resolved.getHistoricalTimeSeriesInfo().getExternalIdBundle().toBundle(date);
final HistoricalTimeSeriesAdjustment adjustment = resolved.getAdjuster().getAdjustment(resolvedIdentifiers);
properties.with(NORMALIZATION_PROPERTY, adjustment.toString());
}
return new ValueSpecification(desiredValue.getValueName(), ComputationTargetSpecification.of(resolved.getHistoricalTimeSeriesInfo().getUniqueId()), properties.get());
}
}
@Override
protected ValueSpecification getAvailability(final ComputationTargetSpecification targetSpec, final UniqueId identifier, final ValueRequirement desiredValue) {
return null;
}
@Override
protected ValueSpecification getAvailability(final ComputationTargetSpecification targetSpec, final ValueRequirement desiredValue) {
return null;
}
@Override
public Serializable getAvailabilityHintKey() {
final ArrayList<Serializable> key = new ArrayList<Serializable>(3);
key.add(AbstractHistoricalMarketDataProvider.this.getClass().getName());
key.add(date);
key.add(getTimeSeriesResolverKey());
return key;
}
};
}
@Override
public MarketDataPermissionProvider getPermissionProvider() {
return _permissionProvider;
}
//-------------------------------------------------------------------------
@Override
public boolean isCompatible(final MarketDataSpecification marketDataSpec) {
if (!(marketDataSpec instanceof HistoricalMarketDataSpecification)) {
return false;
}
final HistoricalMarketDataSpecification historicalSpec = (HistoricalMarketDataSpecification) marketDataSpec;
return ObjectUtils.equals(getTimeSeriesResolverKey(), historicalSpec.getTimeSeriesResolverKey());
}
protected HistoricalTimeSeriesSource getTimeSeriesSource() {
return _historicalTimeSeriesSource;
}
protected HistoricalTimeSeriesResolver getTimeSeriesResolver() {
return _historicalTimeSeriesResolver;
}
protected String getTimeSeriesResolverKey() {
return _timeSeriesResolverKey;
}
/**
* The function name used in value specifications describing items sourced by this provider. This is only used for diagnostics when browsing the dependency graph.
*
* @return the function name
*/
protected String getSyntheticFunctionName() {
return getClass().getSimpleName();
}
}