| package org.hamcrest.core; |
| |
| import org.hamcrest.Description; |
| import org.hamcrest.Matcher; |
| import org.hamcrest.TypeSafeDiagnosingMatcher; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import static org.hamcrest.core.AllOf.allOf; |
| import static org.hamcrest.core.IsEqual.equalTo; |
| |
| public class IsCollectionContaining<T> extends TypeSafeDiagnosingMatcher<Iterable<? super T>> { |
| private final Matcher<? super T> elementMatcher; |
| |
| public IsCollectionContaining(Matcher<? super T> elementMatcher) { |
| this.elementMatcher = elementMatcher; |
| } |
| |
| @Override |
| protected boolean matchesSafely(Iterable<? super T> collection, Description mismatchDescription) { |
| if (isEmpty(collection)) { |
| mismatchDescription.appendText("was empty"); |
| return false; |
| } |
| |
| for (Object item : collection) { |
| if (elementMatcher.matches(item)) { |
| return true; |
| } |
| } |
| |
| mismatchDescription.appendText("mismatches were: ["); |
| boolean isPastFirst = false; |
| for (Object item : collection) { |
| if (isPastFirst) { |
| mismatchDescription.appendText(", "); |
| } |
| elementMatcher.describeMismatch(item, mismatchDescription); |
| isPastFirst = true; |
| } |
| mismatchDescription.appendText("]"); |
| return false; |
| } |
| |
| private boolean isEmpty(Iterable<? super T> iterable) { |
| return ! iterable.iterator().hasNext(); |
| } |
| |
| @Override |
| public void describeTo(Description description) { |
| description |
| .appendText("a collection containing ") |
| .appendDescriptionOf(elementMatcher); |
| } |
| |
| |
| /** |
| * Creates a matcher for {@link Iterable}s that only matches when a single pass over the |
| * examined {@link Iterable} yields at least one item that is matched by the specified |
| * <code>itemMatcher</code>. Whilst matching, the traversal of the examined {@link Iterable} |
| * will stop as soon as a matching item is found. |
| * For example: |
| * <pre>assertThat(Arrays.asList("foo", "bar"), hasItem(startsWith("ba")))</pre> |
| * |
| * @param itemMatcher |
| * the matcher to apply to items provided by the examined {@link Iterable} |
| */ |
| public static <T> Matcher<Iterable<? super T>> hasItem(Matcher<? super T> itemMatcher) { |
| return new IsCollectionContaining<>(itemMatcher); |
| } |
| |
| /** |
| * Creates a matcher for {@link Iterable}s that only matches when a single pass over the |
| * examined {@link Iterable} yields at least one item that is equal to the specified |
| * <code>item</code>. Whilst matching, the traversal of the examined {@link Iterable} |
| * will stop as soon as a matching item is found. |
| * For example: |
| * <pre>assertThat(Arrays.asList("foo", "bar"), hasItem("bar"))</pre> |
| * |
| * @param item |
| * the item to compare against the items provided by the examined {@link Iterable} |
| */ |
| public static <T> Matcher<Iterable<? super T>> hasItem(T item) { |
| // Doesn't forward to hasItem() method so compiler can sort out generics. |
| return new IsCollectionContaining<>(equalTo(item)); |
| } |
| |
| /** |
| * Creates a matcher for {@link Iterable}s that matches when consecutive passes over the |
| * examined {@link Iterable} yield at least one item that is matched by the corresponding |
| * matcher from the specified <code>itemMatchers</code>. Whilst matching, each traversal of |
| * the examined {@link Iterable} will stop as soon as a matching item is found. |
| * For example: |
| * <pre>assertThat(Arrays.asList("foo", "bar", "baz"), hasItems(endsWith("z"), endsWith("o")))</pre> |
| * |
| * @param itemMatchers |
| * the matchers to apply to items provided by the examined {@link Iterable} |
| */ |
| @SafeVarargs |
| public static <T> Matcher<Iterable<T>> hasItems(Matcher<? super T>... itemMatchers) { |
| List<Matcher<? super Iterable<T>>> all = new ArrayList<>(itemMatchers.length); |
| |
| for (Matcher<? super T> elementMatcher : itemMatchers) { |
| // Doesn't forward to hasItem() method so compiler can sort out generics. |
| all.add(new IsCollectionContaining<>(elementMatcher)); |
| } |
| |
| return allOf(all); |
| } |
| |
| /** |
| * Creates a matcher for {@link Iterable}s that matches when consecutive passes over the |
| * examined {@link Iterable} yield at least one item that is equal to the corresponding |
| * item from the specified <code>items</code>. Whilst matching, each traversal of the |
| * examined {@link Iterable} will stop as soon as a matching item is found. |
| * For example: |
| * <pre>assertThat(Arrays.asList("foo", "bar", "baz"), hasItems("baz", "foo"))</pre> |
| * |
| * @param items |
| * the items to compare against the items provided by the examined {@link Iterable} |
| */ |
| @SafeVarargs |
| public static <T> Matcher<Iterable<T>> hasItems(T... items) { |
| List<Matcher<? super Iterable<T>>> all = new ArrayList<>(items.length); |
| for (T item : items) { |
| all.add(hasItem(item)); |
| } |
| |
| return allOf(all); |
| } |
| |
| } |