aboutsummaryrefslogtreecommitdiff
path: root/hamcrest-core/src/main/java/org/hamcrest/core/IsCollectionContaining.java
diff options
context:
space:
mode:
Diffstat (limited to 'hamcrest-core/src/main/java/org/hamcrest/core/IsCollectionContaining.java')
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/core/IsCollectionContaining.java133
1 files changed, 133 insertions, 0 deletions
diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/IsCollectionContaining.java b/hamcrest-core/src/main/java/org/hamcrest/core/IsCollectionContaining.java
new file mode 100644
index 0000000..c55853d
--- /dev/null
+++ b/hamcrest-core/src/main/java/org/hamcrest/core/IsCollectionContaining.java
@@ -0,0 +1,133 @@
+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);
+ }
+
+}