    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    }