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 }