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 < 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 < 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 > 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 > 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 ≠ 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 ≠ 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 }