View Javadoc

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