Package com.opengamma.financial.currency

Source Code of com.opengamma.financial.currency.AbstractCurrencyMatrixSourcingFunction$DetermineResults

/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.financial.currency;

import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.opengamma.engine.ComputationTarget;
import com.opengamma.engine.ComputationTargetSpecification;
import com.opengamma.engine.function.AbstractFunction;
import com.opengamma.engine.function.FunctionCompilationContext;
import com.opengamma.engine.function.FunctionExecutionContext;
import com.opengamma.engine.function.FunctionInputs;
import com.opengamma.engine.target.ComputationTargetType;
import com.opengamma.engine.value.ComputedValue;
import com.opengamma.engine.value.ValueProperties;
import com.opengamma.engine.value.ValuePropertyNames;
import com.opengamma.engine.value.ValueRequirement;
import com.opengamma.engine.value.ValueSpecification;
import com.opengamma.financial.currency.CurrencyMatrixValue.CurrencyMatrixCross;
import com.opengamma.financial.currency.CurrencyMatrixValue.CurrencyMatrixFixed;
import com.opengamma.financial.currency.CurrencyMatrixValue.CurrencyMatrixValueRequirement;
import com.opengamma.timeseries.DoubleTimeSeries;
import com.opengamma.util.money.Currency;

/**
* Injects values from a {@link CurrencyMatrix} into a dependency graph to satisfy the requirements generated by {@link CurrencyMatrixLookupFunction}.
*/
public abstract class AbstractCurrencyMatrixSourcingFunction extends AbstractFunction.NonCompiledInvoker {

  /**
   * Property name when applied to a {@link CurrencyMatrix} target to allow the counter currency to be identified.
   */
  protected static final String SOURCE_CURRENCY_PROPERTY = "Counter";

  /**
   * Property name when applied to a {@link CurrencyMatrix} target to allow the base currency to be identified.
   */
  protected static final String TARGET_CURRENCY_PROPERTY = "Base";

  /**
   * Property name for tagging input values.
   */
  private static final String SOURCE_CURRENCY_TAG = ValuePropertyNames.OUTPUT_RESERVED_PREFIX + SOURCE_CURRENCY_PROPERTY;

  /**
   * Property name for tagging input values.
   */
  private static final String TARGET_CURRENCY_TAG = ValuePropertyNames.OUTPUT_RESERVED_PREFIX + TARGET_CURRENCY_PROPERTY;

  private final String _valueRequirementName;

  protected AbstractCurrencyMatrixSourcingFunction(final String valueRequirementName) {
    _valueRequirementName = valueRequirementName;
  }

  protected String getValueRequirementName() {
    return _valueRequirementName;
  }

  @Override
  public ComputationTargetType getTargetType() {
    return CurrencyMatrixResolver.TYPE;
  }

  @Override
  public Set<ValueSpecification> getResults(final FunctionCompilationContext context, final ComputationTarget target) {
    final String valueRequirementName = getValueRequirementName();
    final ComputationTargetSpecification targetSpec = target.toSpecification();
    final CurrencyMatrix matrix = (CurrencyMatrix) target.getValue();
    final Collection<Currency> sourceCurrencies = matrix.getSourceCurrencies();
    final Collection<Currency> targetCurrencies = matrix.getTargetCurrencies();
    final Set<ValueSpecification> results = Sets.<ValueSpecification>newHashSetWithExpectedSize(sourceCurrencies.size() * targetCurrencies.size());
    final ValueProperties.Builder properties = createValueProperties();
    for (Currency sourceCurrency : sourceCurrencies) {
      properties.withoutAny(SOURCE_CURRENCY_PROPERTY).with(SOURCE_CURRENCY_PROPERTY, sourceCurrency.getCode());
      for (Currency targetCurrency : targetCurrencies) {
        if (!targetCurrency.equals(sourceCurrency)) {
          final CurrencyMatrixValue conversion = matrix.getConversion(sourceCurrency, targetCurrency);
          if (conversion != null) {
            results.add(new ValueSpecification(valueRequirementName, targetSpec, properties.withoutAny(TARGET_CURRENCY_PROPERTY).with(TARGET_CURRENCY_PROPERTY, targetCurrency.getCode()).get()));
          }
        }
      }
    }
    return results;
  }

