/**
* Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.sesame.marketdata;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.threeten.bp.LocalDate;
import org.threeten.bp.ZonedDateTime;
import com.google.common.collect.Sets;
import com.opengamma.timeseries.date.DateTimeSeries;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.result.FailureStatus;
import com.opengamma.util.result.Result;
import com.opengamma.util.time.LocalDateRange;
/**
* Market data bundle that doesn't contain any data but records requests it receives for data.
* <p>
* All of the data lookup methods always return a failure result. Requests are recorded if the data
* isn't available in the bundle of supplied data passed to the constructor.
*
* TODO move to the engine package and make package-private
*/
public final class GatheringMarketDataBundle implements MarketDataBundle {
/**
* This class is only used during the first phase of execution while the engine is gathering market
* data requirements. Every result returned by this class will be a failure and it would be expensive
* to construct a stack trace every time. It would also be pointless as the results from the first
* phase of execution are ignored and therefore the stack traces would never be seen.
*/
private static final Result<?> FAILURE = Result.failure(FailureStatus.PENDING_DATA,
"Gathering requirements - no data available");
private final MarketDataTime _time;
private final MarketDataBundle _suppliedData;
private final Set<SingleValueRequirement> _requirements;
private final Set<TimeSeriesRequirement> _timeSeriesRequirements;
private GatheringMarketDataBundle(MarketDataTime time, MarketDataBundle suppliedData) {
this(time,
suppliedData,
Collections.newSetFromMap(new ConcurrentHashMap<SingleValueRequirement, Boolean>()),
Collections.newSetFromMap(new ConcurrentHashMap<TimeSeriesRequirement, Boolean>()));
}
private GatheringMarketDataBundle(MarketDataTime time,
MarketDataBundle suppliedData,
Set<SingleValueRequirement> requirements,
Set<TimeSeriesRequirement> timeSeriesRequirements) {
_time = ArgumentChecker.notNull(time, "time");
_suppliedData = ArgumentChecker.notNull(suppliedData, "suppliedData");
_requirements = requirements;
_timeSeriesRequirements = timeSeriesRequirements;
}
public static GatheringMarketDataBundle create(ZonedDateTime time, MarketDataBundle suppliedData) {
return new GatheringMarketDataBundle(MarketDataTime.of(time), suppliedData);
}
public static GatheringMarketDataBundle create(LocalDate date, MarketDataBundle suppliedData) {
return new GatheringMarketDataBundle(MarketDataTime.of(date), suppliedData);
}
public static GatheringMarketDataBundle create(MarketDataBundle suppliedData) {
return new GatheringMarketDataBundle(MarketDataTime.VALUATION_TIME, suppliedData);
}
@Override
public <T, I extends MarketDataId<T>> Result<T> get(I id, Class<T> dataType) {
// only gather requirements for data that hasn't been supplied
if (_suppliedData.get(id, dataType).isSuccess()) {
return failure();
}
SingleValueRequirement requirement = SingleValueRequirement.of(id, _time);
_requirements.add(requirement);
return failure();
}
@Override
public <T, I extends MarketDataId<T>> Result<DateTimeSeries<LocalDate, T>> get(
I id,
Class<T> dataType,
LocalDateRange dateRange) {
// only gather requirements for data that hasn't been supplied
if (_suppliedData.get(id, dataType, dateRange).isSuccess()) {
return failure();
}
TimeSeriesRequirement requirement = TimeSeriesRequirement.of(id, dateRange);
_timeSeriesRequirements.add(requirement);
return failure();
}
@Override
public MarketDataBundle withTime(ZonedDateTime time) {
return new GatheringMarketDataBundle(MarketDataTime.of(time), _suppliedData, _requirements, _timeSeriesRequirements);
}
@Override
public MarketDataBundle withDate(LocalDate date) {
return new GatheringMarketDataBundle(MarketDataTime.of(date), _suppliedData, _requirements, _timeSeriesRequirements);
}
/**
* @return the gathered requirements
*/
public Set<MarketDataRequirement> getRequirements() {
return Sets.<MarketDataRequirement>union(_requirements, _timeSeriesRequirements);
}
@SuppressWarnings("unchecked") // this is safe, the type is never used in a failure result
private static <T> Result<T> failure() {
return (Result<T>) FAILURE;
}
}