View Javadoc
1   package io.atlassian.fugue.extensions.step;
2   
3   import io.atlassian.fugue.Option;
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 Option} 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(Option)}
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 Option
23   * @since 4.7.0
24   */
25  public final class OptionStep5<A, B, C, D, E> {
26    private final Option<A> option1;
27    private final Option<B> option2;
28    private final Option<C> option3;
29    private final Option<D> option4;
30    private final Option<E> option5;
31  
32    OptionStep5(Option<A> option1, Option<B> option2, Option<C> option3, Option<D> option4, Option<E> option5) {
33      this.option1 = option1;
34      this.option2 = option2;
35      this.option3 = option3;
36      this.option4 = option4;
37      this.option5 = option5;
38    }
39  
40    /**
41     * Apply the provided function with the previous Step results.
42     * <p>
43     * Internally this will perform a {@link Option#flatMap(Function)} and the
44     * result 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> OptionStep6<A, B, C, D, E, F> then(
52      Function5<? super A, ? super B, ? super C, ? super D, ? super E, ? extends Option<? extends F>> functor) {
53      Option<F> option6 = option1.flatMap(value1 -> option2.flatMap(value2 -> option3.flatMap(value3 -> option4.flatMap(value4 -> option5
54        .flatMap(value5 -> functor.apply(value1, value2, value3, value4, value5))))));
55      return new OptionStep6<>(option1, option2, option3, option4, option5, option6);
56    }
57  
58    /**
59     * Apply the provided supplier with the previous Step results.
60     * <p>
61     * Internally this will perform a {@link Option#flatMap(Function)} and the
62     * supplier will become the next step value.
63     * <p>
64     * This is different to {@link #then(Function5)} in that the previous step
65     * results are not provided for the new step evaluation.
66     *
67     * @param supplier The supplier to provide the result of the flatMap with the
68     * previous step.
69     * @param <F> The type of the next step result
70     * @return The next step class
71     */
72    public <F> OptionStep6<A, B, C, D, E, F> then(Supplier<? extends Option<? extends F>> supplier) {
73      Option<F> option6 = option1.flatMap(value1 -> option2.flatMap(value2 -> option3.flatMap(value3 -> option4.flatMap(value4 -> option5
74        .flatMap(value5 -> supplier.get())))));
75      return new OptionStep6<>(option1, option2, option3, option4, option5, option6);
76    }
77  
78    /**
79     * Apply the provided predicate with the previous step results.
80     *
81     * @param predicate The check that must be satisfied by contained values
82     * @return This step class with either the same last step value, or changed to
83     * none
84     */
85    public OptionStep5<A, B, C, D, E> filter(Predicate5<? super A, ? super B, ? super C, ? super D, ? super E> predicate) {
86      Option<E> filterOption5 = option1.flatMap(value1 -> option2.flatMap(value2 -> option3.flatMap(value3 -> option4.flatMap(value4 -> option5
87        .filter(value5 -> predicate.test(value1, value2, value3, value4, value5))))));
88      return new OptionStep5<>(option1, option2, option3, option4, filterOption5);
89    }
90  
91    /**
92     * Terminating step expression, that will provide the previous steps to this
93     * function and return the result as a <code>some</code>
94     *
95     * @param functor The yield function to map on previous values
96     * @param <Z> The type for the returned result
97     * @return An Option containing this result or none
98     */
99    public <Z> Option<Z> yield(Function5<? super A, ? super B, ? super C, ? super D, ? super E, Z> functor) {
100     return option1.flatMap(value1 -> option2.flatMap(value2 -> option3.flatMap(value3 -> option4.flatMap(value4 -> option5.map(value5 -> functor
101       .apply(value1, value2, value3, value4, value5))))));
102   }
103 }