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 * @see #compose(IOFunction) 57 */ 58 default IOConsumer<T> andThen(final Consumer<? super R> after) { 59 Objects.requireNonNull(after, "after"); 60 return (final T t) -> after.accept(apply(t)); 61 } 62 63 /** 64 * Returns a composed {@link IOFunction} that first applies this function to its input, and then applies the 65 * {@code after} function to the result. If evaluation of either function throws an exception, it is relayed to the 66 * caller of the composed function. 67 * 68 * @param <V> the type of output of the {@code after} function, and of the composed function 69 * @param after the function to apply after this function is applied 70 * @return a composed function that first applies this function and then applies the {@code after} function 71 * @throws NullPointerException if after is null 72 * @see #compose(IOFunction) 73 */ 74 default <V> IOFunction<T, V> andThen(final Function<? super R, ? extends V> after) { 75 Objects.requireNonNull(after, "after"); 76 return (final T t) -> after.apply(apply(t)); 77 } 78 79 /** 80 * Returns a composed {@link IOFunction} that first applies this function to its input, and then applies the 81 * {@code after} consumer to the result. If evaluation of either function throws an exception, it is relayed to the 82 * caller of the composed function. 83 * 84 * @param after the consumer to apply after this function is applied 85 * @return a composed function that first applies this function and then applies the {@code after} consumer 86 * @throws NullPointerException if after is null 87 * @see #compose(IOFunction) 88 */ 89 default IOConsumer<T> andThen(final IOConsumer<? super R> after) { 90 Objects.requireNonNull(after, "after"); 91 return (final T t) -> after.accept(apply(t)); 92 } 93 94 /** 95 * Returns a composed {@link IOFunction} that first applies this function to its input, and then applies the 96 * {@code after} function to the result. If evaluation of either function throws an exception, it is relayed to the 97 * caller of the composed function. 98 * 99 * @param <V> the type of output of the {@code after} function, and of the composed function 100 * @param after the function to apply after this function is applied 101 * @return a composed function that first applies this function and then applies the {@code after} function 102 * @throws NullPointerException if after is null 103 * @see #compose(IOFunction) 104 */ 105 default <V> IOFunction<T, V> andThen(final IOFunction<? super R, ? extends V> after) { 106 Objects.requireNonNull(after, "after"); 107 return (final T t) -> after.apply(apply(t)); 108 } 109 110 /** 111 * Applies this function to the given argument. 112 * 113 * @param t the function argument 114 * @return the function result 115 * @throws IOException if an I/O error occurs. 116 */ 117 R apply(T t) throws IOException; 118 119 /** 120 * Creates a {@link Function} for this instance that throws {@link UncheckedIOException} instead of {@link IOException}. 121 * 122 * @return an UncheckedIOException Function. 123 * @since 2.12.0 124 */ 125 default Function<T, R> asFunction() { 126 return t -> Uncheck.apply(this, t); 127 } 128 129 /** 130 * Returns a composed {@link IOFunction} that first applies the {@code before} function to its input, and then applies 131 * this function to the result. If evaluation of either function throws an exception, it is relayed to the caller of the 132 * composed function. 133 * 134 * @param <V> the type of input to the {@code before} function, and to the composed function 135 * @param before the function to apply before this function is applied 136 * @return a composed function that first applies the {@code before} function and then applies this function 137 * @throws NullPointerException if before is null 138 * @see #andThen(IOFunction) 139 */ 140 default <V> IOFunction<V, R> compose(final Function<? super V, ? extends T> before) { 141 Objects.requireNonNull(before, "before"); 142 return (final V v) -> apply(before.apply(v)); 143 } 144 145 /** 146 * Returns a composed {@link IOFunction} that first applies the {@code before} function to its input, and then applies 147 * this function to the result. If evaluation of either function throws an exception, it is relayed to the caller of the 148 * composed function. 149 * 150 * @param <V> the type of input to the {@code before} function, and to the composed function 151 * @param before the function to apply before this function is applied 152 * @return a composed function that first applies the {@code before} function and then applies this function 153 * @throws NullPointerException if before is null 154 * @see #andThen(IOFunction) 155 */ 156 default <V> IOFunction<V, R> compose(final IOFunction<? super V, ? extends T> before) { 157 Objects.requireNonNull(before, "before"); 158 return (final V v) -> apply(before.apply(v)); 159 } 160 161 /** 162 * Returns a composed {@link IOFunction} that first applies the {@code before} function to its input, and then applies 163 * this function to the result. If evaluation of either function throws an exception, it is relayed to the caller of the 164 * composed function. 165 * 166 * @param before the supplier which feeds the application of this function 167 * @return a composed function that first applies the {@code before} function and then applies this function 168 * @throws NullPointerException if before is null 169 * @see #andThen(IOFunction) 170 */ 171 default IOSupplier<R> compose(final IOSupplier<? extends T> before) { 172 Objects.requireNonNull(before, "before"); 173 return () -> apply(before.get()); 174 } 175 176 /** 177 * Returns a composed {@link IOFunction} that first applies the {@code before} function to its input, and then applies 178 * this function to the result. If evaluation of either function throws an exception, it is relayed to the caller of the 179 * composed function. 180 * 181 * @param before the supplier which feeds the application of this function 182 * @return a composed function that first applies the {@code before} function and then applies this function 183 * @throws NullPointerException if before is null 184 * @see #andThen(IOFunction) 185 */ 186 default IOSupplier<R> compose(final Supplier<? extends T> before) { 187 Objects.requireNonNull(before, "before"); 188 return () -> apply(before.get()); 189 } 190 }