001    /*
002     * Created on Sep 17, 2010
003     * 
004     * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
005     * the License. You may obtain a copy of the License at
006     * 
007     * http://www.apache.org/licenses/LICENSE-2.0
008     * 
009     * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
010     * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
011     * specific language governing permissions and limitations under the License.
012     * 
013     * Copyright @2010-2011 the original author or authors.
014     */
015    package org.fest.assertions.internal;
016    
017    import static org.fest.assertions.error.ConditionAndGroupGenericParameterTypeShouldBeTheSame.shouldBeSameGenericBetweenIterableAndCondition;
018    import static org.fest.assertions.error.ElementsShouldBe.elementsShouldBe;
019    import static org.fest.assertions.error.ElementsShouldBeAtLeast.elementsShouldBeAtLeast;
020    import static org.fest.assertions.error.ElementsShouldBeExactly.elementsShouldBeExactly;
021    import static org.fest.assertions.error.ElementsShouldHave.elementsShouldHave;
022    import static org.fest.assertions.error.ElementsShouldHaveAtLeast.elementsShouldHaveAtLeast;
023    import static org.fest.assertions.error.ElementsShouldHaveAtMost.elementsShouldHaveAtMost;
024    import static org.fest.assertions.error.ElementsShouldHaveExactly.elementsShouldHaveExactly;
025    import static org.fest.assertions.error.ElementsShouldNotBe.elementsShouldNotBe;
026    import static org.fest.assertions.error.ElementsShouldNotBeAtLeast.elementsShouldNotBeAtLeast;
027    import static org.fest.assertions.error.ElementsShouldNotBeAtMost.elementsShouldNotBeAtMost;
028    import static org.fest.assertions.error.ElementsShouldNotBeExactly.elementsShouldNotBeExactly;
029    import static org.fest.assertions.error.ElementsShouldNotHave.elementsShouldNotHave;
030    import static org.fest.assertions.error.ElementsShouldNotHaveAtLeast.elementsShouldNotHaveAtLeast;
031    import static org.fest.assertions.error.ElementsShouldNotHaveAtMost.elementsShouldNotHaveAtMost;
032    import static org.fest.assertions.error.ElementsShouldNotHaveExactly.elementsShouldNotHaveExactly;
033    import static org.fest.assertions.error.ShouldBeEmpty.shouldBeEmpty;
034    import static org.fest.assertions.error.ShouldBeNullOrEmpty.shouldBeNullOrEmpty;
035    import static org.fest.assertions.error.ShouldBeSubsetOf.shouldBeSubsetOf;
036    import static org.fest.assertions.error.ShouldContain.shouldContain;
037    import static org.fest.assertions.error.ShouldContainNull.shouldContainNull;
038    import static org.fest.assertions.error.ShouldContainOnly.shouldContainOnly;
039    import static org.fest.assertions.error.ShouldContainSequence.shouldContainSequence;
040    import static org.fest.assertions.error.ShouldEndWith.shouldEndWith;
041    import static org.fest.assertions.error.ShouldHaveSameSizeAs.shouldHaveSameSizeAs;
042    import static org.fest.assertions.error.ShouldHaveSize.shouldHaveSize;
043    import static org.fest.assertions.error.ShouldNotBeEmpty.shouldNotBeEmpty;
044    import static org.fest.assertions.error.ShouldNotContain.shouldNotContain;
045    import static org.fest.assertions.error.ShouldNotContainNull.shouldNotContainNull;
046    import static org.fest.assertions.error.ShouldNotHaveDuplicates.shouldNotHaveDuplicates;
047    import static org.fest.assertions.error.ShouldStartWith.shouldStartWith;
048    import static org.fest.assertions.internal.CommonErrors.*;
049    import static org.fest.util.Collections.*;
050    
051    import java.util.Comparator;
052    import java.util.HashSet;
053    import java.util.LinkedHashSet;
054    import java.util.LinkedList;
055    import java.util.List;
056    import java.util.Set;
057    
058    import org.fest.assertions.core.AssertionInfo;
059    import org.fest.assertions.core.Condition;
060    import org.fest.util.ComparatorBasedComparisonStrategy;
061    import org.fest.util.ComparisonStrategy;
062    import org.fest.util.StandardComparisonStrategy;
063    import org.fest.util.VisibleForTesting;
064    
065    /**
066     * Reusable assertions for <code>{@link Iterable}</code>s.
067     * 
068     * @author Alex Ruiz
069     * @author Yvonne Wang
070     * @author Maciej Jaskowski
071     * @author Nicolas François
072     * @author Joel Costigliola
073     */
074    public class Iterables {
075    
076      private static final Iterables INSTANCE = new Iterables();
077    
078      /**
079       * Returns the singleton instance of this class based on {@link StandardComparisonStrategy}.
080       * @return the singleton instance of this class based on {@link StandardComparisonStrategy}.
081       */
082      public static Iterables instance() {
083        return INSTANCE;
084      }
085    
086      private final ComparisonStrategy comparisonStrategy;
087    
088      @VisibleForTesting
089      Failures failures = Failures.instance();
090    
091      @VisibleForTesting
092      Conditions conditions = Conditions.instance();
093    
094      @VisibleForTesting
095      Iterables() {
096        this(StandardComparisonStrategy.instance());
097      }
098    
099      public Iterables(ComparisonStrategy comparisonStrategy) {
100        this.comparisonStrategy = comparisonStrategy;
101      }
102    
103      @VisibleForTesting
104      public Comparator<?> getComparator() {
105        if (comparisonStrategy instanceof ComparatorBasedComparisonStrategy) { return ((ComparatorBasedComparisonStrategy) comparisonStrategy)
106            .getComparator(); }
107        return null;
108      }
109    
110      /**
111       * Asserts that the given <code>{@link Iterable}</code> is {@code null} or empty.
112       * @param info contains information about the assertion.
113       * @param actual the given {@code Iterable}.
114       * @throws AssertionError if the given {@code Iterable} is not {@code null} *and* contains one or more elements.
115       */
116      public void assertNullOrEmpty(AssertionInfo info, Iterable<?> actual) {
117        if (actual == null || isEmpty(actual)) return;
118        throw failures.failure(info, shouldBeNullOrEmpty(actual));
119      }
120    
121      /**
122       * Asserts that the given {@code Iterable} is empty.
123       * @param info contains information about the assertion.
124       * @param actual the given {@code Iterable}.
125       * @throws AssertionError if the given {@code Iterable} is {@code null}.
126       * @throws AssertionError if the given {@code Iterable} is not empty.
127       */
128      public void assertEmpty(AssertionInfo info, Iterable<?> actual) {
129        assertNotNull(info, actual);
130        if (isEmpty(actual)) return;
131        throw failures.failure(info, shouldBeEmpty(actual));
132      }
133    
134      /**
135       * Asserts that the given {@code Iterable} is not empty.
136       * @param info contains information about the assertion.
137       * @param actual the given {@code Iterable}.
138       * @throws AssertionError if the given {@code Iterable} is {@code null}.
139       * @throws AssertionError if the given {@code Iterable} is empty.
140       */
141      public void assertNotEmpty(AssertionInfo info, Iterable<?> actual) {
142        assertNotNull(info, actual);
143        if (!isEmpty(actual)) return;
144        throw failures.failure(info, shouldNotBeEmpty());
145      }
146    
147      /**
148       * Asserts that the number of elements in the given {@code Iterable} is equal to the expected one.
149       * @param info contains information about the assertion.
150       * @param actual the given {@code Iterable}.
151       * @param expectedSize the expected size of {@code actual}.
152       * @throws AssertionError if the given {@code Iterable} is {@code null}.
153       * @throws AssertionError if the number of elements in the given {@code Iterable} is different than the expected one.
154       */
155      public void assertHasSize(AssertionInfo info, Iterable<?> actual, int expectedSize) {
156        assertNotNull(info, actual);
157        int sizeOfActual = sizeOf(actual);
158        if (sizeOfActual == expectedSize) return;
159        throw failures.failure(info, shouldHaveSize(actual, sizeOfActual, expectedSize));
160      }
161    
162      /**
163       * Assert that the actual {@code Iterable} has the same size as the other array.
164       * @param info contains information about the assertion.
165       * @param actual the given {@code Iterable}.
166       * @param other the given array to compare.
167       * @throws AssertionError if the actual group is {@code null}.
168       * @throws AssertionError if the other group is {@code null}.
169       * @throws AssertionError if actual {@code Iterable} and other array don't have the same size.
170       */
171      public void assertHasSameSizeAs(AssertionInfo info, Iterable<?> actual, Object[] other) {
172        assertNotNull(info, actual);
173        if (other == null) throw arrayOfValuesToLookForIsNull();
174        int sizeOfActual = sizeOf(actual);
175        int sizeOfOther = other.length;
176        if (sizeOfActual == sizeOfOther) return;
177        throw failures.failure(info, shouldHaveSameSizeAs(actual, sizeOfActual, sizeOfOther));
178      }
179    
180      /**
181       * Assert that the actual {@code Iterable} has the same size as the other {@code Iterable}.
182       * @param info contains information about the assertion.
183       * @param actual the given {@code Iterable}.
184       * @param other the given {@code Iterable}.
185       * @throws AssertionError if the actual group is {@code null}.
186       * @throws AssertionError if the other group is {@code null}.
187       * @throws AssertionError if actual and other {@code Iterable} don't have the same size.
188       */
189      public void assertHasSameSizeAs(AssertionInfo info, Iterable<?> actual, Iterable<?> other) {
190        assertNotNull(info, actual);
191        checkNotNull(info, other);
192        int sizeOfActual = sizeOf(actual);
193        int sizeOfOther = sizeOf(other);
194        if (sizeOfActual == sizeOfOther) return;
195        throw failures.failure(info, shouldHaveSameSizeAs(actual, sizeOfActual, sizeOfOther));
196      }
197    
198      /**
199       * Asserts that the given {@code Iterable} contains the given values, in any order.
200       * @param info contains information about the assertion.
201       * @param actual the given {@code Iterable}.
202       * @param values the values that are expected to be in the given {@code Iterable}.
203       * @throws NullPointerException if the array of values is {@code null}.
204       * @throws IllegalArgumentException if the array of values is empty.
205       * @throws AssertionError if the given {@code Iterable} is {@code null}.
206       * @throws AssertionError if the given {@code Iterable} does not contain the given values.
207       */
208      public void assertContains(AssertionInfo info, Iterable<?> actual, Object[] values) {
209        checkIsNotNullAndNotEmpty(values);
210        assertNotNull(info, actual);
211        Set<Object> notFound = new LinkedHashSet<Object>();
212        for (Object value : values)
213          if (!iterableContains(actual, value)) notFound.add(value);
214        if (notFound.isEmpty()) return;
215        throw failures.failure(info, shouldContain(actual, values, notFound, comparisonStrategy));
216      }
217    
218      /**
219       * Delegates to {@link ComparisonStrategy#iterableContains(Iterable, Object)}
220       */
221      private boolean iterableContains(Iterable<?> actual, Object value) {
222        return comparisonStrategy.iterableContains(actual, value);
223      }
224    
225      /**
226       * Delegates to {@link ComparisonStrategy#iterableRemoves(Iterable, Object)}
227       */
228      private void iterableRemoves(Iterable<?> actual, Object value) {
229        comparisonStrategy.iterableRemoves(actual, value);
230      }
231    
232      /**
233       * Asserts that the given {@code Iterable} contains only the given values and nothing else, in any order.
234       * @param info contains information about the assertion.
235       * @param actual the given {@code Iterable}.
236       * @param values the values that are expected to be in the given {@code Iterable}.
237       * @throws NullPointerException if the array of values is {@code null}.
238       * @throws IllegalArgumentException if the array of values is empty.
239       * @throws AssertionError if the given {@code Iterable} is {@code null}.
240       * @throws AssertionError if the given {@code Iterable} does not contain the given values or if the given
241       *           {@code Iterable} contains values that are not in the given array.
242       */
243      public void assertContainsOnly(AssertionInfo info, Iterable<?> actual, Object[] values) {
244        checkIsNotNullAndNotEmpty(values);
245        assertNotNull(info, actual);
246        Set<Object> notExpected = setFromIterable(actual);
247        Set<Object> notFound = containsOnly(notExpected, values);
248        if (notExpected.isEmpty() && notFound.isEmpty()) return;
249        throw failures.failure(info, shouldContainOnly(actual, values, notFound, notExpected, comparisonStrategy));
250      }
251    
252      private Set<Object> containsOnly(Set<Object> actual, Object[] values) {
253        Set<Object> notFound = new LinkedHashSet<Object>();
254        for (Object o : set(values)) {
255          if (iterableContains(actual, o)) iterableRemoves(actual, o);
256          else notFound.add(o);
257        }
258        return notFound;
259      }
260    
261      /**
262       * build a Set with that avoid duplicates <b>according to given comparison strategy</b>
263       * @param elements to feed the Set we want to build
264       * @return a Set without duplicates <b>according to given comparison strategy</b>
265       */
266      private Set<Object> set(Object... elements) {
267        if (elements == null) return null;
268        Set<Object> set = new HashSet<Object>();
269        for (Object e : elements) {
270          // only add is not already there
271          if (!iterableContains(set, e)) set.add(e);
272        }
273        return set;
274      }
275    
276      /**
277       * build a Set with that avoid duplicates <b>according to given comparison strategy</b>
278       * @param iterable to feed the Set we want to build
279       * @return a Set without duplicates <b>according to given comparison strategy</b>
280       */
281      private Set<Object> setFromIterable(Iterable<?> iterable) {
282        if (iterable == null) return null;
283        Set<Object> set = new HashSet<Object>();
284        for (Object e : iterable) {
285          // only add is not already there
286          if (!iterableContains(set, e)) set.add(e);
287        }
288        return set;
289      }
290    
291      /**
292       * Verifies that the given <code>{@link Iterable}</code> contains the given sequence of objects, without any other
293       * objects between them.
294       * @param info contains information about the assertion.
295       * @param actual the given {@code Iterable}.
296       * @param sequence the sequence of objects to look for.
297       * @throws AssertionError if the given {@code Iterable} is {@code null}.
298       * @throws NullPointerException if the given sequence is {@code null}.
299       * @throws IllegalArgumentException if the given sequence is empty.
300       * @throws AssertionError if the given {@code Iterable} does not contain the given sequence of objects.
301       */
302      public void assertContainsSequence(AssertionInfo info, Iterable<?> actual, Object[] sequence) {
303        checkIsNotNullAndNotEmpty(sequence);
304        assertNotNull(info, actual);
305        List<?> actualAsList = list(actual);
306        for (int i = 0; i < actualAsList.size(); i++) {
307          // look for given sequence in actual starting from current index (i)
308          if (containsSequenceAtGivenIndex(actualAsList, sequence, i)) return;
309        }
310        throw actualDoesNotContainSequence(info, actual, sequence);
311      }
312    
313      /**
314       * Verifies that the actual <code>Iterable</code> is a subset of values <code>Iterable</code>. <br/>
315       * Both actual and given iterable are treated as sets, therefore duplicates on either of them are ignored.
316       * @param info contains information about the assertion.
317       * @param actual the actual {@code Iterable}.
318       * @param values the {@code Iterable} that should contain all actual elements.
319       * @throws AssertionError if the actual {@code Iterable} is {@code null}.
320       * @throws NullPointerException if the given Iterable is {@code null}.
321       * @throws AssertionError if the actual {@code Iterable} is not subset of set <code>{@link Iterable}</code>
322       */
323      public void assertIsSubsetOf(AssertionInfo info, Iterable<?> actual, Iterable<?> values) {
324        assertNotNull(info, actual);
325        checkNotNull(info, values);
326        List<Object> extra = list();
327        for (Object actualElement : actual) {
328          if (!iterableContains(values, actualElement)) {
329            extra.add(actualElement);
330          }
331        }
332        if (extra.size() > 0) throw actualIsNotSubsetOfSet(info, actual, values, extra);
333      }
334    
335      private static void checkNotNull(AssertionInfo info, Iterable<?> set) {
336        if (set == null) throw iterableToLookForIsNull();
337      }
338    
339      private AssertionError actualIsNotSubsetOfSet(AssertionInfo info, Object actual, Iterable<?> set, Iterable<?> extra) {
340        return failures.failure(info, shouldBeSubsetOf(actual, set, extra, comparisonStrategy));
341      }
342    
343      /**
344       * Return true if actualAsList contains exactly the given sequence at given starting index, false otherwise.
345       * @param actualAsList the list to look sequance in
346       * @param sequence the sequence to look for
347       * @param startingIndex the index of actual list at which we start looking for sequence.
348       * @return
349       */
350      private boolean containsSequenceAtGivenIndex(List<?> actualAsList, Object[] sequence, int startingIndex) {
351        // check that, starting from given index, actualAsList has enough remaining elements to contain sequence
352        if (actualAsList.size() - startingIndex < sequence.length) return false;
353        for (int i = 0; i < sequence.length; i++) {
354          if (!areEqual(actualAsList.get(startingIndex + i), sequence[i])) return false;
355        }
356        return true;
357      }
358    
359      /**
360       * Delegates to {@link ComparisonStrategy#areEqual(Object, Object)}
361       */
362      private boolean areEqual(Object actual, Object other) {
363        return comparisonStrategy.areEqual(actual, other);
364      }
365    
366      private AssertionError actualDoesNotContainSequence(AssertionInfo info, Iterable<?> actual, Object[] sequence) {
367        return failures.failure(info, shouldContainSequence(actual, sequence, comparisonStrategy));
368      }
369    
370      /**
371       * Asserts that the given {@code Iterable} does not contain the given values.
372       * @param info contains information about the assertion.
373       * @param actual the given {@code Iterable}.
374       * @param values the values that are expected not to be in the given {@code Iterable}.
375       * @throws NullPointerException if the array of values is {@code null}.
376       * @throws IllegalArgumentException if the array of values is empty.
377       * @throws AssertionError if the given {@code Iterable} is {@code null}.
378       * @throws AssertionError if the given {@code Iterable} contains any of given values.
379       */
380      public void assertDoesNotContain(AssertionInfo info, Iterable<?> actual, Object[] values) {
381        checkIsNotNullAndNotEmpty(values);
382        assertNotNull(info, actual);
383        Set<Object> found = new LinkedHashSet<Object>();
384        for (Object o : values)
385          if (iterableContains(actual, o)) found.add(o);
386        if (found.isEmpty()) return;
387        throw failures.failure(info, shouldNotContain(actual, values, found, comparisonStrategy));
388      }
389    
390      /**
391       * Asserts that the given {@code Iterable} does not have duplicate values.
392       * @param info contains information about the assertion.
393       * @param actual the given {@code Iterable}.
394       * @throws NullPointerException if the array of values is {@code null}.
395       * @throws IllegalArgumentException if the array of values is empty.
396       * @throws AssertionError if the given {@code Iterable} is {@code null}.
397       * @throws AssertionError if the given {@code Iterable} contains duplicate values.
398       */
399      public void assertDoesNotHaveDuplicates(AssertionInfo info, Iterable<?> actual) {
400        assertNotNull(info, actual);
401        Iterable<?> duplicates = comparisonStrategy.duplicatesFrom(actual);
402        if (isEmpty(duplicates)) return;
403        throw failures.failure(info, shouldNotHaveDuplicates(actual, duplicates, comparisonStrategy));
404      }
405    
406      /**
407       * Verifies that the given {@code Iterable} starts with the given sequence of objects, without any other objects
408       * between them. Similar to <code>{@link #assertContainsSequence(AssertionInfo, Iterable, Object[])}</code>, but it
409       * also verifies that the first element in the sequence is also the first element of the given {@code Iterable}.
410       * @param info contains information about the assertion.
411       * @param actual the given {@code Iterable}.
412       * @param sequence the sequence of objects to look for.
413       * @throws NullPointerException if the given argument is {@code null}.
414       * @throws IllegalArgumentException if the given argument is an empty array.
415       * @throws AssertionError if the given {@code Iterable} is {@code null}.
416       * @throws AssertionError if the given {@code Iterable} does not start with the given sequence of objects.
417       */
418      public void assertStartsWith(AssertionInfo info, Iterable<?> actual, Object[] sequence) {
419        checkIsNotNullAndNotEmpty(sequence);
420        assertNotNull(info, actual);
421        int sequenceSize = sequence.length;
422        if (sizeOf(actual) < sequenceSize) throw actualDoesNotStartWithSequence(info, actual, sequence);
423        int i = 0;
424        for (Object o : actual) {
425          if (i >= sequenceSize) break;
426          if (areEqual(o, sequence[i++])) continue;
427          throw actualDoesNotStartWithSequence(info, actual, sequence);
428        }
429      }
430    
431      private AssertionError actualDoesNotStartWithSequence(AssertionInfo info, Iterable<?> actual, Object[] sequence) {
432        return failures.failure(info, shouldStartWith(actual, sequence, comparisonStrategy));
433      }
434    
435      /**
436       * Verifies that the given {@code Iterable} ends with the given sequence of objects, without any other objects between
437       * them. Similar to <code>{@link #assertContainsSequence(AssertionInfo, Iterable, Object[])}</code>, but it also
438       * verifies that the last element in the sequence is also the last element of the given {@code Iterable}.
439       * @param info contains information about the assertion.
440       * @param actual the given {@code Iterable}.
441       * @param sequence the sequence of objects to look for.
442       * @throws NullPointerException if the given argument is {@code null}.
443       * @throws IllegalArgumentException if the given argument is an empty array.
444       * @throws AssertionError if the given {@code Iterable} is {@code null}.
445       * @throws AssertionError if the given {@code Iterable} does not end with the given sequence of objects.
446       */
447      public void assertEndsWith(AssertionInfo info, Iterable<?> actual, Object[] sequence) {
448        checkIsNotNullAndNotEmpty(sequence);
449        assertNotNull(info, actual);
450        int sequenceSize = sequence.length;
451        int sizeOfActual = sizeOf(actual);
452        if (sizeOfActual < sequenceSize) throw actualDoesNotEndWithSequence(info, actual, sequence);
453        int start = sizeOfActual - sequenceSize;
454        int sequenceIndex = 0, indexOfActual = 0;
455        for (Object o : actual) {
456          if (indexOfActual++ < start) continue;
457          if (areEqual(o, sequence[sequenceIndex++])) continue;
458          throw actualDoesNotEndWithSequence(info, actual, sequence);
459        }
460      }
461    
462      /**
463       * Asserts that the given {@code Iterable} contains at least a null element.
464       * @param info contains information about the assertion.
465       * @param actual the given {@code Iterable}.
466       * @throws AssertionError if the given {@code Iterable} is {@code null}.
467       * @throws AssertionError if the given {@code Iterable} does not contain at least a null element.
468       */
469      public void assertContainsNull(AssertionInfo info, Iterable<?> actual) {
470        assertNotNull(info, actual);
471        if (!iterableContains(actual, null)) throw failures.failure(info, shouldContainNull(actual));
472      }
473    
474      /**
475       * Asserts that the given {@code Iterable} does not contain null elements.
476       * @param info contains information about the assertion.
477       * @param actual the given {@code Iterable}.
478       * @throws AssertionError if the given {@code Iterable} is {@code null}.
479       * @throws AssertionError if the given {@code Iterable} contains a null element.
480       */
481      public void assertDoesNotContainNull(AssertionInfo info, Iterable<?> actual) {
482        assertNotNull(info, actual);
483        if (iterableContains(actual, null)) throw failures.failure(info, shouldNotContainNull(actual));
484      }
485    
486      /**
487       * Assert that each element of given {@code Iterable} satisfies the given condition.
488       * @param info contains information about the assertion.
489       * @param actual the given {@code Iterable}.
490       * @param condition the given {@code Condition}.
491       * @throws NullPointerException if the given condition is {@code null}.
492       * @throws AssertionError if a element cannot be cast to E.
493       * @throws AssertionError if one or more element not satisfy the given condition.
494       */
495      public <E> void assertAre(AssertionInfo info, Iterable<?> actual, Condition<E> condition) {
496        assertNotNull(info, actual);
497        conditions.assertIsNotNull(condition);
498        try {
499          List<E> notSatisfiesCondition = notSatisfiesCondition(actual, condition);
500          if (notSatisfiesCondition.isEmpty()) return;
501          throw failures.failure(info, elementsShouldBe(actual, notSatisfiesCondition, condition));
502        } catch (ClassCastException e) {
503          throw failures.failure(info, shouldBeSameGenericBetweenIterableAndCondition(actual, condition));
504        }
505      }
506    
507      /**
508       * Assert that each element of given {@code Iterable} not satisfies the given condition.
509       * @param info contains information about the assertion.
510       * @param actual the given {@code Iterable}.
511       * @param condition the given {@code Condition}.
512       * @throws NullPointerException if the given condition is {@code null}.
513       * @throws AssertionError if a element cannot be cast to E.
514       * @throws AssertionError if one or more element satisfy the given condition.
515       */
516      public <E> void assertAreNot(AssertionInfo info, Iterable<?> actual, Condition<E> condition) {
517        assertNotNull(info, actual);
518        conditions.assertIsNotNull(condition);
519        try {
520          List<E> satisfiesCondition = satisfiesCondition(actual, condition);
521          if (satisfiesCondition.isEmpty()) return;
522          throw failures.failure(info, elementsShouldNotBe(actual, satisfiesCondition, condition));
523        } catch (ClassCastException e) {
524          throw failures.failure(info, shouldBeSameGenericBetweenIterableAndCondition(actual, condition));
525        }
526      }
527    
528      /**
529       * Assert that each element of given {@code Iterable} satisfies the given condition.
530       * @param info contains information about the assertion.
531       * @param actual the given {@code Iterable}.
532       * @param condition the given {@code Condition}.
533       * @throws NullPointerException if the given condition is {@code null}.
534       * @throws AssertionError if a element cannot be cast to E.
535       * @throws AssertionError if one or more element not satisfy the given condition.
536       */
537      public <E> void assertHave(AssertionInfo info, Iterable<?> actual, Condition<E> condition) {
538        assertNotNull(info, actual);
539        conditions.assertIsNotNull(condition);
540        try {
541          List<E> notSatisfiesCondition = notSatisfiesCondition(actual, condition);
542          if (notSatisfiesCondition.isEmpty()) return;
543          throw failures.failure(info, elementsShouldHave(actual, notSatisfiesCondition, condition));
544        } catch (ClassCastException e) {
545          throw failures.failure(info, shouldBeSameGenericBetweenIterableAndCondition(actual, condition));
546        }
547      }
548    
549      /**
550       * Assert that each element of given {@code Iterable} not satisfies the given condition.
551       * @param info contains information about the assertion.
552       * @param actual the given {@code Iterable}.
553       * @param condition the given {@code Condition}.
554       * @throws NullPointerException if the given condition is {@code null}.
555       * @throws AssertionError if a element cannot be cast to E.
556       * @throws AssertionError if one or more element satisfy the given condition.
557       */
558      public <E> void assertDoNotHave(AssertionInfo info, Iterable<?> actual, Condition<E> condition) {
559        assertNotNull(info, actual);
560        conditions.assertIsNotNull(condition);
561        try {
562          List<E> satisfiesCondition = satisfiesCondition(actual, condition);
563          if (satisfiesCondition.isEmpty()) return;
564          throw failures.failure(info, elementsShouldNotHave(actual, satisfiesCondition, condition));
565        } catch (ClassCastException e) {
566          throw failures.failure(info, shouldBeSameGenericBetweenIterableAndCondition(actual, condition));
567        }
568      }
569    
570      /**
571       * Assert that there is <b>at least</b> <i>n</i> elements in the actual {@code Iterable} satisfying the given
572       * condition.
573       * @param info contains information about the assertion.
574       * @param actual the given {@code Iterable}.
575       * @param n the minimum number of times the condition should be verified.
576       * @param condition the given {@code Condition}.
577       * @throws NullPointerException if the given condition is {@code null}.
578       * @throws AssertionError if a element cannot be cast to E.
579       * @throws AssertionError if the number of elements satisfying the given condition is &lt; n.
580       */
581      public <E> void assertAreAtLeast(AssertionInfo info, Iterable<?> actual, int n, Condition<E> condition) {
582        assertNotNull(info, actual);
583        conditions.assertIsNotNull(condition);
584        try {
585          List<E> satisfiesCondition = satisfiesCondition(actual, condition);
586          if (satisfiesCondition.size() >= n) return;
587          throw failures.failure(info, elementsShouldBeAtLeast(actual, n, condition));
588        } catch (ClassCastException e) {
589          throw failures.failure(info, shouldBeSameGenericBetweenIterableAndCondition(actual, condition));
590        }
591      }
592    
593      /**
594       * Assert that there is <b>at least</b> <i>n</i> elements in the actual {@code Iterable} <b>not</b> satisfying the
595       * given condition.
596       * @param info contains information about the assertion.
597       * @param actual the given {@code Iterable}.
598       * @param n the number of times the condition should not be verified at least.
599       * @param condition the given {@code Condition}.
600       * @throws NullPointerException if the given condition is {@code null}.
601       * @throws AssertionError if a element cannot be cast to E.
602       * @throws AssertionError if the number of elements not satisfying the given condition is &lt; n.
603       */
604      public <E> void assertAreNotAtLeast(AssertionInfo info, Iterable<?> actual, int n, Condition<E> condition) {
605        assertNotNull(info, actual);
606        conditions.assertIsNotNull(condition);
607        try {
608          List<E> notSatisfiesCondition = notSatisfiesCondition(actual, condition);
609          if (notSatisfiesCondition.size() >= n) return;
610          throw failures.failure(info, elementsShouldNotBeAtLeast(actual, n, condition));
611        } catch (ClassCastException e) {
612          throw failures.failure(info, shouldBeSameGenericBetweenIterableAndCondition(actual, condition));
613        }
614      }
615    
616      /**
617       * Assert that there is <b>at most</b> <i>n</i> elements in the actual {@code Iterable} satisfying the given
618       * condition.
619       * @param info contains information about the assertion.
620       * @param actual the given {@code Iterable}.
621       * @param n the number of times the condition should be at most verified.
622       * @param condition the given {@code Condition}.
623       * @throws NullPointerException if the given condition is {@code null}.
624       * @throws AssertionError if a element cannot be cast to E.
625       * @throws AssertionError if the number of elements satisfying the given condition is &gt; n.
626       */
627      public <E> void assertAreAtMost(AssertionInfo info, Iterable<?> actual, int n, Condition<E> condition) {
628        assertNotNull(info, actual);
629        conditions.assertIsNotNull(condition);
630        try {
631          List<E> satisfiesCondition = satisfiesCondition(actual, condition);
632          if (satisfiesCondition.size() <= n) return;
633          throw failures.failure(info, elementsShouldNotBeAtMost(actual, n, condition));
634        } catch (ClassCastException e) {
635          throw failures.failure(info, shouldBeSameGenericBetweenIterableAndCondition(actual, condition));
636        }
637      }
638    
639      /**
640       * Verifies that there is <b>at most</b> <i>n</i> elements in the actual {@code Iterable} <b>not</b> satisfying the
641       * given condition.
642       * @param info contains information about the assertion.
643       * @param actual the given {@code Iterable}.
644       * @param n the number of times the condition should not be verified at most.
645       * @param condition the given {@code Condition}.
646       * @throws NullPointerException if the given condition is {@code null}.
647       * @throws AssertionError if a element cannot be cast to E.
648       * @throws AssertionError if the number of elements not satisfying the given condition is &gt; n.
649       */
650      public <E> void assertAreNotAtMost(AssertionInfo info, Iterable<?> actual, int n, Condition<E> condition) {
651        assertNotNull(info, actual);
652        conditions.assertIsNotNull(condition);
653        try {
654          List<E> notSatisfiesCondition = notSatisfiesCondition(actual, condition);
655          if (notSatisfiesCondition.size() <= n) return;
656          throw failures.failure(info, elementsShouldNotBeAtMost(actual, n, condition));
657        } catch (ClassCastException e) {
658          throw failures.failure(info, shouldBeSameGenericBetweenIterableAndCondition(actual, condition));
659        }
660      }
661    
662      /**
663       * Verifies that there is <b>exactly</b> <i>n</i> elements in the actual {@code Iterable} satisfying the given
664       * condition.
665       * @param info contains information about the assertion.
666       * @param actual the given {@code Iterable}.
667       * @param n the exact number of times the condition should be verified.
668       * @param condition the given {@code Condition}.
669       * @throws NullPointerException if the given condition is {@code null}.
670       * @throws AssertionError if a element cannot be cast to E.
671       * @throws AssertionError if the number of elements satisfying the given condition is &ne; n.
672       */
673      public <E> void assertAreExactly(AssertionInfo info, Iterable<?> actual, int n, Condition<E> condition) {
674        assertNotNull(info, actual);
675        conditions.assertIsNotNull(condition);
676        try {
677          List<E> satisfiesCondition = satisfiesCondition(actual, condition);
678          if (satisfiesCondition.size() == n) return;
679          throw failures.failure(info, elementsShouldBeExactly(actual, n, condition));
680        } catch (ClassCastException e) {
681          throw failures.failure(info, shouldBeSameGenericBetweenIterableAndCondition(actual, condition));
682        }
683      }
684    
685      /**
686       * Verifies that there is <b>exactly</b> <i>n</i> elements in the actual {@code Iterable} <b>not</b> satisfying the
687       * given condition.
688       * @param info contains information about the assertion.
689       * @param actual the given {@code Iterable}.
690       * @param n the exact number of times the condition should not be verified.
691       * @param condition the given {@code Condition}.
692       * @throws NullPointerException if the given condition is {@code null}.
693       * @throws AssertionError if a element cannot be cast to E.
694       * @throws AssertionError if the number of elements not satisfying the given condition is &ne; n.
695       */
696      public <E> void assertAreNotExactly(AssertionInfo info, Iterable<?> actual, int n, Condition<E> condition) {
697        assertNotNull(info, actual);
698        conditions.assertIsNotNull(condition);
699        try {
700          List<E> notSatisfiesCondition = notSatisfiesCondition(actual, condition);
701          if (notSatisfiesCondition.size() == n) return;
702          throw failures.failure(info, elementsShouldNotBeExactly(actual, n, condition));
703        } catch (ClassCastException e) {
704          throw failures.failure(info, shouldBeSameGenericBetweenIterableAndCondition(actual, condition));
705        }
706      }
707    
708      /**
709       * An alias method of {@link #assertAreAtLeast(AssertionInfo, Iterable, int, Condition)} to provide a richer fluent
710       * api (same logic, only error message differs).
711       */
712      public <E> void assertHaveAtLeast(AssertionInfo info, Iterable<?> actual, int times, Condition<E> condition) {
713        assertNotNull(info, actual);
714        conditions.assertIsNotNull(condition);
715        try {
716          List<E> satisfiesCondition = satisfiesCondition(actual, condition);
717          if (satisfiesCondition.size() >= times) return;
718          throw failures.failure(info, elementsShouldHaveAtLeast(actual, times, condition));
719        } catch (ClassCastException e) {
720          throw failures.failure(info, shouldBeSameGenericBetweenIterableAndCondition(actual, condition));
721        }
722      }
723    
724      /**
725       * An alias method of {@link #assertAreNotAtLeast(AssertionInfo, Iterable, int, Condition)} to provide a richer fluent
726       * api (same logic, only error message differs).
727       */
728      public <E> void assertDoNotHaveAtLeast(AssertionInfo info, Iterable<?> actual, int times, Condition<E> condition) {
729        assertNotNull(info, actual);
730        conditions.assertIsNotNull(condition);
731        try {
732          List<E> notSatisfiesCondition = notSatisfiesCondition(actual, condition);
733          if (notSatisfiesCondition.size() >= times) return;
734          throw failures.failure(info, elementsShouldNotHaveAtLeast(actual, times, condition));
735        } catch (ClassCastException e) {
736          throw failures.failure(info, shouldBeSameGenericBetweenIterableAndCondition(actual, condition));
737        }
738      }
739    
740      /**
741       * An alias method of {@link #assertAreAtMost(AssertionInfo, Iterable, int, Condition)} to provide a richer fluent api
742       * (same logic, only error message differs).
743       */
744      public <E> void assertHaveAtMost(AssertionInfo info, Iterable<?> actual, int times, Condition<E> condition) {
745        assertNotNull(info, actual);
746        conditions.assertIsNotNull(condition);
747        try {
748          List<E> satisfiesCondition = satisfiesCondition(actual, condition);
749          if (satisfiesCondition.size() <= times) return;
750          throw failures.failure(info, elementsShouldHaveAtMost(actual, times, condition));
751        } catch (ClassCastException e) {
752          throw failures.failure(info, shouldBeSameGenericBetweenIterableAndCondition(actual, condition));
753        }
754      }
755    
756      /**
757       * An alias method of {@link #assertAreNotAtMost(AssertionInfo, Iterable, int, Condition)} to provide a richer fluent
758       * api (same logic, only error message differs).
759       */
760      public <E> void assertDoNotHaveAtMost(AssertionInfo info, Iterable<?> actual, int times, Condition<E> condition) {
761        assertNotNull(info, actual);
762        conditions.assertIsNotNull(condition);
763        try {
764          List<E> notSatisfiesCondition = notSatisfiesCondition(actual, condition);
765          if (notSatisfiesCondition.size() <= times) return;
766          throw failures.failure(info, elementsShouldNotHaveAtMost(actual, times, condition));
767        } catch (ClassCastException e) {
768          throw failures.failure(info, shouldBeSameGenericBetweenIterableAndCondition(actual, condition));
769        }
770      }
771    
772      /**
773       * An alias method of {@link #assertAreExactly(AssertionInfo, Iterable, int, Condition)} to provide a richer fluent
774       * api (same logic, only error message differs).
775       */
776      public <E> void assertHaveExactly(AssertionInfo info, Iterable<?> actual, int times, Condition<E> condition) {
777        assertNotNull(info, actual);
778        conditions.assertIsNotNull(condition);
779        try {
780          List<E> satisfiesCondition = satisfiesCondition(actual, condition);
781          if (satisfiesCondition.size() == times) return;
782          throw failures.failure(info, elementsShouldHaveExactly(actual, times, condition));
783        } catch (ClassCastException e) {
784          throw failures.failure(info, shouldBeSameGenericBetweenIterableAndCondition(actual, condition));
785        }
786      }
787    
788      /**
789       * An alias method of {@link #assertAreNotExactly(AssertionInfo, Iterable, int, Condition)} to provide a richer fluent
790       * api (same logic, only error message differs).
791       */
792      public <E> void assertDoNotHaveExactly(AssertionInfo info, Iterable<?> actual, int times, Condition<E> condition) {
793        assertNotNull(info, actual);
794        conditions.assertIsNotNull(condition);
795        try {
796          List<E> notSatisfiesCondition = notSatisfiesCondition(actual, condition);
797          if (notSatisfiesCondition.size() == times) return;
798          throw failures.failure(info, elementsShouldNotHaveExactly(actual, times, condition));
799        } catch (ClassCastException e) {
800          throw failures.failure(info, shouldBeSameGenericBetweenIterableAndCondition(actual, condition));
801        }
802      }
803    
804      private void checkIsNotNullAndNotEmpty(Object[] values) {
805        if (values == null) throw arrayOfValuesToLookForIsNull();
806        if (values.length == 0) throw arrayOfValuesToLookForIsEmpty();
807      }
808    
809      private void assertNotNull(AssertionInfo info, Iterable<?> actual) {
810        Objects.instance().assertNotNull(info, actual);
811      }
812    
813      private AssertionError actualDoesNotEndWithSequence(AssertionInfo info, Iterable<?> actual, Object[] sequence) {
814        return failures.failure(info, shouldEndWith(actual, sequence, comparisonStrategy));
815      }
816    
817      @SuppressWarnings("unchecked")
818      private <E> List<E> notSatisfiesCondition(Iterable<?> actual, Condition<E> condition) {
819        List<E> notSatisfiesCondition = new LinkedList<E>();
820        for (Object o : actual) {
821          if (!condition.matches((E) o)) {
822            notSatisfiesCondition.add((E) o);
823          }
824        }
825        return notSatisfiesCondition;
826      }
827    
828      @SuppressWarnings("unchecked")
829      private <E> List<E> satisfiesCondition(Iterable<?> actual, Condition<E> condition) {
830        List<E> satisfiesCondition = new LinkedList<E>();
831        for (Object o : actual) {
832          if (condition.matches((E) o)) {
833            satisfiesCondition.add((E) o);
834          }
835        }
836        return satisfiesCondition;
837      }
838    
839      static public NullPointerException iterableToLookForIsNull() {
840        return new NullPointerException("The iterable to look for should not be null");
841      }
842    
843      static public IllegalArgumentException iterableToLookForIsEmpty() {
844        return new IllegalArgumentException("The iterable to look for should not be empty");
845      }
846    
847    }