001 package org.hamcrest.core;
002
003 import org.hamcrest.*;
004
005 import java.util.ArrayList;
006
007 public class CombinableMatcher<T> extends TypeSafeDiagnosingMatcher<T> {
008 private final Matcher<? super T> matcher;
009
010 public CombinableMatcher(Matcher<? super T> matcher) {
011 this.matcher = matcher;
012 }
013
014 @Override
015 protected boolean matchesSafely(T item, Description mismatch) {
016 if (!matcher.matches(item)) {
017 matcher.describeMismatch(item, mismatch);
018 return false;
019 }
020 return true;
021 }
022
023 @Override
024 public void describeTo(Description description) {
025 description.appendDescriptionOf(matcher);
026 }
027
028 public CombinableMatcher<T> and(Matcher<? super T> other) {
029 return new CombinableMatcher<T>(new AllOf<T>(templatedListWith(other)));
030 }
031
032 public CombinableMatcher<T> or(Matcher<? super T> other) {
033 return new CombinableMatcher<T>(new AnyOf<T>(templatedListWith(other)));
034 }
035
036 private ArrayList<Matcher<? super T>> templatedListWith(Matcher<? super T> other) {
037 ArrayList<Matcher<? super T>> matchers = new ArrayList<Matcher<? super T>>();
038 matchers.add(matcher);
039 matchers.add(other);
040 return matchers;
041 }
042
043 /**
044 * Creates a matcher that matches when both of the specified matchers match the examined object.
045 * <p/>
046 * For example:
047 * <pre>assertThat("fab", both(containsString("a")).and(containsString("b")))</pre>
048 */
049 @Factory
050 public static <LHS> CombinableBothMatcher<LHS> both(Matcher<? super LHS> matcher) {
051 return new CombinableBothMatcher<LHS>(matcher);
052 }
053
054 public static final class CombinableBothMatcher<X> {
055 private final Matcher<? super X> first;
056 public CombinableBothMatcher(Matcher<? super X> matcher) {
057 this.first = matcher;
058 }
059 public CombinableMatcher<X> and(Matcher<? super X> other) {
060 return new CombinableMatcher<X>(first).and(other);
061 }
062 }
063
064 /**
065 * Creates a matcher that matches when either of the specified matchers match the examined object.
066 * <p/>
067 * For example:
068 * <pre>assertThat("fan", either(containsString("a")).and(containsString("b")))</pre>
069 */
070 @Factory
071 public static <LHS> CombinableEitherMatcher<LHS> either(Matcher<? super LHS> matcher) {
072 return new CombinableEitherMatcher<LHS>(matcher);
073 }
074
075 public static final class CombinableEitherMatcher<X> {
076 private final Matcher<? super X> first;
077 public CombinableEitherMatcher(Matcher<? super X> matcher) {
078 this.first = matcher;
079 }
080 public CombinableMatcher<X> or(Matcher<? super X> other) {
081 return new CombinableMatcher<X>(first).or(other);
082 }
083 }
084 }