/**
* Copyright (C) 2015 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.strata.calc.marketdata;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import org.joda.beans.Bean;
import org.joda.beans.BeanBuilder;
import org.joda.beans.BeanDefinition;
import org.joda.beans.ImmutableBean;
import org.joda.beans.JodaBeanUtils;
import org.joda.beans.MetaProperty;
import org.joda.beans.Property;
import org.joda.beans.PropertyDefinition;
import org.joda.beans.impl.direct.DirectFieldsBeanBuilder;
import org.joda.beans.impl.direct.DirectMetaBean;
import org.joda.beans.impl.direct.DirectMetaProperty;
import org.joda.beans.impl.direct.DirectMetaPropertyMap;
import com.google.common.collect.ImmutableSet;
import com.opengamma.strata.basics.CalculationTarget;
import com.opengamma.strata.basics.ReferenceData;
import com.opengamma.strata.basics.currency.Currency;
import com.opengamma.strata.calc.CalculationRules;
import com.opengamma.strata.calc.Column;
import com.opengamma.strata.calc.runner.CalculationTasks;
import com.opengamma.strata.data.MarketDataId;
import com.opengamma.strata.data.ObservableId;
/**
* Requirements for market data.
* <p>
* This class is used as the input to {@link MarketDataFactory}.
* It includes the market data identifiers that the application needs.
*/
@BeanDefinition(builderScope = "private", constructorScope = "package")
public final class MarketDataRequirements implements ImmutableBean {
/** A set of requirements which specifies that no market data is required. */
private static final MarketDataRequirements EMPTY = MarketDataRequirements.builder().build();
/** Keys identifying the market data values required for the calculations. */
@PropertyDefinition(validate = "notNull", builderType = "Set<? extends ObservableId>")
private final ImmutableSet<ObservableId> observables;
/** Keys identifying the market data values required for the calculations. */
@PropertyDefinition(validate = "notNull", builderType = "Set<? extends MarketDataId<?>>")
private final ImmutableSet<MarketDataId<?>> nonObservables;
/** Keys identifying the time series of market data values required for the calculations. */
@PropertyDefinition(validate = "notNull", builderType = "Set<? extends ObservableId>")
private final ImmutableSet<ObservableId> timeSeries;
/**
* The currencies in the calculation results. The market data must include FX rates in the
* to allow conversion into the reporting currency. The FX rates must have the output currency as the base
* currency and the reporting currency as the counter currency.
*/
@PropertyDefinition(validate = "notNull")
private final ImmutableSet<Currency> outputCurrencies;
//-------------------------------------------------------------------------
/**
* Obtains an instance from a set of targets, columns and rules.
* <p>
* The targets will typically be trades.
* The columns represent the measures to calculate.
*
* @param calculationRules the rules defining how the calculation is performed
* @param targets the targets for which values of the measures will be calculated
* @param columns the columns that will be calculated
* @param refData the reference data
* @return the market data requirements
*/
public static MarketDataRequirements of(
CalculationRules calculationRules,
List<? extends CalculationTarget> targets,
List<Column> columns,
ReferenceData refData) {
return CalculationTasks.of(calculationRules, targets, columns).requirements(refData);
}
/**
* Obtains an instance containing a single market data ID.
*
* @param id the ID of the only market data value required
* @return a set of requirements containing a single market data ID
*/
public static MarketDataRequirements of(MarketDataId<?> id) {
return builder().addValues(id).build();
}
/**
* Obtains an instance specifying that no market data is required.
*
* @return a set of requirements specifying that no market data is required
*/
public static MarketDataRequirements empty() {
return EMPTY;
}
/**
* Returns an empty mutable builder for building up a set of requirements.
*
* @return an empty mutable builder for building up a set of requirements
*/
public static MarketDataRequirementsBuilder builder() {
return new MarketDataRequirementsBuilder();
}
//-------------------------------------------------------------------------
/**
* Merges multiple sets of requirements into a single set.
*
* @param requirements market data requirements
* @return a single set of requirements containing all the requirements from the input sets
*/
public static MarketDataRequirements combine(List<MarketDataRequirements> requirements) {
ImmutableSet.Builder<ObservableId> observablesBuilder = ImmutableSet.builder();
ImmutableSet.Builder<MarketDataId<?>> nonObservablesBuilder = ImmutableSet.builder();
ImmutableSet.Builder<ObservableId> timeSeriesBuilder = ImmutableSet.builder();
ImmutableSet.Builder<Currency> outputCurrenciesBuilder = ImmutableSet.builder();
for (MarketDataRequirements req : requirements) {
observablesBuilder.addAll(req.observables);
nonObservablesBuilder.addAll(req.nonObservables);
timeSeriesBuilder.addAll(req.timeSeries);
outputCurrenciesBuilder.addAll(req.outputCurrencies);
}
return new MarketDataRequirements(
observablesBuilder.build(),
nonObservablesBuilder.build(),
timeSeriesBuilder.build(),
outputCurrenciesBuilder.build());
}
//------------------------- AUTOGENERATED START -------------------------
///CLOVER:OFF
/**
* The meta-bean for {@code MarketDataRequirements}.
* @return the meta-bean, not null
*/
public static MarketDataRequirements.Meta meta() {
return MarketDataRequirements.Meta.INSTANCE;
}
static {
JodaBeanUtils.registerMetaBean(MarketDataRequirements.Meta.INSTANCE);
}
/**
* Creates an instance.
* @param observables the value of the property, not null
* @param nonObservables the value of the property, not null
* @param timeSeries the value of the property, not null
* @param outputCurrencies the value of the property, not null
*/
MarketDataRequirements(
Set<? extends ObservableId> observables,
Set<? extends MarketDataId<?>> nonObservables,
Set<? extends ObservableId> timeSeries,
Set<Currency> outputCurrencies) {
JodaBeanUtils.notNull(observables, "observables");
JodaBeanUtils.notNull(nonObservables, "nonObservables");
JodaBeanUtils.notNull(timeSeries, "timeSeries");
JodaBeanUtils.notNull(outputCurrencies, "outputCurrencies");
this.observables = ImmutableSet.copyOf(observables);
this.nonObservables = ImmutableSet.copyOf(nonObservables);
this.timeSeries = ImmutableSet.copyOf(timeSeries);
this.outputCurrencies = ImmutableSet.copyOf(outputCurrencies);
}
@Override
public MarketDataRequirements.Meta metaBean() {
return MarketDataRequirements.Meta.INSTANCE;
}
@Override
public <R> Property<R> property(String propertyName) {
return metaBean().<R>metaProperty(propertyName).createProperty(this);
}
@Override
public Set<String> propertyNames() {
return metaBean().metaPropertyMap().keySet();
}
//-----------------------------------------------------------------------
/**
* Gets keys identifying the market data values required for the calculations.
* @return the value of the property, not null
*/
public ImmutableSet<ObservableId> getObservables() {
return observables;
}
//-----------------------------------------------------------------------
/**
* Gets keys identifying the market data values required for the calculations.
* @return the value of the property, not null
*/
public ImmutableSet<MarketDataId<?>> getNonObservables() {
return nonObservables;
}
//-----------------------------------------------------------------------
/**
* Gets keys identifying the time series of market data values required for the calculations.
* @return the value of the property, not null
*/
public ImmutableSet<ObservableId> getTimeSeries() {
return timeSeries;
}
//-----------------------------------------------------------------------
/**
* Gets the currencies in the calculation results. The market data must include FX rates in the
* to allow conversion into the reporting currency. The FX rates must have the output currency as the base
* currency and the reporting currency as the counter currency.
* @return the value of the property, not null
*/
public ImmutableSet<Currency> getOutputCurrencies() {
return outputCurrencies;
}
//-----------------------------------------------------------------------
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj != null && obj.getClass() == this.getClass()) {
MarketDataRequirements other = (MarketDataRequirements) obj;
return JodaBeanUtils.equal(observables, other.observables) &&
JodaBeanUtils.equal(nonObservables, other.nonObservables) &&
JodaBeanUtils.equal(timeSeries, other.timeSeries) &&
JodaBeanUtils.equal(outputCurrencies, other.outputCurrencies);
}
return false;
}
@Override
public int hashCode() {
int hash = getClass().hashCode();
hash = hash * 31 + JodaBeanUtils.hashCode(observables);
hash = hash * 31 + JodaBeanUtils.hashCode(nonObservables);
hash = hash * 31 + JodaBeanUtils.hashCode(timeSeries);
hash = hash * 31 + JodaBeanUtils.hashCode(outputCurrencies);
return hash;
}
@Override
public String toString() {
StringBuilder buf = new StringBuilder(160);
buf.append("MarketDataRequirements{");
buf.append("observables").append('=').append(observables).append(',').append(' ');
buf.append("nonObservables").append('=').append(nonObservables).append(',').append(' ');
buf.append("timeSeries").append('=').append(timeSeries).append(',').append(' ');
buf.append("outputCurrencies").append('=').append(JodaBeanUtils.toString(outputCurrencies));
buf.append('}');
return buf.toString();
}
//-----------------------------------------------------------------------
/**
* The meta-bean for {@code MarketDataRequirements}.
*/
public static final class Meta extends DirectMetaBean {
/**
* The singleton instance of the meta-bean.
*/
static final Meta INSTANCE = new Meta();
/**
* The meta-property for the {@code observables} property.
*/
@SuppressWarnings({"unchecked", "rawtypes" })
private final MetaProperty<ImmutableSet<ObservableId>> observables = DirectMetaProperty.ofImmutable(
this, "observables", MarketDataRequirements.class, (Class) ImmutableSet.class);
/**
* The meta-property for the {@code nonObservables} property.
*/
@SuppressWarnings({"unchecked", "rawtypes" })
private final MetaProperty<ImmutableSet<MarketDataId<?>>> nonObservables = DirectMetaProperty.ofImmutable(
this, "nonObservables", MarketDataRequirements.class, (Class) ImmutableSet.class);
/**
* The meta-property for the {@code timeSeries} property.
*/
@SuppressWarnings({"unchecked", "rawtypes" })
private final MetaProperty<ImmutableSet<ObservableId>> timeSeries = DirectMetaProperty.ofImmutable(
this, "timeSeries", MarketDataRequirements.class, (Class) ImmutableSet.class);
/**
* The meta-property for the {@code outputCurrencies} property.
*/
@SuppressWarnings({"unchecked", "rawtypes" })
private final MetaProperty<ImmutableSet<Currency>> outputCurrencies = DirectMetaProperty.ofImmutable(
this, "outputCurrencies", MarketDataRequirements.class, (Class) ImmutableSet.class);
/**
* The meta-properties.
*/
private final Map<String, MetaProperty<?>> metaPropertyMap$ = new DirectMetaPropertyMap(
this, null,
"observables",
"nonObservables",
"timeSeries",
"outputCurrencies");
/**
* Restricted constructor.
*/
private Meta() {
}
@Override
protected MetaProperty<?> metaPropertyGet(String propertyName) {
switch (propertyName.hashCode()) {
case 121811856: // observables
return observables;
case 824041091: // nonObservables
return nonObservables;
case 779431844: // timeSeries
return timeSeries;
case -1022597040: // outputCurrencies
return outputCurrencies;
}
return super.metaPropertyGet(propertyName);
}
@Override
public BeanBuilder<? extends MarketDataRequirements> builder() {
return new MarketDataRequirements.Builder();
}
@Override
public Class<? extends MarketDataRequirements> beanType() {
return MarketDataRequirements.class;
}
@Override
public Map<String, MetaProperty<?>> metaPropertyMap() {
return metaPropertyMap$;
}
//-----------------------------------------------------------------------
/**
* The meta-property for the {@code observables} property.
* @return the meta-property, not null
*/
public MetaProperty<ImmutableSet<ObservableId>> observables() {
return observables;
}
/**
* The meta-property for the {@code nonObservables} property.
* @return the meta-property, not null
*/
public MetaProperty<ImmutableSet<MarketDataId<?>>> nonObservables() {
return nonObservables;
}
/**
* The meta-property for the {@code timeSeries} property.
* @return the meta-property, not null
*/
public MetaProperty<ImmutableSet<ObservableId>> timeSeries() {
return timeSeries;
}
/**
* The meta-property for the {@code outputCurrencies} property.
* @return the meta-property, not null
*/
public MetaProperty<ImmutableSet<Currency>> outputCurrencies() {
return outputCurrencies;
}
//-----------------------------------------------------------------------
@Override
protected Object propertyGet(Bean bean, String propertyName, boolean quiet) {
switch (propertyName.hashCode()) {
case 121811856: // observables
return ((MarketDataRequirements) bean).getObservables();
case 824041091: // nonObservables
return ((MarketDataRequirements) bean).getNonObservables();
case 779431844: // timeSeries
return ((MarketDataRequirements) bean).getTimeSeries();
case -1022597040: // outputCurrencies
return ((MarketDataRequirements) bean).getOutputCurrencies();
}
return super.propertyGet(bean, propertyName, quiet);
}
@Override
protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) {
metaProperty(propertyName);
if (quiet) {
return;
}
throw new UnsupportedOperationException("Property cannot be written: " + propertyName);
}
}
//-----------------------------------------------------------------------
/**
* The bean-builder for {@code MarketDataRequirements}.
*/
private static final class Builder extends DirectFieldsBeanBuilder<MarketDataRequirements> {
private Set<? extends ObservableId> observables = ImmutableSet.of();
private Set<? extends MarketDataId<?>> nonObservables = ImmutableSet.of();
private Set<? extends ObservableId> timeSeries = ImmutableSet.of();
private Set<Currency> outputCurrencies = ImmutableSet.of();
/**
* Restricted constructor.
*/
private Builder() {
}
//-----------------------------------------------------------------------
@Override
public Object get(String propertyName) {
switch (propertyName.hashCode()) {
case 121811856: // observables
return observables;
case 824041091: // nonObservables
return nonObservables;
case 779431844: // timeSeries
return timeSeries;
case -1022597040: // outputCurrencies
return outputCurrencies;
default:
throw new NoSuchElementException("Unknown property: " + propertyName);
}
}
@SuppressWarnings("unchecked")
@Override
public Builder set(String propertyName, Object newValue) {
switch (propertyName.hashCode()) {
case 121811856: // observables
this.observables = (Set<? extends ObservableId>) newValue;
break;
case 824041091: // nonObservables
this.nonObservables = (Set<? extends MarketDataId<?>>) newValue;
break;
case 779431844: // timeSeries
this.timeSeries = (Set<? extends ObservableId>) newValue;
break;
case -1022597040: // outputCurrencies
this.outputCurrencies = (Set<Currency>) newValue;
break;
default:
throw new NoSuchElementException("Unknown property: " + propertyName);
}
return this;
}
@Override
public Builder set(MetaProperty<?> property, Object value) {
super.set(property, value);
return this;
}
@Override
public Builder setString(String propertyName, String value) {
setString(meta().metaProperty(propertyName), value);
return this;
}
@Override
public Builder setString(MetaProperty<?> property, String value) {
super.setString(property, value);
return this;
}
@Override
public Builder setAll(Map<String, ? extends Object> propertyValueMap) {
super.setAll(propertyValueMap);
return this;
}
@Override
public MarketDataRequirements build() {
return new MarketDataRequirements(
observables,
nonObservables,
timeSeries,
outputCurrencies);
}
//-----------------------------------------------------------------------
@Override
public String toString() {
StringBuilder buf = new StringBuilder(160);
buf.append("MarketDataRequirements.Builder{");
buf.append("observables").append('=').append(JodaBeanUtils.toString(observables)).append(',').append(' ');
buf.append("nonObservables").append('=').append(JodaBeanUtils.toString(nonObservables)).append(',').append(' ');
buf.append("timeSeries").append('=').append(JodaBeanUtils.toString(timeSeries)).append(',').append(' ');
buf.append("outputCurrencies").append('=').append(JodaBeanUtils.toString(outputCurrencies));
buf.append('}');
return buf.toString();
}
}
///CLOVER:ON
//-------------------------- AUTOGENERATED END --------------------------
}