/** * Copyright (C) 2016 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.strata.calc.runner; import static com.opengamma.strata.collect.Guavate.toImmutableMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.stream.Stream; import com.opengamma.strata.basics.CalculationTarget; /** * The calculation functions. * <p> * This provides the complete set of functions that will be used in a calculation. * <p> * The default implementation is accessed by the static factory methods. * It matches the {@link CalculationFunction} by the type of the {@link CalculationTarget}. * As such, the default implementation is essentially a {@code Map} where the keys are the * target type {@code Class} that the function operates on. */ public interface CalculationFunctions { /** * Obtains an empty instance with no functions. * * @return the empty instance */ public static CalculationFunctions empty() { return DefaultCalculationFunctions.EMPTY; } /** * Obtains an instance from the specified functions. * <p> * This returns an implementation that matches the function by the type of the * target, as returned by {@link CalculationFunction#targetType()}. * The list will be converted to a {@code Map} keyed by the target type. * Each function must refer to a different target type. * * @param functions the functions * @return the calculation functions */ public static CalculationFunctions of(CalculationFunction<?>... functions) { return DefaultCalculationFunctions.of(Stream.of(functions).collect(toImmutableMap(fn -> fn.targetType()))); } /** * Obtains an instance from the specified functions. * <p> * This returns an implementation that matches the function by the type of the * target, as returned by {@link CalculationFunction#targetType()}. * The list will be converted to a {@code Map} keyed by the target type. * Each function must refer to a different target type. * * @param functions the functions * @return the calculation functions */ public static CalculationFunctions of(List<? extends CalculationFunction<?>> functions) { return DefaultCalculationFunctions.of(functions.stream().collect(toImmutableMap(fn -> fn.targetType()))); } /** * Obtains an instance from the specified functions. * <p> * This returns an implementation that matches the function by the type of the target. * When finding the matching function, the target type is looked up in the specified map. * The map will be validated to ensure the {@code Class} is consistent with * {@link CalculationFunction#targetType()}. * * @param functions the functions * @return the calculation functions */ public static CalculationFunctions of(Map<Class<?>, ? extends CalculationFunction<?>> functions) { return DefaultCalculationFunctions.of(functions); } //------------------------------------------------------------------------- /** * Gets the function that handles the specified target. * <p> * If no function is found, a suitable default that can perform no calculations is provided. * * @param <T> the target type * @param target the calculation target, such as a trade * @return the function */ public default <T extends CalculationTarget> CalculationFunction<? super T> getFunction(T target) { return findFunction(target).orElse(MissingConfigCalculationFunction.INSTANCE); } /** * Finds the function that handles the specified target. * <p> * If no function is found the result is empty. * * @param <T> the target type * @param target the calculation target, such as a trade * @return the function, empty if not found */ public abstract <T extends CalculationTarget> Optional<CalculationFunction<? super T>> findFunction(T target); /** * Returns a set of calculation functions which combines the functions in this set with the functions in another. * <p> * If both sets of functions contain a function for a target then the function from this set is returned. * * @param other another set of calculation functions * @return a set of calculation functions which combines the functions in this set with the functions in the other */ public default CalculationFunctions composedWith(CalculationFunctions other) { return CompositeCalculationFunctions.of(this, other); } /** * Returns a set of calculation functions which combines the functions in this set with some * derived calculation functions. * <p> * Each derived function calculates one measure for one type of target, possibly using other calculated measures * as inputs. * <p> * If any of the derived functions depend on each other they must be passed to this method in the correct * order to ensure their dependencies can be satisfied. For example, if there is a derived function * {@code fnA} which depends on the measure calculated by function {@code fnB} they must be passed to * this method in the order {@code fnB, fnA}. * * @param functions the functions * @return a set of calculation functions which combines the functions in this set with some * derived calculation functions */ public default CalculationFunctions composedWith(DerivedCalculationFunction<?, ?>... functions) { return new DerivedCalculationFunctions(this, functions); } }