/*
 * Copyright (c) 2011 Google, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.google.common.truth;

import static com.google.common.base.Preconditions.checkArgument;

import java.util.Arrays;
import java.util.Iterator;

/**
 * @author Kevin Bourrillion
 */
public class IterableSubject<S extends IterableSubject<S, T, C>, T, C extends Iterable<T>> extends Subject<S, C> {

  @SuppressWarnings({ "unchecked", "rawtypes" })
  public static <T, C extends Iterable<T>> IterableSubject<? extends IterableSubject<?, T, C>, T, C> create(
      FailureStrategy failureStrategy, Iterable<T> list) {
    return new IterableSubject(failureStrategy, list);
  }

  // TODO: Arguably this should even be package private
  protected IterableSubject(FailureStrategy failureStrategy, C list) {
    super(failureStrategy, list);
  }

  /**
   * Attests that the subject holds no more objects, or fails.
   */
  public void isEmpty() {
    if (getSubject().iterator().hasNext()) {
      fail("is empty");
    }
  }

  /**
   * Attests that the subject holds one or more objects, or fails
   */
  public void isNotEmpty() {
    if (!getSubject().iterator().hasNext()) {
      fail("is not empty");
    }
  }

  /**
   * Asserts that an Iterable has a specific size.
   */
  public final void hasSize(int expectedSize) {
    checkArgument(expectedSize >= 0, "expectedSize(%s) must be >= 0", expectedSize);
    int actualSize = iterablesSize(getSubject());
    if (actualSize != expectedSize) {
      failWithBadResults("has a size of", expectedSize, "is", actualSize);
    }
  }

  // TODO(user): Why can't we use Iterables.size() here?
  // It breaks //javatests/com/google/common/util:tests_validator for some reason
  private static int iterablesSize(Iterable<?> iterable) {
    int count = 0;
    for (Object unused : iterable) {
      count++;
    }
    return count;
  }

  /**
   * Asserts that the items are supplied in the order given by the iterable. If
   * the iterable under test and/or the {@code expectedItems} do not provide
   * iteration order guarantees (say, {@link Set<T>}s), this method may provide
   * unexpected results.  Consider using {@link #is(T)} in such cases, or using
   * collections and iterables that provide strong order guarantees.
   */
  public void iteratesAs(Iterable<?> expectedItems) {
    Iterator<T> actualItems = getSubject().iterator();
    for (Object expected : expectedItems) {
      if (!actualItems.hasNext()) {
        fail("iterates through", expectedItems);
      } else {
        Object actual = actualItems.next();
        if (actual == expected || actual != null && actual.equals(expected)) {
          continue;
        } else {
          fail("iterates through", expectedItems);
        }
      }
    }
    if (actualItems.hasNext()) {
      fail("iterates through", expectedItems);
    }
  }

  /**
   * @deprecated use {@link #iteratesAs(T...)}
   */
  @Deprecated
  public void iteratesOverSequence(Object... expectedItems) {
    iteratesAs(expectedItems);
  }

  /**
   * Asserts that the items are supplied in the order given by the iterable. If
   * the iterable under test does not provide iteration order guarantees (say,
   * a {@link Set<T>}), this method is not suitable for asserting that order.
   * Consider using {@link #is(T)}
   */
  public void iteratesAs(Object... expectedItems) {
    iteratesAs(Arrays.asList(expectedItems));
  }
}

@@ -690,16 +690,61 @@
 ument;%0A%0A
+import com.google.common.collect.Iterables;%0A%0A
 import j
@@ -1974,25 +1974,25 @@
 lSize = 
-i
+I
 terables
 Size(get
@@ -1979,25 +1979,26 @@
  = Iterables
-S
+.s
 ize(getSubje
@@ -2113,24 +2113,24 @@
 ctualSize);%0A
+
     %7D%0A  %7D%0A%0A 
@@ -2132,306 +2132,8 @@
  %7D%0A%0A
-  // TODO(user): Why can't we use Iterables.size() here?%0A  // It breaks //javatests/com/google/common/util:tests_validator for some reason%0A  private static int iterablesSize(Iterable%3C?%3E iterable) %7B%0A    int count = 0;%0A    for (Object unused : iterable) %7B%0A      count++;%0A    %7D%0A    return count;%0A  %7D%0A%0A
   /*

Use Iterables.size() in truth. ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=72566755