class BeanTokenEvaluator extends TokenEvaluator<Bean> {

  @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);
  }

}