com.opengamma.financial.currency.CurrencyMatrixLookupFunction.java Source code

Java tutorial

Introduction

Here is the source code for com.opengamma.financial.currency.CurrencyMatrixLookupFunction.java

Source

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

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;

import com.google.common.collect.ImmutableSet;
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.ComputationTargetRequirement;
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.ValueRequirementNames;
import com.opengamma.engine.value.ValueSpecification;
import com.opengamma.financial.analytics.timeseries.HistoricalTimeSeriesFunctionUtils;
import com.opengamma.id.ExternalId;
import com.opengamma.id.ExternalIdBundle;

/**
 * Rewrites a requirement to satisfy the currency requirements generated by {@link CurrencyConversionFunction} into one that will query a {@link CurrencyMatrix}.
 */
public class CurrencyMatrixLookupFunction extends AbstractFunction.NonCompiledInvoker {

    /**
     * Property name when applied to a {@link CurrencyPair} target to allow the matrix to be selected.
     */
    protected static final String CURRENCY_MATRIX_NAME_PROPERTY = "CurrencyMatrix";

    private final String _defaultCurrencyMatrixName;
    private final String[] _additionalProperties;

    public CurrencyMatrixLookupFunction(final String defaultCurrencyMatrixName) {
        _defaultCurrencyMatrixName = defaultCurrencyMatrixName;
        _additionalProperties = null;
    }

    public CurrencyMatrixLookupFunction(final String[] params) {
        _defaultCurrencyMatrixName = params[0];
        _additionalProperties = new String[params.length - 1];
        System.arraycopy(params, 1, _additionalProperties, 0, _additionalProperties.length);
    }

    @Override
    protected ValueProperties.Builder createValueProperties() {
        final ValueProperties.Builder properties = super.createValueProperties();
        if (_additionalProperties != null) {
            for (int i = 0; i < _additionalProperties.length; i += 2) {
                properties.with(_additionalProperties[i], _additionalProperties[i + 1]);
            }
        }
        return properties;
    }

    protected String getDefaultCurrencyMatrixName() {
        return _defaultCurrencyMatrixName;
    }

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

    private ValueSpecification createSpotRateResult(ComputationTargetSpecification targetSpec,
            ValueProperties properties) {
        return new ValueSpecification(ValueRequirementNames.SPOT_RATE, targetSpec, properties);
    }

    private ValueSpecification createHistoricalTimeSeriesResult(ComputationTargetSpecification targetSpec,
            ValueProperties properties) {
        properties = properties.copy().withAny(HistoricalTimeSeriesFunctionUtils.START_DATE_PROPERTY)
                .with(HistoricalTimeSeriesFunctionUtils.INCLUDE_START_PROPERTY,
                        HistoricalTimeSeriesFunctionUtils.NO_VALUE, HistoricalTimeSeriesFunctionUtils.YES_VALUE)
                .withAny(HistoricalTimeSeriesFunctionUtils.END_DATE_PROPERTY)
                .with(HistoricalTimeSeriesFunctionUtils.INCLUDE_END_PROPERTY,
                        HistoricalTimeSeriesFunctionUtils.NO_VALUE, HistoricalTimeSeriesFunctionUtils.YES_VALUE)
                .get();
        return new ValueSpecification(ValueRequirementNames.HISTORICAL_FX_TIME_SERIES, targetSpec, properties);
    }

    private ValueSpecification createTimeSeriesLatestResult(ComputationTargetSpecification targetSpec,
            ValueProperties properties) {
        return new ValueSpecification(ValueRequirementNames.HISTORICAL_TIME_SERIES_LATEST, targetSpec, properties);
    }

    @Override
    public Set<ValueSpecification> getResults(final FunctionCompilationContext context,
            final ComputationTarget target) {
        final ComputationTargetSpecification targetSpec = target.toSpecification();
        final ValueProperties properties = createValueProperties().withAny(CURRENCY_MATRIX_NAME_PROPERTY).get();
        return ImmutableSet.of(createSpotRateResult(targetSpec, properties),
                createHistoricalTimeSeriesResult(targetSpec, properties),
                createTimeSeriesLatestResult(targetSpec, properties));
    }

