/** * Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.master.historicaltimeseries.impl; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.threeten.bp.LocalDate; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; import com.opengamma.core.historicaltimeseries.HistoricalTimeSeriesAdjuster; import com.opengamma.id.ExternalIdBundle; import com.opengamma.master.historicaltimeseries.HistoricalTimeSeriesMaster; import com.opengamma.master.historicaltimeseries.HistoricalTimeSeriesResolutionResult; import com.opengamma.master.historicaltimeseries.HistoricalTimeSeriesSelector; import com.opengamma.master.historicaltimeseries.ManageableHistoricalTimeSeriesInfo; import com.opengamma.util.ArgumentChecker; /** * Historical time series resolver that can expose synthetic data fields by mapping these onto a real, underlying data * field together with an optional adjuster. */ public class FieldMappingHistoricalTimeSeriesResolver extends DefaultHistoricalTimeSeriesResolver { private static final Logger s_logger = LoggerFactory.getLogger(FieldMappingHistoricalTimeSeriesResolver.class); private final Map<String, HistoricalTimeSeriesFieldAdjustmentMap> _fieldMaps; public FieldMappingHistoricalTimeSeriesResolver(Collection<HistoricalTimeSeriesFieldAdjustmentMap> fieldMaps, HistoricalTimeSeriesSelector selector, HistoricalTimeSeriesMaster master) { super(selector, master); _fieldMaps = getFieldMaps(fieldMaps); } @Override public HistoricalTimeSeriesResolutionResult resolve(ExternalIdBundle identifierBundle, LocalDate identifierValidityDate, String dataSource, String dataProvider, String dataField, String resolutionKey) { ArgumentChecker.notNull(dataField, "dataField"); // Apply any field mappings Map<String, HistoricalTimeSeriesFieldAdjustment> fieldMappings = getFieldAdjustments(dataSource, dataField); if (fieldMappings.size() == 1) { // Optimisation - might as well restrict the search results Map.Entry<String, HistoricalTimeSeriesFieldAdjustment> fieldMappingEntry = Iterables.getOnlyElement(fieldMappings.entrySet()); dataSource = fieldMappingEntry.getKey(); dataProvider = fieldMappingEntry.getValue().getUnderlyingDataProvider(); dataField = fieldMappingEntry.getValue().getUnderlyingDataField(); } else if (fieldMappings.size() > 1) { // Could have been mapped to multiple underlying providers/fields dataField = null; dataProvider = null; } if (identifierBundle != null) { Collection<ManageableHistoricalTimeSeriesInfo> timeSeriesCandidates = search(identifierBundle, identifierValidityDate, dataSource, dataProvider, dataField); if (!fieldMappings.isEmpty()) { Iterator<ManageableHistoricalTimeSeriesInfo> it = timeSeriesCandidates.iterator(); while (it.hasNext()) { ManageableHistoricalTimeSeriesInfo candidate = it.next(); HistoricalTimeSeriesFieldAdjustment fieldAdjustment = fieldMappings.get(candidate.getDataSource()); if (fieldAdjustment == null || ((fieldAdjustment.getUnderlyingDataProvider() != null && !fieldAdjustment.getUnderlyingDataProvider().equals(candidate.getDataProvider())) || !fieldAdjustment.getUnderlyingDataField().equals(candidate.getDataField()))) { // Incompatible it.remove(); } } } ManageableHistoricalTimeSeriesInfo selectedResult = select(timeSeriesCandidates, resolutionKey); if (selectedResult == null) { s_logger.debug("Resolver failed to find any time-series for {} using {}/{}", new Object[] {identifierBundle, dataField, resolutionKey }); return null; } HistoricalTimeSeriesFieldAdjustment fieldAdjustment = fieldMappings.get(selectedResult.getDataSource()); HistoricalTimeSeriesAdjuster adjuster = fieldAdjustment != null ? fieldAdjustment.getAdjuster() : null; return new HistoricalTimeSeriesResolutionResult(selectedResult, adjuster); } else { return search(dataSource, dataProvider, dataField); } } public Collection<HistoricalTimeSeriesFieldAdjustmentMap> getFieldMaps() { return _fieldMaps.values(); } //------------------------------------------------------------------------- private Map<String, HistoricalTimeSeriesFieldAdjustmentMap> getFieldMaps(Collection<HistoricalTimeSeriesFieldAdjustmentMap> fieldMaps) { Map<String, HistoricalTimeSeriesFieldAdjustmentMap> result = new HashMap<String, HistoricalTimeSeriesFieldAdjustmentMap>(); for (HistoricalTimeSeriesFieldAdjustmentMap fieldMap : fieldMaps) { if (result.put(fieldMap.getDataSource(), fieldMap) != null) { throw new IllegalArgumentException("Only one field map per data source is permitted. Found multiple for data source " + fieldMap.getDataSource()); } } return result; } private Map<String, HistoricalTimeSeriesFieldAdjustment> getFieldAdjustments(String dataSource, String dataField) { if (dataSource != null) { HistoricalTimeSeriesFieldAdjustmentMap fieldMap = _fieldMaps.get(dataSource); HistoricalTimeSeriesFieldAdjustment fieldAdjustment = fieldMap != null ? fieldMap.getFieldAdjustment(dataField) : null; return fieldAdjustment != null ? ImmutableMap.of(dataSource, fieldAdjustment) : ImmutableMap.<String, HistoricalTimeSeriesFieldAdjustment>of(); } Map<String, HistoricalTimeSeriesFieldAdjustment> results = new HashMap<String, HistoricalTimeSeriesFieldAdjustment>(); for (Map.Entry<String, HistoricalTimeSeriesFieldAdjustmentMap> fieldMapEntry : _fieldMaps.entrySet()) { HistoricalTimeSeriesFieldAdjustment fieldAdjustment = fieldMapEntry.getValue().getFieldAdjustment(dataField); if (fieldAdjustment != null) { results.put(fieldMapEntry.getKey(), fieldAdjustment); } } return results; } }