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