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