001package org.apache.archiva.common; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import java.util.function.Function; 023 024/** 025 * This is a class that can be used for the Try monad 026 * 027 * The Try monad is able to collect exceptions during processing 028 * of a stream. 029 * 030 * 031 * 032 */ 033public abstract class Try<V> { 034 035 private Try() { 036 037 } 038 039 public abstract Boolean isSuccess(); 040 041 public abstract Boolean isFailure(); 042 043 public abstract void throwException(); 044 045 /** 046 * Returns the value if this is a success instance. Otherwise throws 047 * a runtime exception with the stored throwable as cause. 048 * 049 * @return The value 050 */ 051 public abstract V get(); 052 053 /** 054 * Returns the throwable that is stored in the failure. 055 * 056 * @return The Throwable or null. 057 */ 058 public abstract Throwable getError(); 059 060 061 /** 062 * A mapping method for mapping the current instance to a new type. 063 * 064 * @param fn 065 * @param <U> 066 * @return 067 */ 068 public <U> Try<U> map(Function<? super V, U> fn) { 069 try { 070 return Try.success(fn.apply(get())); 071 } catch (Throwable e) { 072 return Try.failure(e); 073 } 074 } 075 076 /** 077 * This is the bind method. 078 * If this instance is success the function will be applied. If any error occurs 079 * a failure instance will be returned. 080 * If this instance is failure a new failure will be returned. 081 * 082 * @param fn 083 * @param <U> 084 * @return 085 */ 086 public <U> Try<U> flatMap(Function<? super V, Try<U>> fn) { 087 try { 088 return fn.apply(get()); 089 } catch (Throwable t) { 090 return Try.failure(t); 091 } 092 } 093 094 public static <V> Try<V> failure(String message) { 095 096 return new Failure<>(message); 097 098 } 099 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}