/** * 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.HashMap; import java.util.Map; import org.threeten.bp.LocalDate; import org.threeten.bp.ZonedDateTime; import com.google.common.collect.ImmutableMap; import com.opengamma.timeseries.date.DateTimeSeries; import com.opengamma.util.ArgumentChecker; /** * Builder for constructing instances of {@link MarketDataEnvironment}. */ public class MarketDataEnvironmentBuilder { /** The time for which the market data is valid. */ private MarketDataTime _time = MarketDataTime.VALUATION_TIME; /** Single market data values, keyed by their requirement. */ private final Map<SingleValueRequirement, Object> _marketData = new HashMap<>(); /** Time series of values, keyed by the ID of the value. */ private final Map<MarketDataId<?>, DateTimeSeries<LocalDate, ?>> _timeSeries = new HashMap<>(); /** The valuation time for calculations using the bundle's data. */ private ZonedDateTime _valuationTime; private MarketDataEnvironmentBuilder(MarketDataTime time) { _time = ArgumentChecker.notNull(time, "time"); } MarketDataEnvironmentBuilder(ZonedDateTime valuationTime, Map<SingleValueRequirement, Object> marketData, Map<MarketDataId<?>, DateTimeSeries<LocalDate, ?>> timeSeries) { ArgumentChecker.notNull(marketData, "marketData"); ArgumentChecker.notNull(timeSeries, "timeSeries"); _valuationTime = ArgumentChecker.notNull(valuationTime, "valuationTime"); _marketData.putAll(marketData); _timeSeries.putAll(timeSeries); } /** * Creates an instance whose single data values are valid indefinitely. */ public MarketDataEnvironmentBuilder() { this(MarketDataTime.VALUATION_TIME); } // TODO rename add -> addSingleValue and addTimeSeries /** * Adds a single value of data to the builder. * * @param id ID of the data * @param marketDataItem the data * @return this builder */ public MarketDataEnvironmentBuilder add(MarketDataId<?> id, Object marketDataItem) { ArgumentChecker.notNull(id, "id"); ArgumentChecker.notNull(marketDataItem, "marketDataItem"); SingleValueRequirement requirement = SingleValueRequirement.of(id, _time); _marketData.put(requirement, marketDataItem); return this; } /** * Adds a single value of data to the builder that is valid for a single day. * * @param id ID of the data * @param marketDataItem the data * @param marketDataDate the date for which the data is valid * @return this builder */ public MarketDataEnvironmentBuilder add(MarketDataId<?> id, Object marketDataItem, LocalDate marketDataDate) { ArgumentChecker.notNull(id, "id"); ArgumentChecker.notNull(marketDataItem, "marketDataItem"); ArgumentChecker.notNull(marketDataDate, "marketDataDate"); _marketData.put(SingleValueRequirement.of(id, marketDataDate), marketDataItem); return this; } /** * Adds a single value of data to the builder that is valid for a specific time. * * @param id ID of the data * @param marketDataItem the data * @param marketDataTime the time at which the data is valid * @return this builder */ public MarketDataEnvironmentBuilder add(MarketDataId<?> id, Object marketDataItem, ZonedDateTime marketDataTime) { ArgumentChecker.notNull(id, "id"); ArgumentChecker.notNull(marketDataItem, "marketDataItem"); ArgumentChecker.notNull(marketDataTime, "marketDataTime"); _marketData.put(SingleValueRequirement.of(id, marketDataTime), marketDataItem); return this; } /** * Adds a time series to the builder. * * @param id ID of the data * @param timeSeries the data * @return this builder */ public MarketDataEnvironmentBuilder add(MarketDataId<?> id, DateTimeSeries<LocalDate, ?> timeSeries) { ArgumentChecker.notNull(id, "id"); ArgumentChecker.notNull(timeSeries, "timeSeries"); _timeSeries.put(id, timeSeries); return this; } /** * Adds a single value to the builder. * * @param requirement the requirement for the value * @param value the value * @return this builder */ public MarketDataEnvironmentBuilder add(SingleValueRequirement requirement, Object value) { ArgumentChecker.notNull(requirement, "requirement"); ArgumentChecker.notNull(value, "value"); _marketData.put(requirement, value); return this; } /** * Adds single values to the builder in bulk. * * @param items the data * @return this builder */ public MarketDataEnvironmentBuilder addSingleValues(Map<SingleValueRequirement, Object> items) { ArgumentChecker.notNull(items, "items"); _marketData.putAll(items); return this; } /** * Adds time series to the builder in bulk. * * @param timeSeries the time series * @return this builder */ public MarketDataEnvironmentBuilder addTimeSeries( Map<MarketDataId<?>, ? extends DateTimeSeries<LocalDate, ?>> timeSeries) { ArgumentChecker.notNull(timeSeries, "timeSeries"); _timeSeries.putAll(timeSeries); return this; } /** * Sets the valuation time that should be used for calculations using this bundle's data. * * @param valuationTime the valuation time for calculations using this bundle's data * @return this builder */ public MarketDataEnvironmentBuilder valuationTime(ZonedDateTime valuationTime) { _valuationTime = ArgumentChecker.notNull(valuationTime, "valuationTime"); return this; } /** * Builds a market data bundle from the data in this builder. * <p> * Changes to this builder after calling {@code build()} won't affect the data in the bundle. This builder * can continue to be used after calling {@code build()} and can build an unlimited number of bundles. * * @return a market data bundle containing the data in this builder */ public MarketDataEnvironment build() { return new MapMarketDataEnvironment(_marketData, _timeSeries, _valuationTime); } /** * Merges two market data environments with non-overlapping data and the same valuation time. * <p> * This method will fail if any market data requirement or ID appears in both environments or if they * have different valuation times. * * @param env1 a market data environment * @param env2 a market data environment * @return a market data environment containing the data from both environments */ public static MarketDataEnvironment merge(MarketDataEnvironment env1, MarketDataEnvironment env2) { ArgumentChecker.notNull(env1, "env1"); ArgumentChecker.notNull(env2, "env2"); Map<SingleValueRequirement, Object> data = ImmutableMap.<SingleValueRequirement, Object>builder() .putAll(env1.getData()) .putAll(env2.getData()) .build(); Map<MarketDataId<?>, DateTimeSeries<LocalDate, ?>> timeSeries = ImmutableMap.<MarketDataId<?>, DateTimeSeries<LocalDate, ?>>builder() .putAll(env1.getTimeSeries()) .putAll(env2.getTimeSeries()) .build(); return new MapMarketDataEnvironment(data, timeSeries, env1.getValuationTime()); } /** * @return an empty market data environment */ public static MarketDataEnvironment empty() { return new MapMarketDataEnvironment( ImmutableMap.<SingleValueRequirement, Object>of(), ImmutableMap.<MarketDataId<?>, DateTimeSeries<LocalDate, ?>>of(), ZonedDateTime.now()); } }