View Javadoc
1   package io.atlassian.fugue.extensions.step;
2   
3   import io.atlassian.fugue.Either;
4   
5   import java.util.function.Function;
6   import java.util.function.Predicate;
7   import java.util.function.Supplier;
8   
9   /**
10   * The first step of the {@link Either} type.
11   * <p>
12   * This class is not intended to be contructed manually, and should only be used
13   * as part of a {@link Steps} chain, started by {@link Steps#begin(Either)}
14   *
15   * @param <A> The right hand side type of the first defined right value
16   * @param <LEFT> The left hand side type of the Either result
17   * @see Steps for usage examples
18   * @see Either
19   * @since 4.7.0
20   */
21  public final class EitherStep1<A, LEFT> {
22  
23    private final Either<LEFT, A> either1;
24  
25    EitherStep1(Either<LEFT, A> either1) {
26      this.either1 = either1;
27    }
28  
29    /**
30     * Apply the provided function with the previous Step results.
31     * <p>
32     * Internally this will perform a {@link Either#flatMap(Function)} and the
33     * result will become the next step value.
34     *
35     * @param functor The functor to be applied as a flatMap with the previous
36     * step
37     * @param <B> The right hand side type of the next step result
38     * @param <LL> The left hand side type of the result that must be related to
39     * {@link LEFT}
40     * @return The next step class
41     */
42    public <B, LL extends LEFT> EitherStep2<A, B, LEFT> then(Function<? super A, Either<LL, B>> functor) {
43      Either<LEFT, B> either2 = either1.flatMap(functor);
44      return new EitherStep2<>(either1, either2);
45    }
46  
47    /**
48     * Apply the provided supplier with the previous Step results.
49     * <p>
50     * Internally this will perform a {@link Either#flatMap(Function)} and the
51     * supplier will become the next step value.
52     * <p>
53     * This is different to {@link #then(Function)} in that the previous step
54     * results are not provided for the new step evaluation.
55     *
56     * @param supplier The supplier to provide the result of the flatMap with the
57     * previous step.
58     * @param <B> The right hand side type of the next step result
59     * @param <LL> The left hand side type of the result that must be related to
60     * {@link LEFT}
61     * @return The next step class
62     */
63    public <B, LL extends LEFT> EitherStep2<A, B, LEFT> then(Supplier<Either<LL, B>> supplier) {
64      Either<LEFT, B> either2 = either1.flatMap(value1 -> supplier.get());
65      return new EitherStep2<>(either1, either2);
66    }
67  
68    /**
69     * Apply the provided predicate with the previous step results.
70     * <p>
71     * If the predicate is not satisfied then the unsatisfiedSupplier is used to
72     * populate the left value that will prevent any further steps evaluation.
73     *
74     * @param predicate The check that must be satisfied by contained values
75     * @param unsatisfiedSupplier Provide the value to populate the left if not
76     * satisfied
77     * @return This step class with either the same last step value, or changed to
78     * a left
79     */
80    public EitherStep1<A, LEFT> filter(Predicate<? super A> predicate, Supplier<? extends LEFT> unsatisfiedSupplier) {
81      Either<LEFT, A> filterEither1 = either1.filterOrElse(predicate, unsatisfiedSupplier);
82      return new EitherStep1<>(filterEither1);
83    }
84  
85    /**
86     * Terminating step expression, that will provide the previous steps to this
87     * function and return the result as a <code>Right</code>
88     *
89     * @param functor The yield function to map on previous values
90     * @param <Z> The right hand side type for the returned result
91     * @return An Either with the result of this function on right, or the
92     * existing left
93     */
94    public <Z> Either<LEFT, Z> yield(Function<? super A, Z> functor) {
95      return either1.map(functor);
96    }
97  
98  }