diff options
Diffstat (limited to 'src/main/java/org/pacien/lemonad/attempt/Attempt.java')
-rw-r--r-- | src/main/java/org/pacien/lemonad/attempt/Attempt.java | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/src/main/java/org/pacien/lemonad/attempt/Attempt.java b/src/main/java/org/pacien/lemonad/attempt/Attempt.java new file mode 100644 index 0000000..fc437ad --- /dev/null +++ b/src/main/java/org/pacien/lemonad/attempt/Attempt.java | |||
@@ -0,0 +1,129 @@ | |||
1 | /* | ||
2 | * lemonad - Some functional sweetness for Java | ||
3 | * Copyright (C) 2019 Pacien TRAN-GIRARD | ||
4 | * | ||
5 | * This program is free software: you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU Affero General Public License as | ||
7 | * published by the Free Software Foundation, either version 3 of the | ||
8 | * License, or (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Affero General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Affero General Public License | ||
16 | * along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | |||
19 | package org.pacien.lemonad.attempt; | ||
20 | |||
21 | import java.util.function.Consumer; | ||
22 | import java.util.function.Function; | ||
23 | |||
24 | import lombok.NonNull; | ||
25 | |||
26 | /** | ||
27 | * Wraps either a value from a success or an error from a failure. | ||
28 | * | ||
29 | * @param <R> the potential wrapped result type. | ||
30 | * @param <E> the potential error type. | ||
31 | * @author pacien | ||
32 | */ | ||
33 | public interface Attempt<R, E> { | ||
34 | /** | ||
35 | * @return whether the {@link Attempt} is successful. | ||
36 | */ | ||
37 | boolean isSuccess(); | ||
38 | |||
39 | /** | ||
40 | * @return whether the {@link Attempt} is failed. | ||
41 | */ | ||
42 | boolean isFailure(); | ||
43 | |||
44 | /** | ||
45 | * @return the result if this {@link Attempt} is a success. | ||
46 | * @throws java.util.NoSuchElementException if this {@link Attempt} is a failure. | ||
47 | */ | ||
48 | R getResult(); | ||
49 | |||
50 | /** | ||
51 | * @return the error if this {@link Attempt} is a failure. | ||
52 | * @throws java.util.NoSuchElementException if this {@link Attempt} is a success. | ||
53 | */ | ||
54 | E getError(); | ||
55 | |||
56 | /** | ||
57 | * @param resultConsumer a {@link Consumer} of result called if the {@link Attempt} is a success. | ||
58 | * @return the current {@link Attempt} | ||
59 | */ | ||
60 | default Attempt<R, E> ifSuccess(@NonNull Consumer<? super R> resultConsumer) { | ||
61 | if (isSuccess()) resultConsumer.accept(getResult()); | ||
62 | return this; | ||
63 | } | ||
64 | |||
65 | /** | ||
66 | * @param errorConsumer a {@link Consumer} of error called if the {@link Attempt} is a failure. | ||
67 | * @return the current {@link Attempt} | ||
68 | */ | ||
69 | default Attempt<R, E> ifFailure(@NonNull Consumer<? super E> errorConsumer) { | ||
70 | if (isFailure()) errorConsumer.accept(getError()); | ||
71 | return this; | ||
72 | } | ||
73 | |||
74 | /** | ||
75 | * @param mapper a function producing an {@link Attempt}, called with the current result if this {@link Attempt} is a success. | ||
76 | * @return this {@link Attempt} if it is a failure, or the produced one otherwise. | ||
77 | */ | ||
78 | default <RR> Attempt<RR, E> mapResult(@NonNull Function<? super R, ? extends Attempt<? extends RR, ? extends E>> mapper) { | ||
79 | //noinspection unchecked | ||
80 | return (Attempt<RR, E>) (isSuccess() ? mapper.apply(getResult()) : this); | ||
81 | } | ||
82 | |||
83 | /** | ||
84 | * @param mapper a function producing an {@link Attempt}, called with the current error if this {@link Attempt} is a failure. | ||
85 | * @return this {@link Attempt} if it is a success, or the alternative {@link Attempt} retrieved from the supplier otherwise. | ||
86 | */ | ||
87 | default <EE> Attempt<R, EE> mapFailure(@NonNull Function<? super E, ? extends Attempt<? extends R, ? extends EE>> mapper) { | ||
88 | //noinspection unchecked | ||
89 | return (Attempt<R, EE>) (isFailure() ? mapper.apply(getError()) : this); | ||
90 | } | ||
91 | |||
92 | /** | ||
93 | * @param mapper a function transforming an {@link Attempt}. | ||
94 | * @return the transformed {@link Attempt} | ||
95 | */ | ||
96 | default <RR, EE> Attempt<RR, EE> flatMap(@NonNull Function<? super Attempt<? super R, ? super E>, ? extends Attempt<? extends RR, ? extends EE>> mapper) { | ||
97 | //noinspection unchecked | ||
98 | return (Attempt<RR, EE>) mapper.apply(this); | ||
99 | } | ||
100 | |||
101 | /** | ||
102 | * @param result the result of the {@link Attempt}. | ||
103 | * @return a successful {@link Attempt} wrapping the supplied result. | ||
104 | */ | ||
105 | static <R, E> Attempt<R, E> success(R result) { | ||
106 | return new Success<>(result); | ||
107 | } | ||
108 | |||
109 | /** | ||
110 | * @param error the cause of the failure of the {@link Attempt}. | ||
111 | * @return a failed {@link Attempt} with the supplied error. | ||
112 | */ | ||
113 | static <R, E> Attempt<R, E> failure(E error) { | ||
114 | return new Failure<>(error); | ||
115 | } | ||
116 | |||
117 | /** | ||
118 | * @param supplier a {@code Supplier} that may throw an {@link Throwable}. | ||
119 | * @return an {@link Attempt} wrapping either the result of the execution of the supplier or any thrown {@link Throwable}. | ||
120 | */ | ||
121 | static <R, E extends Throwable> Attempt<R, E> attempt(@NonNull ThrowingSupplier<? extends R, ? extends E> supplier) { | ||
122 | try { | ||
123 | return success(supplier.get()); | ||
124 | } catch (Throwable throwable) { | ||
125 | //noinspection unchecked | ||
126 | return (Attempt<R, E>) failure(throwable); | ||
127 | } | ||
128 | } | ||
129 | } | ||