1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.opencastproject.util.data;
23
24 import static org.opencastproject.util.data.Tuple.tuple;
25
26 import com.entwinemedia.fn.data.Opt;
27
28 import java.util.ArrayList;
29 import java.util.Collections;
30 import java.util.Iterator;
31 import java.util.List;
32
33
34
35
36
37
38 public abstract class Option<A> implements Iterable<A> {
39 private Option() {
40 }
41
42
43 public abstract <B> B fold(Match<A, B> visitor);
44
45 public abstract Option<A> foreach(Function<? super A, Void> f);
46
47 public abstract <B> Option<B> fmap(Function<? super A, ? extends B> f);
48
49 public <B> Option<B> map(Function<? super A, ? extends B> f) {
50 return fmap(f);
51 }
52
53
54 public abstract <B> Option<B> bind(Function<A, Option<B>> f);
55
56 public <B> Option<B> flatMap(Function<A, Option<B>> f) {
57 return bind(f);
58 }
59
60 public abstract boolean isSome();
61
62 public boolean isNone() {
63 return !isSome();
64 }
65
66
67 public Option<A> orElse(Option<A> none) {
68 return isSome() ? this : none;
69 }
70
71
72 public Option<A> orElse(Function0<Option<A>> none) {
73 return isSome() ? this : none.apply();
74 }
75
76
77 public <T extends Throwable> Option<A> orError(T none) throws T {
78 if (isSome())
79 return this;
80 else
81 throw none;
82 }
83
84 public <B> Option<Tuple<A, B>> and(Option<B> b) {
85 if (isSome() && b.isSome()) {
86 return some(tuple(get(), b.get()));
87 } else {
88 return none();
89 }
90 }
91
92
93 public abstract A get();
94
95
96 public abstract A getOrElse(A none);
97
98
99 public abstract A getOrElse(Function0<A> none);
100
101
102 public abstract A getOrElseNull();
103
104
105 public abstract List<A> list();
106
107 public abstract Opt<A> toOpt();
108
109 @Override
110 public abstract int hashCode();
111
112 @Override
113 public abstract boolean equals(Object o);
114
115
116
117
118 public static <A> Option<A> some(final A a) {
119 if (a == null)
120 throw new Error("null must not be wrapped in a some");
121 return new Option<A>() {
122 @Override
123 public <B> B fold(Match<A, B> visitor) {
124 return visitor.some(a);
125 }
126
127 @Override
128 public Option<A> foreach(Function<? super A, Void> f) {
129 f.apply(a);
130 return this;
131 }
132
133 @Override
134 public <B> Option<B> fmap(Function<? super A, ? extends B> f) {
135 B b = f.apply(a);
136 return some(b);
137 }
138
139 @Override
140 public <B> Option<B> bind(Function<A, Option<B>> f) {
141 return f.apply(a);
142 }
143
144 @Override
145 public boolean isSome() {
146 return true;
147 }
148
149 @Override
150 public A get() {
151 return a;
152 }
153
154 @Override
155 public A getOrElse(A none) {
156 return a;
157 }
158
159 @Override
160 public A getOrElse(Function0<A> none) {
161 return a;
162 }
163
164 @Override
165 public A getOrElseNull() {
166 return a;
167 }
168
169 @Override
170 public Iterator<A> iterator() {
171 return Collections.singletonList(a).iterator();
172 }
173
174 @Override
175 public List<A> list() {
176 return Collections.singletonList(a);
177 }
178
179 @Override
180 public Opt<A> toOpt() {
181 return Opt.some(a);
182 }
183
184 @Override
185 public int hashCode() {
186
187 return a.hashCode();
188 }
189
190 @Override
191 public boolean equals(Object o) {
192 if (o instanceof Option) {
193 Option<?> opt = (Option<?>) o;
194
195 return opt.isSome() && a.equals(opt.get());
196 } else {
197 return false;
198 }
199 }
200
201 @Override
202 public String toString() {
203 return "Some(" + a + ")";
204 }
205 };
206 }
207
208
209 public static <A> Option<A> none() {
210 return new Option<A>() {
211 @Override
212 public <B> B fold(Match<A, B> visitor) {
213 return visitor.none();
214 }
215
216 @Override
217 public Option<A> foreach(Function<? super A, Void> f) {
218 return this;
219 }
220
221 @Override
222 public <B> Option<B> fmap(Function<? super A, ? extends B> f) {
223 return none();
224 }
225
226 @Override
227 public <B> Option<B> bind(Function<A, Option<B>> f) {
228 return none();
229 }
230
231 @Override
232 public boolean isSome() {
233 return false;
234 }
235
236 @Override
237 public A get() {
238 throw new IllegalStateException("a none does not contain a value");
239 }
240
241 @Override
242 public A getOrElse(A none) {
243 return none;
244 }
245
246 @Override
247 public A getOrElse(Function0<A> none) {
248 return none.apply();
249 }
250
251 @Override
252 public A getOrElseNull() {
253 return null;
254 }
255
256 @Override
257 public Iterator<A> iterator() {
258 return new ArrayList<A>().iterator();
259 }
260
261 @Override
262 public List<A> list() {
263 return Collections.emptyList();
264 }
265
266 @Override
267 public Opt<A> toOpt() {
268 return Opt.none();
269 }
270
271 @Override
272 public int hashCode() {
273 return -1;
274 }
275
276 @Override
277 public boolean equals(Object o) {
278 return o instanceof Option && ((Option) o).isNone();
279 }
280
281 @Override
282 public String toString() {
283 return "None";
284 }
285 };
286 }
287
288
289
290
291
292
293
294 public static <A> Option<A> none(A example) {
295 return none();
296 }
297
298
299 public static <A> Option<A> none(Class<A> clazz) {
300 return none();
301 }
302
303
304 public static <A> Option<A> option(A a) {
305 if (a != null)
306 return some(a);
307 else
308 return none();
309 }
310
311
312 public static <A> Option<A> fromOpt(Opt<A> a) {
313 for (A x : a) {
314 return some(x);
315 }
316 return none();
317 }
318
319
320
321
322
323
324
325 @Deprecated
326 public static <A> Function0<A> error(final String message) {
327 return new Function0<A>() {
328 @Override
329 public A apply() {
330 throw new Error(message);
331 }
332 };
333 }
334
335
336
337
338
339
340
341
342
343 public static Function<String, Boolean> eq(final String compare) {
344 return new Function<String, Boolean>() {
345 @Override
346 public Boolean apply(String s) {
347 return compare.equals(s);
348 }
349 };
350 }
351
352 public interface Match<A, B> {
353 B some(A a);
354
355 B none();
356 }
357
358
359 public abstract static class EMatch<A> implements Match<A, Void> {
360 @Override
361 public final Void some(A a) {
362 esome(a);
363 return null;
364 }
365
366 @Override
367 public final Void none() {
368 enone();
369 return null;
370 }
371
372 protected abstract void esome(A a);
373
374 protected abstract void enone();
375 }
376 }