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