1 package org.apache.archiva.common;
2
3 /*
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 */
21
22 import java.util.function.Function;
23
24 /**
25 * This is a class that can be used for the Try monad
26 *
27 * The Try monad is able to collect exceptions during processing
28 * of a stream.
29 *
30 *
31 *
32 */
33 public abstract class Try<V> {
34
35 private Try() {
36
37 }
38
39 public abstract Boolean isSuccess();
40
41 public abstract Boolean isFailure();
42
43 public abstract void throwException();
44
45 /**
46 * Returns the value if this is a success instance. Otherwise throws
47 * a runtime exception with the stored throwable as cause.
48 *
49 * @return The value
50 */
51 public abstract V get();
52
53 /**
54 * Returns the throwable that is stored in the failure.
55 *
56 * @return The Throwable or null.
57 */
58 public abstract Throwable getError();
59
60
61 /**
62 * A mapping method for mapping the current instance to a new type.
63 *
64 * @param fn
65 * @param <U>
66 * @return
67 */
68 public <U> Try<U> map(Function<? super V, U> fn) {
69 try {
70 return Try.success(fn.apply(get()));
71 } catch (Throwable e) {
72 return Try.failure(e);
73 }
74 }
75
76 /**
77 * This is the bind method.
78 * If this instance is success the function will be applied. If any error occurs
79 * a failure instance will be returned.
80 * If this instance is failure a new failure will be returned.
81 *
82 * @param fn
83 * @param <U>
84 * @return
85 */
86 public <U> Try<U> flatMap(Function<? super V, Try<U>> fn) {
87 try {
88 return fn.apply(get());
89 } catch (Throwable t) {
90 return Try.failure(t);
91 }
92 }
93
94 public static <V> Try<V> failure(String message) {
95
96 return new Failure<>(message);
97
98 }
99
100 public static <V> Try<V> failure(String message, Throwable e) {
101
102 return new Failure<>(message, e);
103
104 }
105
106 /**
107 * If you need type coercion, you should call this method as
108 * Try.<YOUR_TYPE>failure(e)
109 *
110 *
111 *
112 * @param e The exception that is thrown
113 * @param <V> The generic type this monad keeps
114 * @return A new Try instance that represents a failure.
115 */
116 public static <V> Try<V> failure(Throwable e) {
117
118 return new Failure<>(e);
119
120 }
121
122
123 /**
124 * Returns a instance for the success case.
125 *
126 * @param value The value that should be stored.
127 * @param <V> The return type
128 * @return A new Try instance with the given value
129 */
130 public static <V> Try<V> success(V value) {
131
132 return new Success<>(value);
133
134 }
135
136 private static class Failure<V> extends Try<V> {
137
138 private Throwable exception;
139
140 public Failure(String message) {
141
142 super();
143
144 this.exception = new IllegalStateException(message);
145
146 }
147
148 public Failure(String message, Throwable e) {
149
150 super();
151
152 this.exception = new IllegalStateException(message, e);
153
154 }
155
156 public Failure(Throwable e) {
157
158 super();
159
160 this.exception = new IllegalStateException(e);
161
162 }
163
164 @Override
165
166 public Boolean isSuccess() {
167
168 return false;
169
170 }
171
172 @Override
173
174 public Boolean isFailure() {
175
176 return true;
177
178 }
179
180 @Override
181
182 public void throwException() {
183
184 throw new RuntimeException(this.exception);
185
186 }
187
188 @Override
189 public V get() {
190 throw new RuntimeException(this.exception);
191 }
192
193 @Override
194 public Throwable getError() {
195 return exception;
196 }
197 }
198
199 private static class Success<V> extends Try<V> {
200
201 private V value;
202
203 public Success(V value) {
204
205 super();
206
207 this.value = value;
208
209 }
210
211 @Override
212
213 public Boolean isSuccess() {
214
215 return true;
216
217 }
218
219 @Override
220
221 public Boolean isFailure() {
222
223 return false;
224
225 }
226
227 @Override
228
229 public void throwException() {
230
231 //log.error("Method throwException() called on a Success instance");
232
233 }
234
235 @Override
236 public V get() {
237 return value;
238 }
239
240 @Override
241 public Throwable getError() {
242 return null;
243 }
244 }
245
246 // various method such as map an flatMap
247
248
249 @Override
250 public String toString() {
251 return isSuccess() ? "true: "+get() : "false: "+ getError().getMessage();
252 }
253 }