/**
   * iterator over the Tokens in the given ring, starting with the token for the node owning start
   * (which does not have to be a Token in the ring)
   *
   * @param includeMin True if the minimum token should be returned in the ring even if it has no
   *     owner.
   */
  public static Iterator<Token> ringIterator(
      final ArrayList<Token> ring, Token start, boolean includeMin) {
    if (ring.isEmpty())
      return includeMin
          ? Iterators.singletonIterator(StorageService.getPartitioner().getMinimumToken())
          : Iterators.<Token>emptyIterator();

    final boolean insertMin = includeMin && !ring.get(0).isMinimum();
    final int startIndex = firstTokenIndex(ring, start, insertMin);
    return new AbstractIterator<Token>() {
      int j = startIndex;

      protected Token computeNext() {
        if (j < -1) return endOfData();
        try {
          // return minimum for index == -1
          if (j == -1) return StorageService.getPartitioner().getMinimumToken();
          // return ring token for other indexes
          return ring.get(j);
        } finally {
          j++;
          if (j == ring.size()) j = insertMin ? -1 : 0;
          if (j == startIndex)
            // end iteration
            j = -2;
        }
      }
    };
  }