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

import java.util.Set;
import java.util.stream.Collectors;

import org.joda.beans.Bean;

import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multiset;
import com.opengamma.strata.basics.PayReceive;
import com.opengamma.strata.basics.currency.Currency;
import com.opengamma.strata.collect.result.Result;
import com.opengamma.strata.finance.rate.swap.SwapLegType;

/**
 * 
 */
public class IterableTokenEvaluator extends TokenEvaluator<Iterable<?>> {

  private static final Set<Class<?>> SUPPORTED_FIELD_TYPES = ImmutableSet.of(
      Currency.class,
      SwapLegType.class,
      PayReceive.class);

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

  @Override
  public Set<String> tokens(Iterable<?> iterable) {
    Multiset<String> tokens = HashMultiset.create();
    int index = 1;
    for (Object item : iterable) {
      tokens.add(String.valueOf(index++));
      tokens.addAll(fieldValues(item));
    }
    return tokens.stream()
        .filter(token -> tokens.count(token) == 1)
        .collect(Collectors.toSet());
  }

  @Override
  public Result<?> evaluate(Iterable<?> iterable, String token) {
    for (Object item : iterable) {
      if (!fieldValues(item).contains(token)) {
        continue;
      }
      if (!tokens(iterable).contains(token)) {
        return ambiguousTokenFailure(iterable, token);
      }
      return Result.success(item);
    }
    return invalidTokenFailure(iterable, token);
  }

  //-------------------------------------------------------------------------
  private Set<String> fieldValues(Object object) {
    if (!(object instanceof Bean)) {
      return ImmutableSet.of();
    }
    Bean bean = (Bean) object;
    return bean.propertyNames().stream()
        .map(name -> bean.property(name))
        .filter(p -> SUPPORTED_FIELD_TYPES.contains(p.metaProperty().propertyType()))
        .map(p -> p.get())
        .filter(v -> v != null)
        .map(v -> v.toString().toLowerCase())
        .collect(Collectors.toSet());
  }

}

@@ -236,16 +236,66 @@
 ctors;%0A%0A
+import org.apache.commons.lang3.math.NumberUtils;%0A
 import o
@@ -314,16 +314,16 @@
 s.Bean;%0A
-
 %0Aimport 
@@ -405,24 +405,68 @@
 mutableSet;%0A
+import com.google.common.collect.Iterables;%0A
 import com.g
@@ -1159,17 +1159,17 @@
 index = 
-1
+0
 ;%0A    fo
@@ -1411,32 +1411,32 @@
  %7D%0A%0A  @Override%0A
-
   public Result%3C
@@ -1481,24 +1481,294 @@
 ng token) %7B%0A
+    if (NumberUtils.isDigits(token)) %7B%0A      int index = Integer.parseInt(token);%0A      try %7B%0A        return Result.success(Iterables.get(iterable, index));%0A      %7D catch (IndexOutOfBoundsException e) %7B%0A        return invalidTokenFailure(iterable, token);%0A      %7D%0A    %7D%0A
     for (Obj

support use of indices on iterable types