Java tutorial
/** * Copyright (C) 2015 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.strata.engine.config.pricing; import java.util.Map; import java.util.NoSuchElementException; import java.util.Optional; 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.ImmutableConstructor; 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.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; import com.opengamma.strata.basics.CalculationTarget; import com.opengamma.strata.collect.ArgChecker; import com.opengamma.strata.engine.config.FunctionConfig; import com.opengamma.strata.engine.config.Measure; /** * A rule which specifies the function group and parameters that should be used to calculate the value * of a measure for a target. * <p> * A rule matches a calculation if * <ul> * <li>The calculation target is an instance of the target type</li> * <li>The set of measures in the rule contains the measure, or the rule has an empty set of measures, * meaning it handles all measures</li> * <li>The function group has a function to calculate the measure for the target</li> * </ul> * * @param <T> the type of the calculation target */ @BeanDefinition(builderScope = "private", constructorScope = "package") public final class PricingRule<T extends CalculationTarget> implements ImmutableBean { // Fields that define whether the rule applies to a calculation for a target and measure ----------------------------- /** The type of target this rule applies to. */ @PropertyDefinition(validate = "notNull", get = "private") private final Class<T> targetType; /** The measures this rule applies to. An empty set means the rule applies to all measures. */ @PropertyDefinition(validate = "notNull", get = "private") private final ImmutableSet<Measure> measures; // TODO Expression to validate against arbitrary properties of the target // Fields that define the behaviour when the rule matches ------------------------------------------------------------ /** The the function group with configuration parameters used for calculations that satisfy this rule. */ @PropertyDefinition(validate = "notNull", get = "private") private final FunctionGroup<T> functionGroup; /** * The arguments used by the function group when creating functions. These arguments are specified by * the pricing rule. */ @PropertyDefinition(validate = "notNull", get = "private") private final ImmutableMap<String, Object> arguments; /** The function group and arguments bundled up together. */ private final ConfiguredFunctionGroup configuredFunctionGroup; /** * Returns a builder for building pricing rules. * * @param targetType the type of the calculation target * @param <T> the type of the calculation target * @return a builder for building pricing rules */ public static <T extends CalculationTarget> PricingRuleBuilder<T> builder(Class<T> targetType) { return new PricingRuleBuilder<>(targetType); } // package-private constructor used by PricingRuleBuilder @ImmutableConstructor PricingRule(Class<T> targetType, Set<Measure> measures, FunctionGroup<T> functionGroup, Map<String, Object> arguments) { this.targetType = ArgChecker.notNull(targetType, "targetType"); this.measures = ImmutableSet.copyOf(measures); this.functionGroup = ArgChecker.notNull(functionGroup, "functionGroup"); this.arguments = ImmutableMap.copyOf(arguments); this.configuredFunctionGroup = ConfiguredFunctionGroup.of(this.functionGroup, this.arguments); } /** * Returns a function group to calculate a value of the measure for the target if this rule applies to the target. * * @param target a target * @param measure a measure * @return a function group to calculate a value of the measure for the target if this rule applies to the target */ public Optional<ConfiguredFunctionGroup> functionGroup(CalculationTarget target, Measure measure) { Optional<FunctionConfig<T>> functionConfig = functionGroup.functionConfig(target, measure); return targetType.isInstance(target) && handlesMeasure(measure) && functionConfig.isPresent() ? Optional.of(configuredFunctionGroup) : Optional.empty(); } /** * Returns the set of measures configured for a calculation target. * * @param target a target * @return the set of measures configured by this rule */ public ImmutableSet<Measure> configuredMeasures(CalculationTarget target) { if (!targetType.isInstance(target)) { return ImmutableSet.of(); } Set<Measure> measuresConfigured = functionGroup.configuredMeasures(target); if (!measures.isEmpty()) { measuresConfigured = Sets.intersection(measures, functionGroup.configuredMeasures(target)); } return ImmutableSet.copyOf(measuresConfigured); } /** * Returns true if this rule handles the measure. * <p> * A rule handles a measure if {@link #measures} is empty or if it contains the measure. * * @param measure a measure * @return true if this rule handles the measure */ private boolean handlesMeasure(Measure measure) { return measures.isEmpty() || measures.contains(measure); } //------------------------- AUTOGENERATED START ------------------------- ///CLOVER:OFF /** * The meta-bean for {@code PricingRule}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static PricingRule.Meta meta() { return PricingRule.Meta.INSTANCE; } /** * The meta-bean for {@code PricingRule}. * @param <R> the bean's generic type * @param cls the bean's generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static <R extends CalculationTarget> PricingRule.Meta<R> metaPricingRule(Class<R> cls) { return PricingRule.Meta.INSTANCE; } static { JodaBeanUtils.registerMetaBean(PricingRule.Meta.INSTANCE); } @SuppressWarnings("unchecked") @Override public PricingRule.Meta<T> metaBean() { return PricingRule.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 the type of target this rule applies to. * @return the value of the property, not null */ private Class<T> getTargetType() { return targetType; } //----------------------------------------------------------------------- /** * Gets the measures this rule applies to. An empty set means the rule applies to all measures. * @return the value of the property, not null */ private ImmutableSet<Measure> getMeasures() { return measures; } //----------------------------------------------------------------------- /** * Gets the the function group with configuration parameters used for calculations that satisfy this rule. * @return the value of the property, not null */ private FunctionGroup<T> getFunctionGroup() { return functionGroup; } //----------------------------------------------------------------------- /** * Gets the arguments used by the function group when creating functions. These arguments are specified by * the pricing rule. * @return the value of the property, not null */ private ImmutableMap<String, Object> getArguments() { return arguments; } //----------------------------------------------------------------------- @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { PricingRule<?> other = (PricingRule<?>) obj; return JodaBeanUtils.equal(getTargetType(), other.getTargetType()) && JodaBeanUtils.equal(getMeasures(), other.getMeasures()) && JodaBeanUtils.equal(getFunctionGroup(), other.getFunctionGroup()) && JodaBeanUtils.equal(getArguments(), other.getArguments()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getTargetType()); hash = hash * 31 + JodaBeanUtils.hashCode(getMeasures()); hash = hash * 31 + JodaBeanUtils.hashCode(getFunctionGroup()); hash = hash * 31 + JodaBeanUtils.hashCode(getArguments()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(160); buf.append("PricingRule{"); buf.append("targetType").append('=').append(getTargetType()).append(',').append(' '); buf.append("measures").append('=').append(getMeasures()).append(',').append(' '); buf.append("functionGroup").append('=').append(getFunctionGroup()).append(',').append(' '); buf.append("arguments").append('=').append(JodaBeanUtils.toString(getArguments())); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code PricingRule}. * @param <T> the type */ public static final class Meta<T extends CalculationTarget> extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code targetType} property. */ @SuppressWarnings({ "unchecked", "rawtypes" }) private final MetaProperty<Class<T>> targetType = DirectMetaProperty.ofImmutable(this, "targetType", PricingRule.class, (Class) Class.class); /** * The meta-property for the {@code measures} property. */ @SuppressWarnings({ "unchecked", "rawtypes" }) private final MetaProperty<ImmutableSet<Measure>> measures = DirectMetaProperty.ofImmutable(this, "measures", PricingRule.class, (Class) ImmutableSet.class); /** * The meta-property for the {@code functionGroup} property. */ @SuppressWarnings({ "unchecked", "rawtypes" }) private final MetaProperty<FunctionGroup<T>> functionGroup = DirectMetaProperty.ofImmutable(this, "functionGroup", PricingRule.class, (Class) FunctionGroup.class); /** * The meta-property for the {@code arguments} property. */ @SuppressWarnings({ "unchecked", "rawtypes" }) private final MetaProperty<ImmutableMap<String, Object>> arguments = DirectMetaProperty.ofImmutable(this, "arguments", PricingRule.class, (Class) ImmutableMap.class); /** * The meta-properties. */ private final Map<String, MetaProperty<?>> metaPropertyMap$ = new DirectMetaPropertyMap(this, null, "targetType", "measures", "functionGroup", "arguments"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty<?> metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 486622315: // targetType return targetType; case -976812331: // measures return measures; case 2031434119: // functionGroup return functionGroup; case -2035517098: // arguments return arguments; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder<? extends PricingRule<T>> builder() { return new PricingRule.Builder<T>(); } @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public Class<? extends PricingRule<T>> beanType() { return (Class) PricingRule.class; } @Override public Map<String, MetaProperty<?>> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code targetType} property. * @return the meta-property, not null */ public MetaProperty<Class<T>> targetType() { return targetType; } /** * The meta-property for the {@code measures} property. * @return the meta-property, not null */ public MetaProperty<ImmutableSet<Measure>> measures() { return measures; } /** * The meta-property for the {@code functionGroup} property. * @return the meta-property, not null */ public MetaProperty<FunctionGroup<T>> functionGroup() { return functionGroup; } /** * The meta-property for the {@code arguments} property. * @return the meta-property, not null */ public MetaProperty<ImmutableMap<String, Object>> arguments() { return arguments; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 486622315: // targetType return ((PricingRule<?>) bean).getTargetType(); case -976812331: // measures return ((PricingRule<?>) bean).getMeasures(); case 2031434119: // functionGroup return ((PricingRule<?>) bean).getFunctionGroup(); case -2035517098: // arguments return ((PricingRule<?>) bean).getArguments(); } 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 PricingRule}. * @param <T> the type */ private static final class Builder<T extends CalculationTarget> extends DirectFieldsBeanBuilder<PricingRule<T>> { private Class<T> targetType; private Set<Measure> measures = ImmutableSet.of(); private FunctionGroup<T> functionGroup; private Map<String, Object> arguments = ImmutableMap.of(); /** * Restricted constructor. */ private Builder() { } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 486622315: // targetType return targetType; case -976812331: // measures return measures; case 2031434119: // functionGroup return functionGroup; case -2035517098: // arguments return arguments; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @SuppressWarnings("unchecked") @Override public Builder<T> set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 486622315: // targetType this.targetType = (Class<T>) newValue; break; case -976812331: // measures this.measures = (Set<Measure>) newValue; break; case 2031434119: // functionGroup this.functionGroup = (FunctionGroup<T>) newValue; break; case -2035517098: // arguments this.arguments = (Map<String, Object>) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder<T> set(MetaProperty<?> property, Object value) { super.set(property, value); return this; } @Override public Builder<T> setString(String propertyName, String value) { setString(meta().metaProperty(propertyName), value); return this; } @Override public Builder<T> setString(MetaProperty<?> property, String value) { super.setString(property, value); return this; } @Override public Builder<T> setAll(Map<String, ? extends Object> propertyValueMap) { super.setAll(propertyValueMap); return this; } @Override public PricingRule<T> build() { return new PricingRule<T>(targetType, measures, functionGroup, arguments); } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(160); buf.append("PricingRule.Builder{"); buf.append("targetType").append('=').append(JodaBeanUtils.toString(targetType)).append(',').append(' '); buf.append("measures").append('=').append(JodaBeanUtils.toString(measures)).append(',').append(' '); buf.append("functionGroup").append('=').append(JodaBeanUtils.toString(functionGroup)).append(',') .append(' '); buf.append("arguments").append('=').append(JodaBeanUtils.toString(arguments)); buf.append('}'); return buf.toString(); } } ///CLOVER:ON //-------------------------- AUTOGENERATED END -------------------------- }