View Javadoc

1   package io.atlassian.fugue.hamcrest;
2   
3   import io.atlassian.fugue.Option;
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 OptionMatchers {
12  
13    private OptionMatchers() {
14      throw new UnsupportedOperationException();
15    }
16  
17    public static <L> Matcher<Option<?>> isNone() {
18      return NoneMatcher.INSTANCE;
19    }
20  
21    public static <T> Matcher<Option<T>> isSome(Matcher<? super T> subMatcher) {
22      return new SomeMatcher<>(requireNonNull(subMatcher, "subMatcher"));
23    }
24  
25    private static class NoneMatcher extends TypeSafeMatcher<Option<?>> {
26  
27      private static final Matcher<Option<?>> INSTANCE = new NoneMatcher();
28  
29      private NoneMatcher() {}
30  
31      @Override protected boolean matchesSafely(Option<?> actual) {
32        return actual.isEmpty();
33      }
34  
35      @Override public void describeTo(Description description) {
36        description.appendText("none");
37      }
38  
39      @Override protected void describeMismatchSafely(Option<?> actual, Description mismatchDescription) {
40        actual.forEach(item -> mismatchDescription.appendText("was some"));
41      }
42    }
43  
44    private static class SomeMatcher<T> extends TypeSafeMatcher<Option<T>> {
45  
46      private final Matcher<? super T> subMatcher;
47  
48      private SomeMatcher(Matcher<? super T> subMatcher) {
49        this.subMatcher = subMatcher;
50      }
51  
52      @Override protected boolean matchesSafely(Option<T> actual) {
53        return actual.exists(subMatcher::matches);
54      }
55  
56      @Override public void describeTo(Description description) {
57        description.appendText("some that ");
58        subMatcher.describeTo(description);
59      }
60  
61      @Override protected void describeMismatchSafely(Option<T> actual, Description mismatchDescription) {
62        actual.fold(() -> {
63          mismatchDescription.appendText("was none");
64          return Unit();
65        }, item -> {
66          mismatchDescription.appendText("was some that ");
67          subMatcher.describeMismatch(item, mismatchDescription);
68          return Unit();
69        });
70      }
71    }
72  
73  }