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 }