    @Override
    public Set<ValueRequirement> getRequirements(final FunctionCompilationContext context,
            final ComputationTarget target, final ValueRequirement desiredValue) {
        final CurrencyPair currencies = (CurrencyPair) target.getValue();
        final ValueProperties.Builder constraints = ValueProperties
                .with(AbstractCurrencyMatrixSourcingFunction.SOURCE_CURRENCY_PROPERTY,
                        currencies.getCounter().getCode())
                .with(AbstractCurrencyMatrixSourcingFunction.TARGET_CURRENCY_PROPERTY,
                        currencies.getBase().getCode());
        ExternalIdBundle matrixIdentifiers = null;
        if (desiredValue.getConstraints().getProperties() != null) {
            for (String constraintName : desiredValue.getConstraints().getProperties()) {
                if (ValuePropertyNames.FUNCTION.equals(constraintName)
                        || constraintName.startsWith(ValuePropertyNames.OUTPUT_RESERVED_PREFIX)) {
                    continue;
                }
                final Set<String> values = desiredValue.getConstraints().getValues(constraintName);
                if (CURRENCY_MATRIX_NAME_PROPERTY.equals(constraintName)) {
                    if (values.isEmpty()) {
                        matrixIdentifiers = ExternalId
                                .of(CurrencyMatrixResolver.IDENTIFIER_SCHEME, getDefaultCurrencyMatrixName())
                                .toBundle();
                    } else {
                        if (values.size() == 1) {
                            matrixIdentifiers = ExternalId
                                    .of(CurrencyMatrixResolver.IDENTIFIER_SCHEME, values.iterator().next())
                                    .toBundle();
                        } else {
                            final Collection<ExternalId> identifiers = new ArrayList<ExternalId>(values.size());
                            for (String matrixName : values) {
                                identifiers
                                        .add(ExternalId.of(CurrencyMatrixResolver.IDENTIFIER_SCHEME, matrixName));
                            }
                            matrixIdentifiers = ExternalIdBundle.of(identifiers);
                        }
                    }
                } else {
                    if (values.isEmpty()) {
                        constraints.withAny(constraintName);
                    } else {
                        constraints.with(constraintName, values);
                    }
                    if (desiredValue.getConstraints().isOptional(constraintName)) {
                        constraints.withOptional(constraintName);
                    }
                }
            }
        }
        if (matrixIdentifiers == null) {
            matrixIdentifiers = ExternalId
                    .of(CurrencyMatrixResolver.IDENTIFIER_SCHEME, getDefaultCurrencyMatrixName()).toBundle();
        }
        return Collections.singleton(new ValueRequirement(desiredValue.getValueName(),
                new ComputationTargetRequirement(CurrencyMatrixResolver.TYPE, matrixIdentifiers),
                constraints.get()));
    }

    @Override
    public Set<ValueSpecification> getResults(final FunctionCompilationContext context,
            final ComputationTarget target, final Map<ValueSpecification, ValueRequirement> inputs) {
        final Set<ValueSpecification> results = Sets.newHashSetWithExpectedSize(inputs.size());
        for (Map.Entry<ValueSpecification, ValueRequirement> inputEntry : inputs.entrySet()) {
            ValueProperties.Builder properties = createValueProperties();
            properties.with(CURRENCY_MATRIX_NAME_PROPERTY, inputEntry.getValue().getTargetReference()
                    .getRequirement().getIdentifiers().getValue(CurrencyMatrixResolver.IDENTIFIER_SCHEME));
            final ValueProperties inputProperties = inputEntry.getKey().getProperties();
            for (String propertyName : inputProperties.getProperties()) {
                if (!AbstractCurrencyMatrixSourcingFunction.SOURCE_CURRENCY_PROPERTY.equals(propertyName)
                        && !AbstractCurrencyMatrixSourcingFunction.TARGET_CURRENCY_PROPERTY.equals(propertyName)
                        && !ValuePropertyNames.FUNCTION.equals(propertyName)) {
                    final Set<String> values = inputProperties.getValues(propertyName);
                    if (values.isEmpty()) {
                        properties.withAny(propertyName);
                    } else {
                        properties.with(propertyName, values);
                    }
                }
            }
            results.add(new ValueSpecification(inputEntry.getKey().getValueName(), target.toSpecification(),
                    properties.get()));
        }
        return results;
    }

    @Override
    public Set<ComputedValue> execute(final FunctionExecutionContext executionContext, final FunctionInputs inputs,
            final ComputationTarget target, final Set<ValueRequirement> desiredValues) {
        final Set<ComputedValue> results = Sets.newHashSetWithExpectedSize(desiredValues.size());
        for (ValueRequirement desiredValue : desiredValues) {
            final Object input = inputs.getValue(desiredValue.getValueName());
            results.add(new ComputedValue(new ValueSpecification(desiredValue.getValueName(),
                    target.toSpecification(), desiredValue.getConstraints()), input));
        }
        return results;
    }

    public int getPriority() {
        if (getDefaultCurrencyMatrixName().contains(CurrencyMatrixConfigPopulator.SYNTHETIC_LIVE_DATA)) {
            return -1;
        }
        return 0;
    }

}