1 package io.atlassian.fugue;
2
3 import java.util.ArrayList;
4 import java.util.NoSuchElementException;
5 import java.util.function.Function;
6 import java.util.function.Supplier;
7
8 import static java.util.Collections.unmodifiableList;
9 import static java.util.Objects.requireNonNull;
10 import static java.util.function.Function.identity;
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 public abstract class Try<A> {
27
28
29
30
31
32
33
34 public static <A> Try<A> failure(final Exception e) {
35 return new Failure<>(e);
36 }
37
38
39
40
41
42
43
44
45 public static <A> Try<A> successful(final A value) {
46 return new Success<>(value);
47 }
48
49
50
51
52
53
54
55
56
57
58 public static <A> Try<Iterable<A>> sequence(Iterable<Try<A>> trys) {
59 final ArrayList<A> ts = new ArrayList<>();
60 for (final Try<A> t : trys) {
61 if (t.isFailure()) {
62 return new Failure<>(t.fold(identity(), x -> {
63 throw new NoSuchElementException();
64 }));
65 }
66 ts.add(t.fold(f -> {
67 throw new NoSuchElementException();
68 }, identity()));
69 }
70 return new Success<>(unmodifiableList(ts));
71 }
72
73
74
75
76
77
78
79
80 public static <A> Try<A> flatten(Try<Try<A>> t) {
81 return t.flatMap(identity());
82 }
83
84
85
86
87
88
89 public abstract boolean isFailure();
90
91
92
93
94
95
96 public abstract boolean isSuccess();
97
98
99
100
101
102
103
104
105
106 public abstract <B> Try<B> flatMap(Function<? super A, Try<B>> f);
107
108
109
110
111
112
113
114
115
116
117 public abstract <B> Try<B> map(Function<? super A, ? extends B> f);
118
119
120
121
122
123
124
125
126
127 public abstract Try<A> recover(Function<? super Exception, A> f);
128
129
130
131
132
133
134
135
136
137
138
139
140 public abstract <X extends Exception> Try<A> recover(Class<X> exceptionType, Function<? super X, A> f);
141
142
143
144
145
146
147
148
149
150 public abstract Try<A> recoverWith(Function<? super Exception, Try<A>> f);
151
152
153
154
155
156
157
158
159
160
161
162
163 public abstract <X extends Exception> Try<A> recoverWith(Class<X> exceptionType, Function<? super X, Try<A>> f);
164
165
166
167
168
169
170
171
172 public abstract A getOrElse(Supplier<A> s);
173
174
175
176
177
178
179
180
181
182
183 public abstract <B> B fold(Function<? super Exception, B> failureF, Function<A, B> successF);
184
185
186
187
188
189
190
191
192 public abstract Either<Exception, A> toEither();
193
194
195
196
197
198
199
200
201 public abstract Option<A> toOption();
202
203 private static final class Failure<A> extends Try<A> {
204
205 private final Exception e;
206
207 Failure(final Exception e) {
208 this.e = requireNonNull(e);
209 }
210
211 @Override public <B> Try<B> map(final Function<? super A, ? extends B> f) {
212 return new Failure<>(e);
213 }
214
215 @Override public boolean isFailure() {
216 return true;
217 }
218
219 @Override public boolean isSuccess() {
220 return false;
221 }
222
223 @Override public <B> Try<B> flatMap(final Function<? super A, Try<B>> f) {
224 return Try.failure(e);
225 }
226
227 @Override public Try<A> recover(final Function<? super Exception, A> f) {
228 return Checked.of(() -> f.apply(e));
229 }
230
231 @SuppressWarnings("unchecked") @Override public <X extends Exception> Try<A> recover(final Class<X> exceptionType, final Function<? super X, A> f) {
232 return exceptionType.isAssignableFrom(e.getClass()) ? Checked.of(() -> f.apply((X) e)) : this;
233 }
234
235 @Override public Try<A> recoverWith(final Function<? super Exception, Try<A>> f) {
236 return f.apply(e);
237 }
238
239 @SuppressWarnings("unchecked") @Override public <X extends Exception> Try<A> recoverWith(Class<X> exceptionType, Function<? super X, Try<A>> f) {
240 return exceptionType.isAssignableFrom(e.getClass()) ? f.apply((X) e) : this;
241 }
242
243 @Override public A getOrElse(final Supplier<A> s) {
244 return s.get();
245 }
246
247 @Override public <B> B fold(final Function<? super Exception, B> failureF, final Function<A, B> successF) {
248 return failureF.apply(e);
249 }
250
251 @Override public Either<Exception, A> toEither() {
252 return Either.left(e);
253 }
254
255 @Override public Option<A> toOption() {
256 return Option.none();
257 }
258
259 @Override public boolean equals(final Object o) {
260 if (this == o) {
261 return true;
262 }
263 if (o == null || getClass() != o.getClass()) {
264 return false;
265 }
266
267 final Failure<?> failure = (Failure<?>) o;
268
269 return e != null ? e.equals(failure.e) : failure.e == null;
270 }
271
272 @Override public int hashCode() {
273 return ~e.hashCode();
274 }
275 }
276
277 private static final class Success<A> extends Try<A> {
278
279 private final A value;
280
281 Success(final A value) {
282 this.value = requireNonNull(value);
283 }
284
285 @Override public <B> Try<B> map(final Function<? super A, ? extends B> f) {
286 return Checked.of(() -> f.apply(value));
287 }
288
289 @Override public boolean isFailure() {
290 return false;
291 }
292
293 @Override public boolean isSuccess() {
294 return true;
295 }
296
297 @Override public <B> Try<B> flatMap(final Function<? super A, Try<B>> f) {
298 return f.apply(value);
299 }
300
301 @Override public Try<A> recover(final Function<? super Exception, A> f) {
302 return this;
303 }
304
305 @Override public <X extends Exception> Try<A> recover(final Class<X> exceptionType, final Function<? super X, A> f) {
306 return this;
307 }
308
309 @Override public Try<A> recoverWith(final Function<? super Exception, Try<A>> f) {
310 return this;
311 }
312
313 @Override public <X extends Exception> Try<A> recoverWith(final Class<X> exceptionType, final Function<? super X, Try<A>> f) {
314 return this;
315 }
316
317 @Override public A getOrElse(final Supplier<A> s) {
318 return value;
319 }
320
321 @Override public <B> B fold(final Function<? super Exception, B> failureF, final Function<A, B> successF) {
322 return successF.apply(value);
323 }
324
325 @Override public Either<Exception, A> toEither() {
326 return Either.right(value);
327 }
328
329 @Override public Option<A> toOption() {
330 return Option.some(value);
331 }
332
333 @Override public boolean equals(final Object o) {
334 if (this == o) {
335 return true;
336 }
337 if (o == null || getClass() != o.getClass()) {
338 return false;
339 }
340 final Success<?> success = (Success<?>) o;
341 return value != null ? value.equals(success.value) : success.value == null;
342 }
343
344 @Override public int hashCode() {
345 return value.hashCode();
346 }
347 }
348 }