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.exceptions; 021 022import static java.util.concurrent.CompletableFuture.completedFuture; 023import static java.util.concurrent.CompletableFuture.failedFuture; 024 025import java.util.Optional; 026import java.util.concurrent.Callable; 027import java.util.concurrent.CompletionStage; 028import java.util.function.Function; 029 030/** 031 * Root interface to support global operations related to exception handling for 032 * functional interface returning Object result. 033 * 034 * @param <F> 035 * the type of the java standard functional interface. For example, 036 * {@code Function<T,R>}. 037 * @param <L> 038 * the type of the lifted functional interface. For example, 039 * {@code Function<T,Optional<R>>}. 040 * @param <S> 041 * the type of the staged functional interface. For example, 042 * {@code Function<T,CompletionStage<R>>}. 043 * @param <T> 044 * the type of the return type of the Functional interface. 045 */ 046public interface ObjectReturnExceptionHandlerSupport<F, L, S, T, Z extends ObjectReturnExceptionHandlerSupport<F, L, S, T, Z>> 047 extends ExceptionHandlerSupport<F, L, Z> { 048 049 /** 050 * Converts this functional interface to the corresponding one in java and wrap 051 * exception using {@link #exceptionMapper()}. 052 * <p> 053 * Conceptually, the exception encapsulation is done in the following way : 054 * 055 * <pre> 056 * (xxx) -> { 057 * try { 058 * return realaction(xxx); 059 * } catch (Exception e) { 060 * throw new exceptionMapper().apply(e); 061 * } 062 * } 063 * </pre> 064 * 065 * @return the unchecked operation 066 * @see #lift() 067 * @see #ignore() 068 */ 069 @Override 070 F uncheck(); 071 072 /** 073 * Converts this functional interface to a lifted one. The lifted version return 074 * an Optional of the original return type. 075 * <p> 076 * Conceptually, this is done by : 077 * 078 * <pre> 079 * (xxx) -> { 080 * try { 081 * return Optional.ofNullable(realaction(xxx)); 082 * } catch (Exception e) { 083 * return Optional.empty(); 084 * } 085 * } 086 * </pre> 087 * 088 * @return the lifted function 089 * @see #uncheck() 090 * @see #ignore() 091 */ 092 @Override 093 L lift(); 094 095 /** 096 * Converts this functional interface to the corresponding java standard 097 * functional interface returning a null in case of error. 098 * <p> 099 * The principle is : 100 * 101 * <pre> 102 * (xxx) -> { 103 * try { 104 * return realaction(xxx); 105 * } catch (Exception e) { 106 * return null; 107 * } 108 * } 109 * </pre> 110 * 111 * @return the operation that ignore error 112 * @see #uncheck() 113 * @see #lift() 114 */ 115 @Override 116 F ignore(); 117 118 /** 119 * Converts this functional interface to the corresponding java standard 120 * functional interface with staged result. 121 * 122 * @return the operation supporting stage. 123 * @since 1.1.0 124 * @see CompletionStage 125 */ 126 S stage(); 127 128 /** 129 * Defines the default value (by default {@code null}) returned by the ignore 130 * and ignored method. 131 * 132 * @return the default value for the ignore/ignored method. 133 * @since 3.0.0 134 */ 135 default T defaultValue() { 136 return null; 137 } 138 139 /** 140 * Used internally to support the exception interception. 141 * 142 * @param internal 143 * the call to be done 144 * @param exceptionhandler 145 * the exception handler. May throw RuntimeException or return some 146 * default value. 147 * @return the result 148 * @throws RuntimeException 149 * in case of error 150 * @param <T> 151 * type of the return value 152 */ 153 static <T> T unchecked(Callable<T> internal, Function<Exception, T> exceptionhandler) { 154 try { 155 return internal.call(); 156 } catch (Exception e) { 157 // exceptionhandler must throw the exception if needed 158 return exceptionhandler.apply(e); 159 } 160 } 161 162 /** 163 * Used internally to support the exception interception. 164 * 165 * @param internal 166 * the call to be done 167 * @return the completion stage 168 * @throws RuntimeException 169 * in case of error 170 * @param <T> 171 * type of the return value 172 */ 173 static <T> CompletionStage<T> staged(Callable<T> internal) { 174 try { 175 return completedFuture(internal.call()); 176 } catch (Exception e) { 177 return failedFuture(e); 178 } 179 } 180 181 /** 182 * Used internally to support the exception interception. 183 * 184 * @return exception handler to support exception control 185 */ 186 default Function<Exception, T> throwingHandler() { 187 return e -> { 188 throw exceptionMapper().apply(e); 189 }; 190 } 191 192 /** 193 * Used internally to support the exception interception. 194 * 195 * @return exception handler to ignore exception 196 */ 197 default Function<Exception, Optional<T>> notThrowingHandler() { 198 return e -> Optional.empty(); 199 } 200}