1 /* 2 * Copyright (c) 2011-2017 Contributors to the Eclipse Foundation 3 * 4 * This program and the accompanying materials are made available under the 5 * terms of the Eclipse Public License 2.0 which is available at 6 * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 * 9 * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 */ 11 12 module hunt.net.AsyncResult; 13 14 import hunt.Exceptions; 15 import hunt.Functions; 16 17 /** 18 * Encapsulates the result of an asynchronous operation. 19 * <p> 20 * Many operations in Vert.x APIs provide results back by passing an instance of this in a {@link hunt.net.Handler}. 21 * <p> 22 * The result can either have failed or succeeded. 23 * <p> 24 * If it failed then the cause of the failure is available with {@link #cause}. 25 * <p> 26 * If it succeeded then the actual result is available with {@link #result} 27 * 28 * @author <a href="http://tfox.org">Tim Fox</a> 29 */ 30 interface AsyncResult(T) { 31 32 /** 33 * The result of the operation. This will be null if the operation failed. 34 * 35 * @return the result or null if the operation failed. 36 */ 37 T result(); 38 39 /** 40 * A Throwable describing failure. This will be null if the operation succeeded. 41 * 42 * @return the cause or null if the operation succeeded. 43 */ 44 Throwable cause(); 45 46 /** 47 * Did it succeed? 48 * 49 * @return true if it succeded or false otherwise 50 */ 51 bool succeeded(); 52 53 /** 54 * Did it fail? 55 * 56 * @return true if it failed or false otherwise 57 */ 58 bool failed(); 59 60 /** 61 * Apply a {@code mapper} function on this async result.<p> 62 * 63 * The {@code mapper} is called with the completed value and this mapper returns a value. This value will complete the result returned by this method call.<p> 64 * 65 * When this async result is failed, the failure will be propagated to the returned async result and the {@code mapper} will not be called. 66 * 67 * @param mapper the mapper function 68 * @return the mapped async result 69 */ 70 final AsyncResult!(U) map(U)(Function!(T, U) mapper) { 71 if (mapper is null) { 72 throw new NullPointerException(); 73 } 74 return new class AsyncResult!(U) { 75 override U result() { 76 if (succeeded()) { 77 return mapper.apply(this.outer.result()); 78 } else { 79 return null; 80 } 81 } 82 83 override Throwable cause() { 84 return this.outer.cause(); 85 } 86 87 override bool succeeded() { 88 return this.outer.succeeded(); 89 } 90 91 override bool failed() { 92 return this.outer.failed(); 93 } 94 }; 95 } 96 97 /** 98 * Map the result of this async result to a specific {@code value}.<p> 99 * 100 * When this async result succeeds, this {@code value} will succeeed the async result returned by this method call.<p> 101 * 102 * When this async result fails, the failure will be propagated to the returned async result. 103 * 104 * @param value the value that eventually completes the mapped async result 105 * @return the mapped async result 106 */ 107 final AsyncResult!(V) map(V)(V value) { 108 return map((t) => value); 109 } 110 111 /** 112 * Map the result of this async result to {@code null}.<p> 113 * 114 * This is a convenience for {@code asyncResult.map((T) null)} or {@code asyncResult.map((Void) null)}.<p> 115 * 116 * When this async result succeeds, {@code null} will succeeed the async result returned by this method call.<p> 117 * 118 * When this async result fails, the failure will be propagated to the returned async result. 119 * 120 * @return the mapped async result 121 */ 122 final AsyncResult!(V) mapEmpty(V)() { 123 return map(V.init); 124 } 125 126 /** 127 * Apply a {@code mapper} function on this async result.<p> 128 * 129 * The {@code mapper} is called with the failure and this mapper returns a value. This value will complete the result returned by this method call.<p> 130 * 131 * When this async result is succeeded, the value will be propagated to the returned async result and the {@code mapper} will not be called. 132 * 133 * @param mapper the mapper function 134 * @return the mapped async result 135 */ 136 final AsyncResult!(T) otherwise(Function!(Throwable, T) mapper) { 137 if (mapper is null) { 138 throw new NullPointerException(); 139 } 140 return new class AsyncResult!(T) { 141 override T result() { 142 if (this.outer.succeeded()) { 143 return this.outer.result(); 144 } else if (this.outer.failed()) { 145 return mapper(this.outer.cause()); 146 } else { 147 return null; 148 } 149 } 150 151 override Throwable cause() { 152 return null; 153 } 154 155 override bool succeeded() { 156 return this.outer.succeeded() || this.outer.failed(); 157 } 158 159 override bool failed() { 160 return false; 161 } 162 }; 163 } 164 165 /** 166 * Map the failure of this async result to a specific {@code value}.<p> 167 * 168 * When this async result fails, this {@code value} will succeeed the async result returned by this method call.<p> 169 * 170 * When this async succeeds, the result will be propagated to the returned async result. 171 * 172 * @param value the value that eventually completes the mapped async result 173 * @return the mapped async result 174 */ 175 final AsyncResult!(T) otherwise(T value) { 176 return otherwise((err) => value); 177 } 178 179 /** 180 * Map the failure of this async result to {@code null}.<p> 181 * 182 * This is a convenience for {@code asyncResult.otherwise((T) null)}.<p> 183 * 184 * When this async result fails, the {@code null} will succeeed the async result returned by this method call.<p> 185 * 186 * When this async succeeds, the result will be propagated to the returned async result. 187 * 188 * @return the mapped async result 189 */ 190 final AsyncResult!(T) otherwiseEmpty() { 191 return otherwise((err) => T.init); 192 } 193 194 } 195 196 AsyncResult!T succeededResult(T)(T v) { 197 return new class AsyncResult!(T) { 198 override T result() { 199 return v; 200 } 201 202 override Throwable cause() { 203 return null; 204 } 205 206 override bool succeeded() { 207 return true; 208 } 209 210 override bool failed() { 211 return false; 212 } 213 }; 214 } 215 216 217 AsyncResult!T failedResult(T)(Throwable t) { 218 return new class AsyncResult!(T) { 219 override T result() { 220 return T.init; 221 } 222 223 override Throwable cause() { 224 return t; 225 } 226 227 override bool succeeded() { 228 return false; 229 } 230 231 override bool failed() { 232 return true; 233 } 234 }; 235 }