View Javadoc
1   package io.atlassian.fugue.hamcrest;
2   
3   import io.atlassian.fugue.Either;
4   import org.hamcrest.Description;
5   import org.hamcrest.Matcher;
6   import org.hamcrest.TypeSafeMatcher;
7   
8   import static io.atlassian.fugue.Unit.Unit;
9   import static java.util.Objects.requireNonNull;
10  
11  public final class EitherMatchers {
12  
13    private EitherMatchers() {
14      throw new UnsupportedOperationException();
15    }
16  
17    public static <L> Matcher<Either<L, ?>> isLeft(Matcher<? super L> subMatcher) {
18      return new LeftMatcher<>(requireNonNull(subMatcher, "subMatcher"));
19    }
20  
21    public static <R> Matcher<Either<?, R>> isRight(Matcher<? super R> subMatcher) {
22      return new RightMatcher<>(requireNonNull(subMatcher, "subMatcher"));
23    }
24  
25    private static class LeftMatcher<L> extends TypeSafeMatcher<Either<L, ?>> {
26  
27      private final Matcher<? super L> subMatcher;
28  
29      private LeftMatcher(Matcher<? super L> subMatcher) {
30        this.subMatcher = subMatcher;
31      }
32  
33      @Override protected boolean matchesSafely(Either<L, ?> actual) {
34        return actual.left().exists(subMatcher::matches);
35      }
36  
37      @Override public void describeTo(Description description) {
38        description.appendText("left that ");
39        subMatcher.describeTo(description);
40      }
41  
42      @Override protected void describeMismatchSafely(Either<L, ?> actual, Description mismatchDescription) {
43        actual.fold(left -> {
44          mismatchDescription.appendText("was left that ");
45          subMatcher.describeMismatch(left, mismatchDescription);
46          return Unit();
47        }, right -> {
48          mismatchDescription.appendText("was right");
49          return Unit();
50        });
51      }
52    }
53  
54    private static class RightMatcher<R> extends TypeSafeMatcher<Either<?, R>> {
55  
56      private final Matcher<? super R> subMatcher;
57  
58      private RightMatcher(Matcher<? super R> subMatcher) {
59        this.subMatcher = subMatcher;
60      }
61  
62      @Override protected boolean matchesSafely(Either<?, R> actual) {
63        return actual.right().exists(subMatcher::matches);
64      }
65  
66      @Override public void describeTo(Description description) {
67        description.appendText("right that ");
68        subMatcher.describeTo(description);
69      }
70  
71      @Override protected void describeMismatchSafely(Either<?, R> actual, Description mismatchDescription) {
72        actual.fold(left -> {
73          mismatchDescription.appendText("was left");
74          return Unit();
75        }, right -> {
76          mismatchDescription.appendText("was right that ");
77          subMatcher.describeMismatch(right, mismatchDescription);
78          return Unit();
79        });
80      }
81    }
82  }