@SuppressWarnings("unchecked")
  static Iterator<MarkerRange.Builder> add(
      Range constraint, List<FieldPartitioner> fps,
      Iterator<MarkerRange.Builder> inner) {

    Iterator<MarkerRange.Builder> current = inner;
    List<Pair<String, Range>> compatible = Lists.newArrayList();
    for (FieldPartitioner fp : fps) {
      Predicate<?> projected = fp.project(constraint);
      if (projected instanceof In) {
        current = addProjected(projected, fp.getName(), current);
      } else if (projected instanceof Range) {
        compatible.add(Pair.of(fp.getName(), (Range) projected));
      }
      // otherwise, all fields are included, so don't add anything
    }

    if (compatible.size() < 1) {
      return current;
    } else if (compatible.size() == 1) {
      Pair<String, Range> pair = compatible.get(0);
      return addProjected((Predicate<?>) pair.second(), pair.first(), current);
    } else {
      return new RangeGroupIterator(constraint, compatible, current);
    }
  }
@ SuppressWarnings ( "unchecked" ) static Iterator < MarkerRange . Builder > add ( Range constraint , List < FieldPartitioner > fps , Iterator < MarkerRange . Builder > inner ) { Iterator < MarkerRange . Builder > current = inner ; List < Pair < String , Range > > compatible = Lists . newArrayList ( ) ; for ( FieldPartitioner fp : fps ) { Predicate < ? > projected = fp . project ( constraint ) ; if ( projected instanceof In ) { current = addProjected ( projected , fp . getName ( ) , current ) ; } else if ( projected instanceof Range ) { compatible . add ( Pair . of ( fp . getName ( ) , ( Range ) projected ) ) ; } } if ( compatible . size ( ) < 1 ) { return current ; } else if ( compatible . size ( ) == 1 ) { Pair < String , Range > pair = compatible . get ( 0 ) ; return addProjected ( ( Predicate < ? > ) pair . second ( ) , pair . first ( ) , current ) ; } else { return new RangeGroupIterator ( constraint , compatible , current ) ; } }
Convenience function to add the correct wrapper {@link StackedIterator} to
the key range Iterator stack.

This method checks the projected constraints to ensure they are compatible
and can be used in a grouped iterator. The constraints that are not are
added as a separate {@code StackedIterator}. For example, constraints
projected by {@link org.kitesdk.data.spi.partition.ListFieldPartitioner} are
"in" constraints and can't be grouped with ranges.

@param constraint A "range" constraint for the <em>source</em> values
@param fps A List of FieldPartitioners with the same source field
@param inner An {@code Iterator} to wrap
@return A key range Iterator