  protected ValueRequirement tagInput(final ValueRequirement requirement, final Currency source, final Currency target) {
    return new ValueRequirement(requirement.getValueName(), requirement.getTargetReference(), requirement.getConstraints().copy().with(SOURCE_CURRENCY_TAG, source.getCode())
        .withOptional(SOURCE_CURRENCY_TAG).with(TARGET_CURRENCY_TAG, target.getCode()).withOptional(TARGET_CURRENCY_TAG).get());
  }

  protected abstract boolean getRequirements(FunctionCompilationContext context, ValueRequirement desiredValue, CurrencyMatrix matrix, Set<ValueRequirement> requirements, Currency source,
      Currency target);

  @Override
  public Set<ValueRequirement> getRequirements(final FunctionCompilationContext context, final ComputationTarget target, final ValueRequirement desiredValue) {
    final CurrencyMatrix matrix = (CurrencyMatrix) target.getValue();
    final Currency sourceCurrency = Currency.of(desiredValue.getConstraint(SOURCE_CURRENCY_PROPERTY));
    final Currency targetCurrency = Currency.of(desiredValue.getConstraint(TARGET_CURRENCY_PROPERTY));
    final Set<ValueRequirement> requirements = new HashSet<ValueRequirement>();
    if (getRequirements(context, desiredValue, matrix, requirements, sourceCurrency, targetCurrency)) {
      return requirements;
    } else {
      return null;
    }
  }

  private static final class DetermineResults implements CurrencyMatrixValueVisitor<Boolean> {

    private final CurrencyMatrix _matrix;
    private final Collection<Currency> _sourceCurrencies;
    private final Collection<Currency> _targetCurrencies;
    private final Map<Currency, Map<Currency, Boolean>> _valid;

    private Currency _currentSourceCurrency;
    private Currency _currentTargetCurrency;

    public DetermineResults(final CurrencyMatrix matrix) {
      _matrix = matrix;
      _sourceCurrencies = _matrix.getSourceCurrencies();
      _targetCurrencies = _matrix.getTargetCurrencies();
      _valid = Maps.newHashMapWithExpectedSize(_sourceCurrencies.size());
    }

    private void input(final Currency source, final Currency target, final Boolean status) {
      Map<Currency, Boolean> target2status = _valid.get(source);
      if (target2status == null) {
        target2status = Maps.newHashMapWithExpectedSize(_targetCurrencies.size());
        _valid.put(source, target2status);
      }
      target2status.put(target, status);
    }

    public void present(final Currency source, final Currency target) {
      input(source, target, Boolean.TRUE);
    }

    public void missing(final Currency source, final Currency target) {
      input(source, target, Boolean.FALSE);
    }

    public boolean hasInputFor(final Currency source, final Currency target) {
      if (source.equals(target)) {
        return false;
      }
      Map<Currency, Boolean> target2status = _valid.get(source);
      if (target2status != null) {
        Boolean status = target2status.get(target);
        if (status != null) {
          return status;
        }
      }
      final CurrencyMatrixValue conversion = _matrix.getConversion(source, target);
      if (conversion == null) {
        missing(source, target);
        return false;
      }
      _currentSourceCurrency = source;
      _currentTargetCurrency = target;
      return conversion.accept(this);
    }

    // CurrentMatrixVisitor

    @Override
    public Boolean visitFixed(CurrencyMatrixFixed fixedValue) {
      present(_currentSourceCurrency, _currentTargetCurrency);
      return Boolean.TRUE;
    }

    @Override
    public Boolean visitValueRequirement(CurrencyMatrixValueRequirement uniqueId) {
      return Boolean.FALSE;
    }

    @Override
    public Boolean visitCross(CurrencyMatrixCross cross) {
      final Currency sourceCurrency = _currentSourceCurrency;
      final Currency targetCurrency = _currentTargetCurrency;
      // Declare as missing to avoid a loop forming
      missing(sourceCurrency, targetCurrency);
      boolean result = hasInputFor(sourceCurrency, cross.getCrossCurrency()) && hasInputFor(cross.getCrossCurrency(), targetCurrency);
      if (result) {
        // Is present after all
        present(sourceCurrency, targetCurrency);
      }
      return result;
    }

  }

