1 /* Copyright (c) 2008 Sascha Kohlmann 2 * 3 * This program is free software: you can redistribute it and/or modify 4 * it under the terms of the GNU Affero General Public License as published by 5 * the Free Software Foundation, either version 3 of the License, or 6 * (at your option) any later version. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU Affero General Public License for more details. 12 * 13 * You should have received a copy of the GNU Affero General Public License 14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 15 */ 16 package net.sf.eos.util; 17 18 import net.sf.eos.Experimental; 19 import net.sf.eos.Function; 20 import net.sf.eos.Predicate; 21 import net.sf.eos.Supplier; 22 import static net.sf.eos.util.Conditions.checkArgumentNotNull; 23 24 /** 25 * Defines some useful compositions for handling with {@link Function Functions}, 26 * {@link Predicate Predicates} and {@link Supplier Suppliers}. 27 * 28 * <p>Each {@code composition} follows the rule of a {@code from} or <em>source</em> 29 * entity, propagating its result value to a {@code to} or <em>target</em> entity.</p> 30 * 31 * @author Sascha Kohlmann 32 */ 33 @Experimental 34 public class Compositions { 35 36 /** 37 * Returns the composition of two functions. For {@code f: F→I} and 38 * {@code g: I→T}, composition is defined as the function {@code h} 39 * such that {@code h(x) == g(f(x))} for each {@code x}. 40 * 41 * <p>The usage interface is designed as a {@code from} function which 42 * propagates its result to the {@code to} function.</p> 43 * 44 * @param <F> the {@code from} or <em>source</em> type 45 * @param <I> the intermediate type 46 * @param <T> the {@code to} or <em>target</em> type 47 * @param from the {@code from} or <em>source</em> {@code function} 48 * @param to the {@code to} or <em>target</em> {@code function} 49 * @throws IllegalArgumentException if one parameter is {@code null} 50 * @since 0.1.0 51 */ 52 public final static <F, I, T> Function<F, T> compose( 53 final Function<? super F, ? extends I> from, 54 final Function<? super I, ? extends T> to) { 55 return new FunctionComposition<F, I, T>(from, to); 56 } 57 58 /** 59 * @see #compose(Function, Function) 60 */ 61 private final static class FunctionComposition<F, I, T> implements Function<F, T> { 62 63 private final Function<? super F, ? extends I> from; 64 private final Function<? super I, ? extends T> to; 65 66 public FunctionComposition(final Function<? super F, ? extends I> from, 67 final Function<? super I, ? extends T> to) { 68 this.from = checkArgumentNotNull(from, "from is null"); 69 this.to = checkArgumentNotNull(to, "to is null"); 70 } 71 public T apply(final F source) { 72 return to.apply(from.apply(source)); 73 } 74 } 75 76 /** 77 * Returns a composition of a <em>from</em> {@code Function} and an evaluating 78 * <em>to</em> {@code Predicate}. The {@code predicate} retrieves the value from 79 * the {@code function}. 80 * 81 * <p>The usage interface is designed as a {@code from} function which 82 * propagates its result to the {@code to} predicate.</p> 83 * 84 * @param <F> the {@code from} or <em>source</em> type 85 * @param <T> the {@code to} or <em>target</em> type 86 * @param fromFunction the {@code from} or <em>source</em> {@code function} 87 * @param toPredicate the {@code to} or <em>target</em> {@code predicate} 88 * @return a {@code predicate} 89 * @throws IllegalArgumentException if one parameter is {@code null} 90 * @since 0.7.0 91 */ 92 public final static <F, T> Predicate<F> compose( 93 final Function<? super F, ? extends T> fromFunction, 94 final Predicate<T> toPredicate) { 95 return new FunctionPredicateComposition<F, T>(fromFunction, toPredicate); 96 } 97 98 /** @see #compose(Function, Predicate) */ 99 private final static class FunctionPredicateComposition<F, T> 100 implements Predicate<F> { 101 102 private final Predicate<? super T> to; 103 private final Function<? super F, ? extends T> from; 104 105 /** 106 * Constructs the composition of the given {@code Function} and 107 * {@code Predicate}. 108 * 109 * @param fromFunction the inner {@link Function}. Must not be {@code null}. 110 * @param toPredicate the outer {@link Predicate}. Must not be {@code null}. 111 */ 112 @SuppressWarnings("nls") 113 public FunctionPredicateComposition( 114 final Function<? super F, ? extends T> fromFunction, 115 final Predicate<T> toPredicate) { 116 this.from = checkArgumentNotNull(fromFunction, "fromFunction is null"); 117 this.to = checkArgumentNotNull(toPredicate, "toPredicate is null"); 118 } 119 120 /** {@inheritDoc} */ 121 public boolean evaluate(final F source) { 122 return this.to.evaluate(this.from.apply(source)); 123 } 124 } 125 126 /** 127 * Returns a composition of a <em>from</em> {@code Supplier} and an applied 128 * <em>to</em> {@code Function}. The {@code function} retrieves the value from 129 * the {@code supplier}. 130 * 131 * <p>The usage interface is designed as a {@code from} supplier which 132 * propagates its result to the {@code to} function.</p> 133 * 134 * @param <F> the {@code from} or <em>source</em> type 135 * @param <T> the {@code to} or <em>target</em> type 136 * @param fromSupplier the {@code from} or <em>source</em> {@code supplier} 137 * @param toFunction the {@code to} or <em>target</em> {@code function} 138 * @return a {@code supplier} with the value from {@code function} 139 * @throws IllegalArgumentException if one parameter is {@code null} 140 * @since 0.7.0 141 */ 142 public final static <F, T> Supplier<T> compose( 143 final Supplier<? extends F> fromSupplier, 144 final Function<F, T> toFunction) { 145 return new SupplierFunctionComposition<F, T>(fromSupplier, toFunction); 146 } 147 148 /** @see #compose(Supplier, Function) */ 149 private final static class SupplierFunctionComposition<F, T> 150 implements Supplier<T> { 151 152 private final Supplier<? extends F> from; 153 private final Function<? super F, ? extends T> to; 154 155 /** 156 * Constructs the composition of the given {@code Supplier} and 157 * {@code Function}. 158 * 159 * @param fromSupplier the inner {@link Supplier}. Must not be {@code null}. 160 * @param toFunction the outer {@link Function}. Must not be {@code null}. 161 */ 162 @SuppressWarnings("nls") 163 public SupplierFunctionComposition(final Supplier<? extends F> fromSupplier, 164 final Function<F, T> toFunction) { 165 this.from = checkArgumentNotNull(fromSupplier, "fromSupplier is null"); 166 this.to = checkArgumentNotNull(toFunction, "toFunction is null"); 167 } 168 169 /** {@inheritDoc} */ 170 public T get() { 171 return this.to.apply(this.from.get()); 172 } 173 } 174 175 /** 176 * Composes a rule. A rule contains a {@code predicate} as decision maker either to call the 177 * {@code trueFunction} or the {@code falseFunction}. The returning function calls the 178 * {@code trueFunction} if {@code predicate} returns {@code true}. Otherwise the 179 * {@code falseFunction} will call. 180 * @param <F> the input type of the {@code predicate} and the {@code functions} 181 * @param <T> the output type of the applyied {@code functions} 182 * @param decider the decision maker 183 * @param trueFunction apply if the decision maker returns {@code true} 184 * @param falseFunction apply if the decision maker returns {@code false} 185 * @return a ruling function 186 * @since 0.8.1 187 */ 188 public final static <F, T> Function<F, T> composeRule( 189 final Predicate<? super F> decider, 190 final Function<? super F, ? extends T> trueFunction, 191 final Function<? super F, ? extends T> falseFunction) { 192 return new RuledFunctionComposition<F, T>(decider, trueFunction, falseFunction); 193 } 194 195 /** @see #compose(Predicate, Function, Function) */ 196 private static class RuledFunctionComposition<F, T> implements Function<F, T> { 197 /** The <em>trueFunction</em> will aplly if {@link #decisionMaker} returns {@code true}. */ 198 private final Function<? super F, ? extends T> trueFunction; 199 200 /** The <em>falseFunction</em> will aplly if {@link #decisionMaker} returns {@code false}. */ 201 private final Function<? super F, ? extends T> falseFunction; 202 203 /** Descider either call <em>trueFunction</em> or <em>falseFunction</em>. */ 204 private final Predicate<? super F> decisionMaker; 205 206 /** 207 * Constructs the composition of the given {@link Predicate} and {@link Function Functions}. 208 * 209 * @param decisionMaker the predicate which decision is the source for using the 210 * <em>trueFunction</em> or the <em>falseFunction</em> 211 * @param trueFunction the {@link Function} will call if {@code decisionMaker} 212 * returns {@code true} 213 * @param falseFunction the {@link Function} will call if {@code decisionMaker} 214 * returns {@code false} 215 */ 216 @SuppressWarnings("nls") 217 public RuledFunctionComposition( 218 @SuppressWarnings("hiding") final Predicate<? super F> decisionMaker, 219 @SuppressWarnings("hiding") final Function<? super F, ? extends T> trueFunction, 220 @SuppressWarnings("hiding") final Function<? super F, ? extends T> falseFunction) { 221 this.decisionMaker = checkArgumentNotNull(decisionMaker, "decisionMaker is null"); 222 this.trueFunction = checkArgumentNotNull(trueFunction, "trueFunction is null"); 223 this.falseFunction = checkArgumentNotNull(falseFunction, "falseFunction is null"); 224 } 225 226 /** {@inheritDoc} */ 227 public T apply(final F source) { 228 if (this.decisionMaker.evaluate(source)) { 229 return this.trueFunction.apply(source); 230 } 231 return this.falseFunction.apply(source); 232 } 233 } 234 235 /** Never used. */ 236 private Compositions() { } 237 }