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 java.util.Objects; 023import java.util.function.Function; 024import java.util.function.Supplier; 025 026/** 027 * Root interface to support global operations related to exception handling. 028 * 029 * @param <F> 030 * the type of the java standard functional interface. For example, 031 * {@code Function<T,R>}. 032 * @param <L> 033 * the type of the lifted functional interface. For example, 034 * {@code Function<T,Optional<R>>}. 035 * @param <Z> 036 * the type of the interface it self. 037 */ 038public interface ExceptionHandlerSupport<F, L, Z extends ExceptionHandlerSupport<F, L, Z>> { 039 040 /** 041 * Mapping operation to convert the exception that may be thrown during 042 * execution to {@code RuntimeException}. 043 * <p> 044 * The default mapper function may be changed by : 045 * <ul> 046 * <li>Using the second argument of the various {@code unchecked} methods. This 047 * override only the current interface.</li> 048 * <li>By defining global {@code ExceptionMapper}, using the module syntax : 049 * {@code provides ch.powerunit.extensions.exceptions.ExceptionMapper with XXX}</li> 050 * </ul> 051 * 052 * @return the mapping function, which is by default constructing 053 * {@code WrappedException}. 054 * @see WrappedException 055 */ 056 default Function<Exception, RuntimeException> exceptionMapper() { 057 return Constants.MAPPERS; 058 } 059 060 /** 061 * Converts this functional interface to the corresponding one in java and wrap 062 * exception using {@link #exceptionMapper()}. 063 * <p> 064 * Conceptually, the exception encapsulation is done in the following way : 065 * 066 * <pre> 067 * (xxx) -> { 068 * try { 069 * // do the underlying functional interface action and return result if 070 * // applicable 071 * } catch (Exception e) { 072 * throw new exceptionMapper().apply(e); 073 * } 074 * } 075 * </pre> 076 * 077 * @return the unchecked operation 078 * @see #lift() 079 * @see #ignore() 080 */ 081 F uncheck(); 082 083 /** 084 * Converts this functional interface to a lifted one. A lifted version may or 085 * may not have the same return type of the original one. When possible a 086 * version returning an {@code Optional} is provided. For functional interface 087 * without return value, this method will be identical to {@link #ignore()}. 088 * <p> 089 * For functional interface with Object result, the principle is : 090 * 091 * <pre> 092 * (xxx) -> { 093 * try { 094 * return Optional.ofNullable(realaction(xxx)); 095 * } catch (Exception e) { 096 * return Optional.empty(); 097 * } 098 * } 099 * </pre> 100 * 101 * For functional interface with primitive result, the principle is : 102 * 103 * <pre> 104 * (xxx) -> { 105 * try { 106 * return realaction(xxx); 107 * } catch (Exception e) { 108 * return defaultValue; 109 * } 110 * } 111 * </pre> 112 * 113 * For functional interface without result, the principle is : 114 * 115 * <pre> 116 * (xxx) -> { 117 * try { 118 * realaction(xxx); 119 * } catch (Exception e) { 120 * // do nothing 121 * } 122 * } 123 * </pre> 124 * 125 * @return the lifted function 126 * @see #uncheck() 127 * @see #ignore() 128 */ 129 L lift(); 130 131 /** 132 * Converts this functional interface to the corresponding java standard 133 * functional interface returning a default value in case of error. For function 134 * interface without return value, error will be silently ignored. 135 * 136 * <p> 137 * For functional interface with Object result, the principle is : 138 * 139 * <pre> 140 * (xxx) -> { 141 * try { 142 * return realaction(xxx); 143 * } catch (Exception e) { 144 * return null; 145 * } 146 * } 147 * </pre> 148 * 149 * For functional interface with primitive result, the principle is : 150 * 151 * <pre> 152 * (xxx) -> { 153 * try { 154 * return realaction(xxx); 155 * } catch (Exception e) { 156 * return defaultValue; 157 * } 158 * } 159 * </pre> 160 * 161 * For functional interface without result, the principle is : 162 * 163 * <pre> 164 * (xxx) -> { 165 * try { 166 * realaction(xxx); 167 * } catch (Exception e) { 168 * // do nothing 169 * } 170 * } 171 * </pre> 172 * 173 * @return the operation that ignore error 174 * @see #uncheck() 175 * @see #lift() 176 */ 177 F ignore(); 178 179 /** 180 * Add a {@code toString} method to the existing interface based on the received 181 * {@code Supplier}. 182 * 183 * @param toString 184 * the supplier to be used 185 * @return a new interface, with {@code toString} using the received supplier. 186 * @throws NullPointerException 187 * if toString is null 188 * @since 3.0.0 189 */ 190 @SuppressWarnings("unchecked") 191 default Z documented(Supplier<String> toString) { 192 return (Z) InternalHelper.documented(this, Objects.requireNonNull(toString, "toString can't be null")); 193 } 194 195}