/** * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.master.historicaltimeseries.impl; import java.util.Map; import java.util.Set; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.threeten.bp.Clock; import org.threeten.bp.LocalDate; import com.google.common.collect.Maps; import com.opengamma.DataNotFoundException; import com.opengamma.core.change.ChangeManager; import com.opengamma.core.historicaltimeseries.HistoricalTimeSeries; import com.opengamma.core.historicaltimeseries.HistoricalTimeSeriesSource; import com.opengamma.core.historicaltimeseries.impl.SimpleHistoricalTimeSeries; import com.opengamma.id.ExternalIdBundle; import com.opengamma.id.ObjectId; import com.opengamma.id.UniqueId; import com.opengamma.id.VersionCorrection; import com.opengamma.master.AbstractMasterSource; import com.opengamma.master.historicaltimeseries.HistoricalTimeSeriesGetFilter; import com.opengamma.master.historicaltimeseries.HistoricalTimeSeriesInfoDocument; import com.opengamma.master.historicaltimeseries.HistoricalTimeSeriesMaster; import com.opengamma.master.historicaltimeseries.HistoricalTimeSeriesResolutionResult; import com.opengamma.master.historicaltimeseries.HistoricalTimeSeriesResolver; import com.opengamma.master.historicaltimeseries.ManageableHistoricalTimeSeriesInfo; import com.opengamma.timeseries.date.localdate.ImmutableLocalDateDoubleTimeSeries; import com.opengamma.timeseries.date.localdate.LocalDateDoubleTimeSeries; import com.opengamma.util.ArgumentChecker; import com.opengamma.util.OpenGammaClock; import com.opengamma.util.PublicSPI; import com.opengamma.util.tuple.Pair; import com.opengamma.util.tuple.Pairs; /** * A {@code HistoricalTimeSeriesSource} implemented using an underlying {@code HistoricalTimeSeriesMaster}. * <p> * The {@link HistoricalTimeSeriesSource} interface provides time-series to the engine via a narrow API. This class provides the source on top of a standard {@link HistoricalTimeSeriesMaster}. */ @PublicSPI public class MasterHistoricalTimeSeriesSource extends AbstractMasterSource<ManageableHistoricalTimeSeriesInfo, HistoricalTimeSeriesInfoDocument, HistoricalTimeSeriesMaster> implements HistoricalTimeSeriesSource { /** Loggr. */ private static final Logger s_logger = LoggerFactory.getLogger(MasterHistoricalTimeSeriesSource.class); /** * An empty time-series. */ private static final LocalDateDoubleTimeSeries EMPTY_TIMESERIES = ImmutableLocalDateDoubleTimeSeries.EMPTY_SERIES; /** * The resolver. */ private final HistoricalTimeSeriesResolver _resolver; /** * The clock. */ private final Clock _clock = OpenGammaClock.getInstance(); /** * Creates an instance with an underlying master. * * @param master the master, not null * @param resolver the resolver, not null */ public MasterHistoricalTimeSeriesSource(final HistoricalTimeSeriesMaster master, final HistoricalTimeSeriesResolver resolver) { super(master); ArgumentChecker.notNull(resolver, "resolver"); _resolver = resolver; } //------------------------------------------------------------------------- /** * Gets the time-series resolver. * * @return the historical time-series resolver, not null */ public HistoricalTimeSeriesResolver getResolver() { return _resolver; } /** * Gets the clock. * * @return the clock, not null */ public Clock getClock() { return _clock; } //------------------------------------------------------------------------- @Override public HistoricalTimeSeries getHistoricalTimeSeries(UniqueId uniqueId) { return doGetHistoricalTimeSeries(uniqueId, null, null, null); } @Override public HistoricalTimeSeries getHistoricalTimeSeries(UniqueId uniqueId, LocalDate start, boolean includeStart, LocalDate end, boolean includeEnd) { if (start != null && !includeStart) { start = start.plusDays(1); } if (end != null && !includeEnd) { end = end.minusDays(1); } return doGetHistoricalTimeSeries(uniqueId, start, end, null); } @Override public HistoricalTimeSeries getHistoricalTimeSeries(UniqueId uniqueId, LocalDate start, boolean includeStart, LocalDate end, boolean includeEnd, int maxPoints) { if (start != null && !includeStart) { start = start.plusDays(1); } if (end != null && !includeEnd) { end = end.minusDays(1); } return doGetHistoricalTimeSeries(uniqueId, start, end, maxPoints); } @Override public Pair<LocalDate, Double> getLatestDataPoint(UniqueId uniqueId) { ArgumentChecker.notNull(uniqueId, "uniqueId"); HistoricalTimeSeries hts = doGetHistoricalTimeSeries(uniqueId, null, null, -1); if (hts != null) { LocalDateDoubleTimeSeries ldmts = hts.getTimeSeries(); return Pairs.of(ldmts.getLatestTime(), ldmts.getLatestValueFast()); } else { return null; } } @Override public Pair<LocalDate, Double> getLatestDataPoint(UniqueId uniqueId, LocalDate start, boolean includeStart, LocalDate end, boolean includeEnd) { ArgumentChecker.notNull(uniqueId, "uniqueId"); if (start != null && !includeStart) { start = start.plusDays(1); } if (end != null && !includeEnd) { end = end.minusDays(1); } HistoricalTimeSeries hts = doGetHistoricalTimeSeries(uniqueId, start, end, -1); if (hts != null) { LocalDateDoubleTimeSeries ldmts = hts.getTimeSeries(); return Pairs.of(ldmts.getLatestTime(), ldmts.getLatestValueFast()); } else { return null; } } private HistoricalTimeSeries doGetHistoricalTimeSeries(UniqueId uniqueId, LocalDate start, LocalDate end, Integer maxPoints) { ArgumentChecker.notNull(uniqueId, "uniqueId"); try { return getMaster().getTimeSeries(uniqueId, HistoricalTimeSeriesGetFilter.ofRange(start, end, maxPoints)); } catch (DataNotFoundException ex) { return null; } } //------------------------------------------------------------------------- @Override public HistoricalTimeSeries getHistoricalTimeSeries(ExternalIdBundle securityBundle, String dataSource, String dataProvider, String dataField) { return doGetHistoricalTimeSeries(securityBundle, LocalDate.now(getClock()), dataSource, dataProvider, dataField, (LocalDate) null, (LocalDate) null, null); } @Override public HistoricalTimeSeries getHistoricalTimeSeries(ExternalIdBundle securityBundle, LocalDate identifierValidityDate, String dataSource, String dataProvider, String dataField) { return doGetHistoricalTimeSeries(securityBundle, identifierValidityDate, dataSource, dataProvider, dataField, (LocalDate) null, (LocalDate) null, null); } @Override public HistoricalTimeSeries getHistoricalTimeSeries(ExternalIdBundle securityBundle, String dataSource, String dataProvider, String dataField, LocalDate start, boolean includeStart, LocalDate end, boolean includeEnd) { if (start != null && !includeStart) { start = start.plusDays(1); } if (end != null && !includeEnd) { end = end.minusDays(1); } return doGetHistoricalTimeSeries(securityBundle, LocalDate.now(getClock()), dataSource, dataProvider, dataField, start, end, null); } @Override public HistoricalTimeSeries getHistoricalTimeSeries(ExternalIdBundle securityBundle, LocalDate identifierValidityDate, String dataSource, String dataProvider, String dataField, LocalDate start, boolean includeStart, LocalDate end, boolean includeEnd) { if (start != null && !includeStart) { start = start.plusDays(1); } if (end != null && !includeEnd) { end = end.minusDays(1); } return doGetHistoricalTimeSeries(securityBundle, identifierValidityDate, dataSource, dataProvider, dataField, start, end, null); } @Override public HistoricalTimeSeries getHistoricalTimeSeries(ExternalIdBundle securityBundle, String dataSource, String dataProvider, String dataField, LocalDate start, boolean includeStart, LocalDate end, boolean includeEnd, int maxPoints) { if (start != null && !includeStart) { start = start.plusDays(1); } if (end != null && !includeEnd) { end = end.minusDays(1); } return doGetHistoricalTimeSeries(securityBundle, LocalDate.now(getClock()), dataSource, dataProvider, dataField, start, end, maxPoints); } @Override public HistoricalTimeSeries getHistoricalTimeSeries(ExternalIdBundle securityBundle, LocalDate identifierValidityDate, String dataSource, String dataProvider, String dataField, LocalDate start, boolean includeStart, LocalDate end, boolean includeEnd, int maxPoints) { if (start != null && !includeStart) { start = start.plusDays(1); } if (end != null && !includeEnd) { end = end.minusDays(1); } return doGetHistoricalTimeSeries(securityBundle, identifierValidityDate, dataSource, dataProvider, dataField, start, end, maxPoints); } @Override public Pair<LocalDate, Double> getLatestDataPoint(ExternalIdBundle identifierBundle, LocalDate identifierValidityDate, String dataSource, String dataProvider, String dataField) { HistoricalTimeSeries hts = doGetHistoricalTimeSeries(identifierBundle, identifierValidityDate, dataSource, dataProvider, dataField, null, null, -1); if (hts != null) { LocalDateDoubleTimeSeries ldmts = hts.getTimeSeries(); return Pairs.of(ldmts.getLatestTime(), ldmts.getLatestValueFast()); } else { return null; } } @Override public Pair<LocalDate, Double> getLatestDataPoint(ExternalIdBundle identifierBundle, LocalDate identifierValidityDate, String dataSource, String dataProvider, String dataField, LocalDate start, boolean includeStart, LocalDate end, boolean includeEnd) { if (start != null && !includeStart) { start = start.plusDays(1); } if (end != null && !includeEnd) { end = end.minusDays(1); } HistoricalTimeSeries hts = doGetHistoricalTimeSeries(identifierBundle, identifierValidityDate, dataSource, dataProvider, dataField, start, end, -1); if (hts != null) { LocalDateDoubleTimeSeries lddts = hts.getTimeSeries(); return Pairs.of(lddts.getLatestTime(), lddts.getLatestValueFast()); } else { return null; } } @Override public Pair<LocalDate, Double> getLatestDataPoint(ExternalIdBundle identifierBundle, String dataSource, String dataProvider, String dataField) { return getLatestDataPoint(identifierBundle, LocalDate.now(getClock()), dataSource, dataProvider, dataField); } @Override public Pair<LocalDate, Double> getLatestDataPoint(ExternalIdBundle identifierBundle, String dataSource, String dataProvider, String dataField, LocalDate start, boolean includeStart, LocalDate end, boolean includeEnd) { return getLatestDataPoint(identifierBundle, LocalDate.now(getClock()), dataSource, dataProvider, dataField, start, includeStart, end, includeEnd); } private HistoricalTimeSeries doGetHistoricalTimeSeries(ExternalIdBundle identifiers, LocalDate identifierValidityDate, String dataSource, String dataProvider, String dataField, LocalDate start, LocalDate end, Integer maxPoints) { ArgumentChecker.notNull(identifiers, "identifiers"); ArgumentChecker.notNull(dataSource, "dataSource"); ArgumentChecker.notNull(dataField, "field"); HistoricalTimeSeriesResolutionResult resolutionResult = getResolver().resolve(identifiers, identifierValidityDate, dataSource, dataProvider, dataField, null); if (resolutionResult == null) { return null; } HistoricalTimeSeries hts = doGetHistoricalTimeSeries(resolutionResult.getHistoricalTimeSeriesInfo().getTimeSeriesObjectId(), start, end, maxPoints); if (resolutionResult.getAdjuster() != null) { hts = resolutionResult.getAdjuster().adjust(resolutionResult.getHistoricalTimeSeriesInfo().getExternalIdBundle().toBundle(), hts); } return hts; } private HistoricalTimeSeries doGetHistoricalTimeSeries(ObjectId objectId, LocalDate start, LocalDate end, Integer maxPoints) { ArgumentChecker.notNull(objectId, "objectId"); try { return getMaster().getTimeSeries(objectId, VersionCorrection.LATEST, HistoricalTimeSeriesGetFilter.ofRange(start, end, maxPoints)); } catch (DataNotFoundException ex) { return null; } } //------------------------------------------------------------------------- @Override public HistoricalTimeSeries getHistoricalTimeSeries(String dataField, ExternalIdBundle identifierBundle, String resolutionKey) { return doGetHistoricalTimeSeries(dataField, identifierBundle, LocalDate.now(getClock()), resolutionKey, (LocalDate) null, (LocalDate) null, (Integer) null); } @Override public HistoricalTimeSeries getHistoricalTimeSeries(String dataField, ExternalIdBundle identifierBundle, LocalDate identifierValidityDate, String resolutionKey) { return doGetHistoricalTimeSeries(dataField, identifierBundle, identifierValidityDate, resolutionKey, (LocalDate) null, (LocalDate) null, (Integer) null); } @Override public HistoricalTimeSeries getHistoricalTimeSeries(String dataField, ExternalIdBundle identifierBundle, String resolutionKey, LocalDate start, boolean includeStart, LocalDate end, boolean includeEnd) { if (start != null && !includeStart) { start = start.plusDays(1); } if (end != null && !includeEnd) { end = end.minusDays(1); } return doGetHistoricalTimeSeries(dataField, identifierBundle, LocalDate.now(getClock()), resolutionKey, start, end, (Integer) null); } @Override public HistoricalTimeSeries getHistoricalTimeSeries(String dataField, ExternalIdBundle identifierBundle, LocalDate identifierValidityDate, String resolutionKey, LocalDate start, boolean includeStart, LocalDate end, boolean includeEnd) { if (start != null && !includeStart) { start = start.plusDays(1); } if (end != null && !includeEnd) { end = end.minusDays(1); } return doGetHistoricalTimeSeries(dataField, identifierBundle, identifierValidityDate, resolutionKey, start, end, (Integer) null); } @Override public HistoricalTimeSeries getHistoricalTimeSeries(String dataField, ExternalIdBundle identifierBundle, String resolutionKey, LocalDate start, boolean includeStart, LocalDate end, boolean includeEnd, int maxPoints) { if (start != null && !includeStart) { start = start.plusDays(1); } if (end != null && !includeEnd) { end = end.minusDays(1); } return doGetHistoricalTimeSeries(dataField, identifierBundle, LocalDate.now(getClock()), resolutionKey, start, end, maxPoints); } @Override public HistoricalTimeSeries getHistoricalTimeSeries(String dataField, ExternalIdBundle identifierBundle, LocalDate identifierValidityDate, String resolutionKey, LocalDate start, boolean includeStart, LocalDate end, boolean includeEnd, int maxPoints) { if (start != null && !includeStart) { start = start.plusDays(1); } if (end != null && !includeEnd) { end = end.minusDays(1); } return doGetHistoricalTimeSeries(dataField, identifierBundle, identifierValidityDate, resolutionKey, start, end, maxPoints); } @Override public Pair<LocalDate, Double> getLatestDataPoint(String dataField, ExternalIdBundle identifierBundle, String resolutionKey) { return getLatestDataPoint(dataField, identifierBundle, LocalDate.now(getClock()), resolutionKey); } @Override public Pair<LocalDate, Double> getLatestDataPoint(String dataField, ExternalIdBundle identifierBundle, String resolutionKey, LocalDate start, boolean includeStart, LocalDate end, boolean includeEnd) { return getLatestDataPoint(dataField, identifierBundle, LocalDate.now(getClock()), resolutionKey, start, includeStart, end, includeEnd); } @Override public Pair<LocalDate, Double> getLatestDataPoint(String dataField, ExternalIdBundle identifierBundle, LocalDate identifierValidityDate, String resolutionKey) { return getLatestDataPoint(dataField, identifierBundle, identifierValidityDate, resolutionKey, (LocalDate) null, true, (LocalDate) null, true); } @Override public Pair<LocalDate, Double> getLatestDataPoint(String dataField, ExternalIdBundle identifierBundle, LocalDate identifierValidityDate, String resolutionKey, LocalDate start, boolean includeStart, LocalDate end, boolean includeEnd) { if (start != null && !includeStart) { start = start.plusDays(1); } if (end != null && !includeEnd) { end = end.minusDays(1); } HistoricalTimeSeries hts = doGetHistoricalTimeSeries(dataField, identifierBundle, identifierValidityDate, dataField, start, end, -1); if (hts != null) { LocalDateDoubleTimeSeries lddts = hts.getTimeSeries(); return Pairs.of(lddts.getLatestTime(), lddts.getLatestValueFast()); } else { return null; } } private HistoricalTimeSeries doGetHistoricalTimeSeries(String dataField, ExternalIdBundle identifierBundle, LocalDate identifierValidityDate, String resolutionKey, LocalDate start, LocalDate end, Integer maxPoints) { ArgumentChecker.notNull(dataField, "dataField"); ArgumentChecker.notEmpty(identifierBundle, "identifierBundle"); if (StringUtils.isBlank(resolutionKey)) { resolutionKey = HistoricalTimeSeriesRatingFieldNames.DEFAULT_CONFIG_NAME; } HistoricalTimeSeriesResolutionResult resolutionResult = getResolver().resolve(identifierBundle, identifierValidityDate, null, null, dataField, resolutionKey); if (resolutionResult == null) { String message = String.format("Unable to resolve hts using resolutionKey[%s] dataField[%s] bundle[%s] date[%s]", resolutionKey, dataField, identifierBundle, identifierValidityDate); s_logger.debug(message); return null; } if ((maxPoints == null) || (maxPoints != 0)) { HistoricalTimeSeries hts = doGetHistoricalTimeSeries(resolutionResult.getHistoricalTimeSeriesInfo().getUniqueId(), start, end, maxPoints); if (resolutionResult.getAdjuster() != null) { hts = resolutionResult.getAdjuster().adjust(resolutionResult.getHistoricalTimeSeriesInfo().getExternalIdBundle().toBundle(), hts); } return hts; } else { return new SimpleHistoricalTimeSeries(resolutionResult.getHistoricalTimeSeriesInfo().getUniqueId(), EMPTY_TIMESERIES); } } //------------------------------------------------------------------------- @Override public Map<ExternalIdBundle, HistoricalTimeSeries> getHistoricalTimeSeries(Set<ExternalIdBundle> identifierSet, String dataSource, String dataProvider, String dataField, LocalDate start, boolean includeStart, LocalDate end, boolean includeEnd) { ArgumentChecker.notNull(identifierSet, "identifierSet"); Map<ExternalIdBundle, HistoricalTimeSeries> result = Maps.newHashMap(); for (ExternalIdBundle externalIdBundle : identifierSet) { HistoricalTimeSeries historicalTimeSeries = getHistoricalTimeSeries(externalIdBundle, dataSource, dataProvider, dataField, start, includeStart, end, includeEnd); result.put(externalIdBundle, historicalTimeSeries); } return result; } //------------------------------------------------------------------------- @Override public String toString() { return "MasterHistoricalTimeSeriesSource[" + getMaster() + "]"; } @Override public ExternalIdBundle getExternalIdBundle(UniqueId uniqueId) { HistoricalTimeSeriesInfoDocument historicalTimeSeriesInfoDocument = getMaster().get(uniqueId); if (historicalTimeSeriesInfoDocument != null && historicalTimeSeriesInfoDocument.getInfo() != null && historicalTimeSeriesInfoDocument.getInfo().getExternalIdBundle() != null) { return historicalTimeSeriesInfoDocument.getInfo().getExternalIdBundle().toBundle(); } else { s_logger.warn("Cannot find time series info document, or info field is null, or id bundle is null, returning null"); return null; } } //------------------------------------------------------------------------- @Override public ChangeManager changeManager() { return getMaster().changeManager(); } }