  @Override
  public Set<ValueSpecification> getResults(final FunctionCompilationContext context, final ComputationTarget target, final Map<ValueSpecification, ValueRequirement> inputs) {
    final String valueRequirementName = getValueRequirementName();
    final ComputationTargetSpecification targetSpec = target.toSpecification();
    final CurrencyMatrix matrix = (CurrencyMatrix) target.getValue();
    final DetermineResults resultBuilder = new DetermineResults(matrix);
    for (ValueRequirement input : inputs.values()) {
      final Currency sourceCurrency = Currency.of(input.getConstraint(SOURCE_CURRENCY_TAG));
      final Currency targetCurrency = Currency.of(input.getConstraint(TARGET_CURRENCY_TAG));
      resultBuilder.present(sourceCurrency, targetCurrency);
    }
    final Set<ValueSpecification> results = Sets.newHashSetWithExpectedSize(resultBuilder._sourceCurrencies.size() * resultBuilder._targetCurrencies.size());
    final ValueProperties.Builder properties = createValueProperties();
    for (Currency sourceCurrency : resultBuilder._sourceCurrencies) {
      properties.withoutAny(SOURCE_CURRENCY_PROPERTY).with(SOURCE_CURRENCY_PROPERTY, sourceCurrency.getCode());
      for (Currency targetCurrency : resultBuilder._targetCurrencies) {
        if (resultBuilder.hasInputFor(sourceCurrency, targetCurrency)) {
          results.add(new ValueSpecification(valueRequirementName, targetSpec, properties.withoutAny(TARGET_CURRENCY_PROPERTY).with(TARGET_CURRENCY_PROPERTY, targetCurrency.getCode()).get()));
        }
      }
    }
    return results;
  }

  @Override
  public boolean canHandleMissingInputs() {
    return true;
  }

  protected abstract Object getRate(CurrencyMatrix matrix, ValueRequirement desiredValue, FunctionExecutionContext executionContext, FunctionInputs inputs, Currency source, Currency target);

  @Override
  public Set<ComputedValue> execute(final FunctionExecutionContext executionContext, final FunctionInputs inputs, final ComputationTarget target, final Set<ValueRequirement> desiredValues) {
    final CurrencyMatrix matrix = (CurrencyMatrix) target.getValue();
    final Set<ComputedValue> result = Sets.newHashSetWithExpectedSize(desiredValues.size());
    for (ValueRequirement desiredValue : desiredValues) {
      final Currency sourceCurrency = Currency.of(desiredValue.getConstraint(SOURCE_CURRENCY_PROPERTY));
      final Currency targetCurrency = Currency.of(desiredValue.getConstraint(TARGET_CURRENCY_PROPERTY));
      final ValueSpecification valueSpec = new ValueSpecification(desiredValue.getValueName(), target.toSpecification(), desiredValue.getConstraints());
      final Object resultValue = getRate(matrix, desiredValue, executionContext, inputs, sourceCurrency, targetCurrency);
      if (resultValue != null) {
        result.add(new ComputedValue(valueSpec, resultValue));
      }
    }
    return result;
  }

  protected static Object createCrossRate(final Object r1, final Object r2) {
    if ((r1 == null) || (r2 == null)) {
      // Missing input case; reported elsewhere
      return null;
    }
    if (r1 instanceof Double) {
      if (r2 instanceof Double) {
        return (Double) r1 * (Double) r2;
      } else if (r2 instanceof DoubleTimeSeries) {
        return ((DoubleTimeSeries<?>) r2).multiply((Double) r1);
      } else {
        throw new IllegalArgumentException();
      }
    } else if (r1 instanceof DoubleTimeSeries) {
      if (r2 instanceof Double) {
        return ((DoubleTimeSeries<?>) r1).multiply((Double) r2);
      } else if (r2 instanceof DoubleTimeSeries) {
        return ((DoubleTimeSeries<?>) r1).multiply((DoubleTimeSeries<?>) r2);
      } else {
        throw new IllegalArgumentException();
      }
    } else {
      throw new IllegalArgumentException();
    }
  }

}
TOP

Related Classes of com.opengamma.financial.currency.AbstractCurrencyMatrixSourcingFunction$DetermineResults

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.