1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package org.apache.commons.io.function; 19 20 import java.io.IOException; 21 import java.io.UncheckedIOException; 22 import java.util.Objects; 23 import java.util.function.Consumer; 24 import java.util.function.Function; 25 import java.util.function.Supplier; 26 27 /** 28 * Like {@link Function} but throws {@link IOException}. 29 * 30 * @param <T> the type of the input to the operations. 31 * @param <R> the return type of the operations. 32 * @since 2.7 33 */ 34 @FunctionalInterface 35 public interface IOFunction<T, R> { 36 37 /** 38 * Returns a {@link IOFunction} that always returns its input argument. 39 * 40 * @param <T> the type of the input and output objects to the function 41 * @return a function that always returns its input argument 42 */ 43 @SuppressWarnings("unchecked") 44 static <T> IOFunction<T, T> identity() { 45 return Constants.IO_FUNCTION_ID; 46 } 47 48 /** 49 * Returns a composed {@link IOFunction} that first applies this function to its input, and then applies the 50 * {@code after} consumer to the result. If evaluation of either function throws an exception, it is relayed to the 51 * caller of the composed function. 52 * 53 * @param after the consumer to apply after this function is applied 54 * @return a composed function that first applies this function and then applies the {@code after} consumer 55 * @throws NullPointerException if after is null 56 * 57 * @see #compose(IOFunction) 58 */ 59 default IOConsumer<T> andThen(final Consumer<? super R> after) { 60 Objects.requireNonNull(after, "after"); 61 return (final T t) -> after.accept(apply(t)); 62 } 63 64 /** 65 * Returns a composed {@link IOFunction} that first applies this function to its input, and then applies the 66 * {@code after} function to the result. If evaluation of either function throws an exception, it is relayed to the 67 * caller of the composed function. 68 * 69 * @param <V> the type of output of the {@code after} function, and of the composed function 70 * @param after the function to apply after this function is applied 71 * @return a composed function that first applies this function and then applies the {@code after} function 72 * @throws NullPointerException if after is null 73 * 74 * @see #compose(IOFunction) 75 */ 76 default <V> IOFunction<T, V> andThen(final Function<? super R, ? extends V> after) { 77 Objects.requireNonNull(after, "after"); 78 return (final T t) -> after.apply(apply(t)); 79 } 80 81 /** 82 * Returns a composed {@link IOFunction} that first applies this function to its input, and then applies the 83 * {@code after} consumer to the result. If evaluation of either function throws an exception, it is relayed to the 84 * caller of the composed function. 85 * 86 * @param after the consumer to apply after this function is applied 87 * @return a composed function that first applies this function and then applies the {@code after} consumer 88 * @throws NullPointerException if after is null 89 * 90 * @see #compose(IOFunction) 91 */ 92 default IOConsumer<T> andThen(final IOConsumer<? super R> after) { 93 Objects.requireNonNull(after, "after"); 94 return (final T t) -> after.accept(apply(t)); 95 } 96 97 /** 98 * Returns a composed {@link IOFunction} that first applies this function to its input, and then applies the 99 * {@code after} function to the result. If evaluation of either function throws an exception, it is relayed to the 100 * caller of the composed function. 101 * 102 * @param <V> the type of output of the {@code after} function, and of the composed function 103 * @param after the function to apply after this function is applied 104 * @return a composed function that first applies this function and then applies the {@code after} function 105 * @throws NullPointerException if after is null 106 * 107 * @see #compose(IOFunction) 108 */ 109 default <V> IOFunction<T, V> andThen(final IOFunction<? super R, ? extends V> after) { 110 Objects.requireNonNull(after, "after"); 111 return (final T t) -> after.apply(apply(t)); 112 } 113 114 /** 115 * Applies this function to the given argument. 116 * 117 * @param t the function argument 118 * @return the function result 119 * @throws IOException if an I/O error occurs. 120 */ 121 R apply(final T t) throws IOException; 122 123 /** 124 * Creates a {@link Function} for this instance that throws {@link UncheckedIOException} instead of {@link IOException}. 125 * 126 * @return an UncheckedIOException Function. 127 * @since 2.12.0 128 */ 129 default Function<T, R> asFunction() { 130 return t -> Uncheck.apply(this, t); 131 } 132 133 /** 134 * Returns a composed {@link IOFunction} that first applies the {@code before} function to its input, and then applies 135 * this function to the result. If evaluation of either function throws an exception, it is relayed to the caller of the 136 * composed function. 137 * 138 * @param <V> the type of input to the {@code before} function, and to the composed function 139 * @param before the function to apply before this function is applied 140 * @return a composed function that first applies the {@code before} function and then applies this function 141 * @throws NullPointerException if before is null 142 * 143 * @see #andThen(IOFunction) 144 */ 145 default <V> IOFunction<V, R> compose(final Function<? super V, ? extends T> before) { 146 Objects.requireNonNull(before, "before"); 147 return (final V v) -> apply(before.apply(v)); 148 } 149 150 /** 151 * Returns a composed {@link IOFunction} that first applies the {@code before} function to its input, and then applies 152 * this function to the result. If evaluation of either function throws an exception, it is relayed to the caller of the 153 * composed function. 154 * 155 * @param <V> the type of input to the {@code before} function, and to the composed function 156 * @param before the function to apply before this function is applied 157 * @return a composed function that first applies the {@code before} function and then applies this function 158 * @throws NullPointerException if before is null 159 * 160 * @see #andThen(IOFunction) 161 */ 162 default <V> IOFunction<V, R> compose(final IOFunction<? super V, ? extends T> before) { 163 Objects.requireNonNull(before, "before"); 164 return (final V v) -> apply(before.apply(v)); 165 } 166 167 /** 168 * Returns a composed {@link IOFunction} that first applies the {@code before} function to its input, and then applies 169 * this function to the result. If evaluation of either function throws an exception, it is relayed to the caller of the 170 * composed function. 171 * 172 * @param before the supplier which feeds the application of this function 173 * @return a composed function that first applies the {@code before} function and then applies this function 174 * @throws NullPointerException if before is null 175 * 176 * @see #andThen(IOFunction) 177 */ 178 default IOSupplier<R> compose(final IOSupplier<? extends T> before) { 179 Objects.requireNonNull(before, "before"); 180 return () -> apply(before.get()); 181 } 182 183 /** 184 * Returns a composed {@link IOFunction} that first applies the {@code before} function to its input, and then applies 185 * this function to the result. If evaluation of either function throws an exception, it is relayed to the caller of the 186 * composed function. 187 * 188 * @param before the supplier which feeds the application of this function 189 * @return a composed function that first applies the {@code before} function and then applies this function 190 * @throws NullPointerException if before is null 191 * 192 * @see #andThen(IOFunction) 193 */ 194 default IOSupplier<R> compose(final Supplier<? extends T> before) { 195 Objects.requireNonNull(before, "before"); 196 return () -> apply(before.get()); 197 } 198 }