View Javadoc
1   package io.atlassian.fugue.extensions.step;
2   
3   import io.atlassian.fugue.Try;
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 Try} 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(Try)}
14   *
15   * @param <A> The type of the first defined value
16   * @see Steps for usage examples
17   * @see Try
18   * @since 4.7.0
19   */
20  public final class TryStep1<A> {
21  
22    private final Try<A> try1;
23  
24    TryStep1(Try<A> try1) {
25      this.try1 = try1;
26    }
27  
28    /**
29     * Apply the provided function with the previous Step results.
30     * <p>
31     * Internally this will perform a {@link Try#flatMap(Function)} and the result
32     * will become the next step value.
33     *
34     * @param functor The functor to be applied as a flatMap with the previous
35     * step
36     * @param <B> The right hand side type of the next step result
37     * @return The next step class
38     */
39    public <B> TryStep2<A, B> then(Function<? super A, Try<B>> functor) {
40      Try<B> try2 = try1.flatMap(functor);
41      return new TryStep2<>(try1, try2);
42    }
43  
44    /**
45     * Apply the provided supplier with the previous Step results.
46     * <p>
47     * Internally this will perform a {@link Try#flatMap(Function)} and the
48     * supplier will become the next step value.
49     * <p>
50     * This is different to {@link #then(Function)} in that the previous step
51     * results are not provided for the new step evaluation.
52     *
53     * @param supplier The supplier to provide the result of the flatMap with the
54     * previous step.
55     * @param <B> The type of the next step result
56     * @return The next step class
57     */
58    public <B> TryStep2<A, B> then(Supplier<Try<B>> supplier) {
59      Try<B> either2 = try1.flatMap(value1 -> supplier.get());
60      return new TryStep2<>(try1, either2);
61    }
62  
63    /**
64     * Apply the provided predicate with the previous step results.
65     * <p>
66     * If the predicate is not satisfied then the unsatisfiedSupplier is used to
67     * populate the failure value that will prevent any further steps evaluation.
68     *
69     * @param predicate The check that must be satisfied by contained values
70     * @param unsatisfiedSupplier Provide the value to populate the failure if not
71     * satisfied
72     * @return This step class with either the same last step value, or changed to
73     * a failure
74     */
75    public TryStep1<A> filter(Predicate<? super A> predicate, Supplier<Exception> unsatisfiedSupplier) {
76      Try<A> filterTry1 = try1.filterOrElse(predicate, unsatisfiedSupplier);
77      return new TryStep1<>(filterTry1);
78    }
79  
80    /**
81     * Terminating step expression, that will provide the previous steps to this
82     * function and return the result as a <code>Success</code>
83     *
84     * @param functor The yield function to map on previous values
85     * @param <Z> The type for the returned result
86     * @return A Try containing this result as success or failure
87     */
88    public <Z> Try<Z> yield(Function<? super A, Z> functor) {
89      return try1.map(functor);
90    }
91  
92  }