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