1 package io.atlassian.fugue.optic.law;
2
3 import io.atlassian.fugue.Either;
4 import io.atlassian.fugue.Eithers;
5 import io.atlassian.fugue.Option;
6 import io.atlassian.fugue.Options;
7 import io.atlassian.fugue.Pair;
8 import io.atlassian.fugue.Suppliers;
9 import io.atlassian.fugue.law.IsEq;
10 import io.atlassian.fugue.optic.POptional;
11
12 import java.util.Collections;
13 import java.util.List;
14 import java.util.function.Function;
15
16 import static io.atlassian.fugue.law.IsEq.isEq;
17 import static java.util.Spliterator.ORDERED;
18 import static java.util.Spliterators.spliteratorUnknownSize;
19 import static java.util.stream.Collectors.toList;
20 import static java.util.stream.StreamSupport.stream;
21
22 public final class OptionalLaws<S, A> {
23
24 private final POptional<S, S, A, A> optional;
25
26 public OptionalLaws(POptional<S, S, A, A> optional) {
27 this.optional = optional;
28 }
29
30
31
32
33 public IsEq<S> getOptionSet(S s) {
34 return isEq(optional.getOrModify(s).fold(Function.identity(), a -> optional.set(a).apply(s)), s);
35 }
36
37
38
39
40 public IsEq<Option<A>> setGetOption(S s, A a) {
41 return isEq(optional.getOption(optional.set(a).apply(s)), optional.getOption(s).map(__ -> a));
42 }
43
44
45
46
47 public IsEq<S> setIdempotent(S s, A a) {
48 return isEq(optional.set(a).apply(optional.set(a).apply(s)), optional.set(a).apply(s));
49 }
50
51
52
53
54 public IsEq<S> modifyIdentity(S s) {
55 return isEq(optional.modify(Function.<A> identity()).apply(s), s);
56 }
57
58
59
60
61 public IsEq<S> modifySupplierFPoint(S s) {
62 return isEq(optional.modifySupplierF(Suppliers::ofInstance).apply(s).get(), s);
63 }
64
65
66
67
68 public IsEq<Either<String, S>> modifyEitherFPoint(S s) {
69 return isEq(optional.<String> modifyEitherF(Eithers.toRight()).apply(s), Either.right(s));
70 }
71
72
73
74
75 public IsEq<Option<S>> modifyOptionFPoint(S s) {
76 return isEq(optional.modifyOptionF(Options.toOption()).apply(s), Option.some(s));
77 }
78
79
80
81
82 public IsEq<Pair<S, S>> modifyPairFPoint(S s) {
83 return isEq(optional.modifyPairF(a -> Pair.pair(a, a)).apply(s), Pair.pair(s, s));
84 }
85
86
87
88
89 public IsEq<S> modifyFunctionFPoint(S s) {
90 return isEq(optional.<String> modifyFunctionF(a -> __ -> a).apply(s).apply(""), s);
91 }
92
93
94
95
96 public IsEq<List<S>> modifyIterableFPoint(S s) {
97 return isEq(stream(spliteratorUnknownSize(optional.modifyIterableF(Collections::singleton).apply(s).iterator(), ORDERED), false)
98 .collect(toList()), Collections.singletonList(s));
99 }
100
101
102
103
104 public IsEq<Option<S>> setOption(S s, A a) {
105 return isEq(optional.setOption(a).apply(s), optional.getOption(s).map(__ -> optional.set(a).apply(s)));
106 }
107
108
109
110
111 public IsEq<Option<S>> modifyOptionIdentity(S s) {
112 return isEq(optional.modifyOption(Function.identity()).apply(s), optional.getOption(s).map(__ -> s));
113 }
114 }