View Javadoc
1   package io.atlassian.fugue.extensions.step;
2   
3   import io.atlassian.fugue.Try;
4   import io.atlassian.fugue.extensions.functions.Function5;
5   import io.atlassian.fugue.extensions.functions.Predicate5;
6   
7   import java.util.function.Function;
8   import java.util.function.Supplier;
9   
10  /**
11   * The fifth step of the {@link Try} type.
12   * <p>
13   * This class is not intended to be contructed manually, and should only be used
14   * as part of a {@link Steps} chain, started by {@link Steps#begin(Try)}
15   *
16   * @param <A> The type of the first defined value
17   * @param <B> The type of the second defined value
18   * @param <C> The type of the third defined value
19   * @param <D> The type of the fourth defined value
20   * @param <E> The type of the fifth defined value
21   * @see Steps for usage examples
22   * @see Try
23   * @since 4.7.0
24   */
25  public final class TryStep5<A, B, C, D, E> {
26    private final Try<A> try1;
27    private final Try<B> try2;
28    private final Try<C> try3;
29    private final Try<D> try4;
30    private final Try<E> try5;
31  
32    TryStep5(Try<A> try1, Try<B> try2, Try<C> try3, Try<D> try4, Try<E> try5) {
33      this.try1 = try1;
34      this.try2 = try2;
35      this.try3 = try3;
36      this.try4 = try4;
37      this.try5 = try5;
38    }
39  
40    /**
41     * Apply the provided function with the previous Step results.
42     * <p>
43     * Internally this will perform a {@link Try#flatMap(Function)} and the result
44     * will become the next step value.
45     *
46     * @param functor The functor to be applied as a flatMap with the previous
47     * steps
48     * @param <F> The type of the next step result
49     * @return The next step class
50     */
51    public <F> TryStep6<A, B, C, D, E, F> then(Function5<? super A, ? super B, ? super C, ? super D, ? super E, Try<F>> functor) {
52      Try<F> try6 = try1.flatMap(value1 -> try2.flatMap(value2 -> try3.flatMap(value3 -> try4.flatMap(value4 -> try5.flatMap(value5 -> functor.apply(
53        value1, value2, value3, value4, value5))))));
54      return new TryStep6<>(try1, try2, try3, try4, try5, try6);
55    }
56  
57    /**
58     * Apply the provided supplier with the previous Step results.
59     * <p>
60     * Internally this will perform a {@link Try#flatMap(Function)} and the
61     * supplier will become the next step value.
62     * <p>
63     * This is different to {@link #then(Function5)} in that the previous step
64     * results are not provided for the new step evaluation.
65     *
66     * @param supplier The supplier to provide the result of the flatMap with the
67     * previous step.
68     * @param <F> The type of the next step result
69     * @return The next step class
70     */
71    public <F> TryStep6<A, B, C, D, E, F> then(Supplier<Try<F>> supplier) {
72      Try<F> try6 = try1
73        .flatMap(value1 -> try2.flatMap(value2 -> try3.flatMap(value3 -> try4.flatMap(value4 -> try5.flatMap(value5 -> supplier.get())))));
74      return new TryStep6<>(try1, try2, try3, try4, try5, try6);
75    }
76  
77    /**
78     * Apply the provided predicate with the previous step results.
79     * <p>
80     * If the predicate is not satisfied then the unsatisfiedSupplier is used to
81     * populate the failure value that will prevent any further steps evaluation.
82     *
83     * @param predicate The check that must be satisfied by contained values
84     * @param unsatisfiedSupplier Provide the value to populate the failure if not
85     * satisfied
86     * @return This step class with either the same last step value, or changed to
87     * a failure
88     */
89    public TryStep5<A, B, C, D, E> filter(Predicate5<? super A, ? super B, ? super C, ? super D, ? super E> predicate,
90      Supplier<Exception> unsatisfiedSupplier) {
91      Try<E> filterTry5 = try1.flatMap(value1 -> try2.flatMap(value2 -> try3.flatMap(value3 -> try4.flatMap(value4 -> try5.filterOrElse(
92        value5 -> predicate.test(value1, value2, value3, value4, value5), unsatisfiedSupplier)))));
93      return new TryStep5<>(try1, try2, try3, try4, filterTry5);
94    }
95  
96    /**
97     * Terminating step expression, that will provide the previous steps to this
98     * function and return the result as a <code>Success</code>
99     *
100    * @param functor The yield function to map on previous values
101    * @param <Z> The type for the returned result
102    * @return A Try containing this result as success or failure
103    */
104   public <Z> Try<Z> yield(Function5<? super A, ? super B, ? super C, ? super D, ? super E, Z> functor) {
105     return try1.flatMap(value1 -> try2.flatMap(value2 -> try3.flatMap(value3 -> try4.flatMap(value4 -> try5.map(value5 -> functor.apply(value1,
106       value2, value3, value4, value5))))));
107   }
108 }