001/** 002 * Powerunit - A JDK1.8 test framework 003 * Copyright (C) 2014 Mathieu Boretti. 004 * 005 * This file is part of Powerunit 006 * 007 * Powerunit is free software: you can redistribute it and/or modify 008 * it under the terms of the GNU General Public License as published by 009 * the Free Software Foundation, either version 3 of the License, or 010 * (at your option) any later version. 011 * 012 * Powerunit is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 015 * GNU General Public License for more details. 016 * 017 * You should have received a copy of the GNU General Public License 018 * along with Powerunit. If not, see <http://www.gnu.org/licenses/>. 019 */ 020package ch.powerunit.extensions.async.lang; 021 022import static java.util.concurrent.CompletableFuture.supplyAsync; 023import static java.util.concurrent.ForkJoinPool.commonPool; 024 025import java.util.Optional; 026import java.util.concurrent.CompletableFuture; 027import java.util.concurrent.Executor; 028import java.util.concurrent.ForkJoinPool; 029import java.util.function.Function; 030import java.util.function.Predicate; 031import java.util.function.Supplier; 032 033/** 034 * Almost final Step of the builder of {@link CompletableFuture} to define the 035 * executor it self. 036 * 037 * @param <T> 038 * The type of result of the {@link CompletableFuture} 039 * 040 */ 041public interface WaitResultBuilder5<T> extends Supplier<Optional<T>> { 042 043 /** 044 * Directly wait for the result of this execution (the execution is run in this 045 * thread). In case of not ignored exception, an {@link AssertionError} is 046 * thrown. 047 * <p> 048 * 049 * For example : 050 * 051 * <pre> 052 * WaitResult.of(myCallable).dontIgnoreException().expecting(myPredicate).repeat(2) 053 * .every(1000, TimeUnit.MILLISECONDS).get() 054 * </pre> 055 * <ul> 056 * <li>If an exception occurs in {@code myCallable}, an {@link AssertionError} 057 * is thrown</li> 058 * <li>If no result is available, after the 2 try, an empty {@link Optional} is 059 * returned.</li> 060 * <li>Or the result is available in the returned {@link Optional}.</li> 061 * </ul> 062 * 063 * @return the {@link Optional} with the result of the execution 064 * 065 * @throws AssertionError 066 * In case of not ignored exception. 067 */ 068 @Override 069 Optional<T> get(); 070 071 /** 072 * Register an action to be done when the retrieval is finish (in success or 073 * not). 074 * <p> 075 * This may be used, for example, to release resources. This method may be used 076 * several times. In this case, all the registered action will be executed on 077 * Finish, starting by the first one. 078 * 079 * @param action 080 * the action to be done. May be null (ignored). 081 * @return a new instance of {@link WaitResultBuilder5} with this new action to 082 * be done at the end. 083 * @since 1.1.0 084 */ 085 default WaitResultBuilder5<T> onFinish(Runnable action) { 086 if (action == null) { 087 return this; 088 } 089 return () -> { 090 try { 091 return get(); 092 } finally { 093 action.run(); 094 } 095 }; 096 } 097 098 /** 099 * Define the executor to be used for the async part. 100 * <p> 101 * Both the action to retry and the control on the result will be executed on 102 * the thread provided by the executor. 103 * 104 * @param executor 105 * the executor to be used. This can't be null. 106 * @return {@link WaitResultBuilder6 the final step} 107 */ 108 default WaitResultBuilder6<T> using(Executor executor) { 109 return () -> supplyAsync(this, executor); 110 } 111 112 /** 113 * Define the executor to be used for the async part as using 114 * {@link ForkJoinPool#commonPool()}. 115 * <p> 116 * Both the action to retry and the control on the result will be executed on 117 * the thread provided by the executor. 118 * 119 * @return {@link WaitResultBuilder6 the final step} 120 * @see ForkJoinPool#commonPool() 121 */ 122 default WaitResultBuilder6<T> usingDefaultExecutor() { 123 return using(commonPool()); 124 } 125 126 /** 127 * Create and start the async execution of the {@link CompletableFuture}. 128 * 129 * @param executor 130 * the executor to be used. 131 * @return the {@link CompletableFuture} 132 * @deprecated Replaced by {@code using(executor).asyncExec()} 133 */ 134 @Deprecated 135 default CompletableFuture<Optional<T>> asyncExec(Executor executor) { 136 return using(executor).asyncExec(); 137 } 138 139 /** 140 * Create and start the async execution of the {@link CompletableFuture} using 141 * {@link ForkJoinPool#commonPool()}. 142 * 143 * @return the {@link CompletableFuture} 144 * @see #usingDefaultExecutor() 145 * @see WaitResultBuilder6#asyncExec() 146 */ 147 default CompletableFuture<Optional<T>> asyncExec() { 148 return usingDefaultExecutor().asyncExec(); 149 } 150 151 /** 152 * Directly wait for the result of this execution. In case of not ignored 153 * exception, an {@link AssertionError} is thrown. 154 * 155 * @param executor 156 * the executor to be used. 157 * 158 * @return the {@link Optional} with the result of the execution 159 * 160 * @throws AssertionError 161 * In case of not ignored exception. 162 * @deprecated Replaced by {@code using(executor).finish()} 163 */ 164 @Deprecated 165 default Optional<T> finish(Executor executor) { 166 return using(executor).finish(); 167 } 168 169 /** 170 * Directly wait for the result of this execution using 171 * {@link ForkJoinPool#commonPool()}. In case of not ignored exception, an 172 * {@link AssertionError} is thrown. 173 * 174 * @return the {@link Optional} with the result of the execution 175 * 176 * @throws AssertionError 177 * In case of not ignored exception. 178 * @see #usingDefaultExecutor() 179 * @see WaitResultBuilder6#finish() 180 */ 181 default Optional<T> finish() { 182 return usingDefaultExecutor().finish(); 183 } 184 185 /** 186 * Directly wait for a positive result of this execution. In case of not ignored 187 * exception, or when no result are available, an {@link AssertionError} is 188 * thrown. 189 * 190 * @param executor 191 * the executor to be used. 192 * 193 * @return the value if available 194 * 195 * @throws AssertionError 196 * In case of not ignored exception or missing result. 197 * @deprecated Replaced by {@code using(executor).finishWithAResult()} 198 */ 199 @Deprecated 200 default T finishWithAResult(Executor executor) { 201 return using(executor).finishWithAResult(); 202 } 203 204 /** 205 * Directly wait for a positive result of this execution using 206 * {@link ForkJoinPool#commonPool()}. In case of not ignored exception, or when 207 * no result are available, an {@link AssertionError} is thrown. 208 * 209 * @return the value if available 210 * 211 * @throws AssertionError 212 * In case of not ignored exception or missing result. 213 * @see #usingDefaultExecutor() 214 * @see WaitResultBuilder6#finishWithAResult() 215 */ 216 default T finishWithAResult() { 217 return usingDefaultExecutor().finishWithAResult(); 218 } 219 220 /** 221 * Add a mapper fonction, on the result, if applicable. This mapper is executed 222 * in the target thread. 223 * 224 * @param mapper 225 * the function to convert the result. 226 * @param <U> 227 * the target of the mapper. 228 * @return the {@link WaitResultBuilder5} continuation of the builder 229 * @see Optional#map(Function) 230 * @since 1.0.0 231 */ 232 default <U> WaitResultBuilder5<U> map(Function<T, U> mapper) { 233 return () -> get().map(mapper); 234 } 235 236 /** 237 * Add a flat mapper fonction, on the result, if applicable. This mapper is 238 * executed in the target thread. 239 * 240 * @param mapper 241 * the function to convert the result. 242 * @param <U> 243 * the target of the mapper. 244 * @return the {@link WaitResultBuilder5} continuation of the builder 245 * @see Optional#flatMap(Function) 246 * @since 1.1.0 247 */ 248 default <U> WaitResultBuilder5<U> flatMap(Function<T, Optional<U>> mapper) { 249 return () -> get().flatMap(mapper); 250 } 251 252 /** 253 * Add a or operation, on the result, if applicable. This or is executed in the 254 * target thread. 255 * <p> 256 * <b>Only available on java 9</b> 257 * 258 * @param supplier 259 * the function to convert the result 260 * @return the {@link WaitResultBuilder5} continuation of the builder 261 * @see Optional#or(Supplier) 262 * @since 1.1.0 263 */ 264 default WaitResultBuilder5<T> or(Supplier<? extends Optional<? extends T>> supplier) { 265 throw new UnsupportedOperationException("Not available on java 8"); 266 } 267 268 /** 269 * Add a filter predicate, on the result, if applicable. This filter is executed 270 * in the target thread. 271 * 272 * @param filter 273 * the filter 274 * @return the {@link WaitResultBuilder5} continuation of the builder 275 * @see Optional#filter(Predicate) 276 * @since 1.0.0 277 */ 278 default WaitResultBuilder5<T> filter(Predicate<T> filter) { 279 return () -> get().filter(filter); 280 } 281}