com.opengamma.strata.report.framework.expression.BeanTokenEvaluator.java Source code

Java tutorial

Introduction

Here is the source code for com.opengamma.strata.report.framework.expression.BeanTokenEvaluator.java

Source

/**
 * Copyright (C) 2015 - present by OpenGamma Inc. and the OpenGamma group of companies
 * 
 * Please see distribution for license.
 */
package com.opengamma.strata.report.framework.expression;

import java.util.List;
import java.util.Optional;
import java.util.Set;

import org.joda.beans.Bean;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.opengamma.strata.calc.runner.CalculationFunctions;
import com.opengamma.strata.market.amount.LegAmount;
import com.opengamma.strata.market.amount.LegAmounts;

/**
 * Evaluates a token against a bean to produce another object.
 * <p>
 * The token must be the name of one of the properties of the bean and the result is the value of the property.
 * <p>
 * There is special handling of beans with a single property. The name of the property can be omitted from
 * the expression if the bean only has one property.
 * <p>
 * For example, the bean {@link LegAmounts} has a single property named {@code amounts} containing a list of
 * {@link LegAmount} instances. The following expressions are equivalent and both return the first amount in the
 * list. {@code LegInitialNotional} is a measure that produces {@code LegAmounts}.
 * <pre>
 *   Measures.LegInitialNotional.0
 *   Measures.LegInitialNotional.amounts.0
 * </pre>
 * <p>
 * If the token matches the property then the default behaviour applies; the property value is returned and
 * the remaining tokens do not include the property token. If the token doesn't match the property, the property value
 * is returned but the token isn't consumed. i.e. the remaining tokens returned from {@link #evaluate} include
 * the first token.
 */
public class BeanTokenEvaluator extends TokenEvaluator<Bean> {

    @Override
    public Class<Bean> getTargetType() {
        return Bean.class;
    }

    @Override
    public Set<String> tokens(Bean bean) {
        if (bean.propertyNames().size() == 1) {
            String singlePropertyName = Iterables.getOnlyElement(bean.propertyNames());
            Object propertyValue = bean.property(singlePropertyName).get();
            Set<String> valueTokens = ValuePathEvaluator.tokens(propertyValue);

            return ImmutableSet.<String>builder().add(singlePropertyName).addAll(valueTokens).build();
        } else {
            return bean.propertyNames();
        }
    }

    @Override
    public EvaluationResult evaluate(Bean bean, CalculationFunctions functions, String firstToken,
            List<String> remainingTokens) {

        Optional<String> propertyName = bean.propertyNames().stream().filter(p -> p.equalsIgnoreCase(firstToken))
                .findFirst();

        if (propertyName.isPresent()) {
            Object propertyValue = bean.property(propertyName.get()).get();

            return propertyValue != null ? EvaluationResult.success(propertyValue, remainingTokens)
                    : EvaluationResult.failure("No value available for property '{}'", firstToken);
        }
        // The bean has a single property which doesn't match the token.
        // Return the property value without consuming any tokens.
        // This allows skipping over properties when the bean only has a single property.
        if (bean.propertyNames().size() == 1) {
            String singlePropertyName = Iterables.getOnlyElement(bean.propertyNames());
            Object propertyValue = bean.property(singlePropertyName).get();
            List<String> tokens = ImmutableList.<String>builder().add(firstToken).addAll(remainingTokens).build();

            return propertyValue != null ? EvaluationResult.success(propertyValue, tokens)
                    : EvaluationResult.failure("No value available for property '{}'", firstToken);
        }
        return invalidTokenFailure(bean, firstToken);
    }

}