View Javadoc
1   package io.atlassian.fugue.optic;
2   
3   import io.atlassian.fugue.Either;
4   import io.atlassian.fugue.Eithers;
5   import io.atlassian.fugue.Option;
6   
7   import java.util.function.Function;
8   
9   /**
10   * {@link PPrism} restricted to monomorphic update
11   */
12  public final class Prism<S, A> extends PPrism<S, S, A, A> {
13  
14    final PPrism<S, S, A, A> pPrism;
15  
16    public Prism(final PPrism<S, S, A, A> pPrism) {
17      this.pPrism = pPrism;
18    }
19  
20    @Override public Either<S, A> getOrModify(final S s) {
21      return pPrism.getOrModify(s);
22    }
23  
24    @Override public S reverseGet(final A a) {
25      return pPrism.reverseGet(a);
26    }
27  
28    @Override public Option<A> getOption(final S s) {
29      return pPrism.getOption(s);
30    }
31  
32    /***********************************************************/
33    /** Compose methods between a {@link Prism} and another Optics */
34    /***********************************************************/
35  
36    /**
37     * compose a {@link Prism} with a {@link Setter}
38     */
39    public final <C, D> Setter<S, C> composeSetter(final Setter<A, C> other) {
40      return new Setter<>(pPrism.composeSetter(other.pSetter));
41    }
42  
43    /**
44     * compose a {@link Prism} with a {@link Traversal}
45     */
46    public final <C, D> Traversal<S, C> composeTraversal(final Traversal<A, C> other) {
47      return new Traversal<>(pPrism.composeTraversal(other.pTraversal));
48    }
49  
50    /**
51     * compose a {@link Prism} with a {@link Optional}
52     */
53    public final <C, D> Optional<S, C> composeOptional(final Optional<A, C> other) {
54      return new Optional<>(pPrism.composeOptional(other.pOptional));
55    }
56  
57    /**
58     * compose a {@link Prism} with a {@link Lens}
59     */
60    public final <C, D> Optional<S, C> composeLens(final Lens<A, C> other) {
61      return new Optional<>(pPrism.composeLens(other.pLens));
62    }
63  
64    /**
65     * compose a {@link Prism} with a {@link Prism}
66     */
67    public final <C> Prism<S, C> composePrism(final Prism<A, C> other) {
68      return new Prism<>(pPrism.composePrism(other.pPrism));
69    }
70  
71    /**
72     * compose a {@link Prism} with an {@link Iso}
73     */
74    public final <C, D> Prism<S, C> composeIso(final Iso<A, C> other) {
75      return new Prism<>(pPrism.composeIso(other.pIso));
76    }
77  
78    /*****************************************************************/
79    /** Transformation methods to view a {@link Prism} as another Optics */
80    /*****************************************************************/
81  
82    /**
83     * view a {@link Prism} as a {@link Setter}
84     */
85    @Override public final Setter<S, A> asSetter() {
86      return new Setter<>(pPrism.asSetter());
87    }
88  
89    /**
90     * view a {@link Prism} as a {@link Traversal}
91     */
92    @Override public final Traversal<S, A> asTraversal() {
93      return new Traversal<>(pPrism.asTraversal());
94    }
95  
96    /**
97     * view a {@link Prism} as a {@link Optional}
98     */
99    @Override public final Optional<S, A> asOptional() {
100     return new Optional<>(pPrism.asOptional());
101   }
102 
103   public static <S> Prism<S, S> id() {
104     return new Prism<>(pId());
105   }
106 
107   public static <S, A> Prism<S, A> prism(final Function<S, Option<A>> getOption, final Function<A, S> reverseGet) {
108     return new Prism<>(new PPrism<S, S, A, A>() {
109 
110       @Override public Either<S, A> getOrModify(final S s) {
111         return getOption.apply(s).fold(() -> Either.<S, A> left(s), Eithers.<S, A> toRight());
112       }
113 
114       @Override public S reverseGet(final A a) {
115         return reverseGet.apply(a);
116       }
117 
118       @Override public Option<A> getOption(final S s) {
119         return getOption.apply(s);
120       }
121     });
122   }
123 
124 }