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    }