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 package org.apache.commons.functor.core.composite; 18 19 import java.io.Serializable; 20 21 import org.apache.commons.functor.BinaryPredicate; 22 import org.apache.commons.functor.UnaryFunction; 23 import org.apache.commons.lang3.Validate; 24 25 /** 26 * A {@link BinaryPredicate BinaryPredicate} composed of 27 * one binary predicate, <i>p</i>, and two unary 28 * functions, <i>f</i> and <i>g</i>, 29 * evaluating the ordered parameters <i>x</i>, <i>y</i> 30 * to <code><i>p</i>(<i>f</i>(<i>x</i>),<i>g</i>(<i>y</i>))</code>. 31 * <p> 32 * Note that although this class implements 33 * {@link Serializable}, a given instance will 34 * only be truly <code>Serializable</code> if all the 35 * underlying functors are. Attempts to serialize 36 * an instance whose delegates are not all 37 * <code>Serializable</code> will result in an exception. 38 * </p> 39 * @param <L> the left argument type. 40 * @param <R> the right argument type. 41 * @version $Revision: 1345136 $ $Date: 2012-06-01 09:47:06 -0300 (Fri, 01 Jun 2012) $ 42 */ 43 public class UnaryCompositeBinaryPredicate<L, R> implements BinaryPredicate<L, R>, Serializable { 44 /** 45 * serialVersionUID declaration. 46 */ 47 private static final long serialVersionUID = 3841123079006929493L; 48 49 /** Base hash integer used to shift hash. */ 50 private static final int HASH_SHIFT = 4; 51 52 /** 53 * Internal helper. 54 * 55 * @param <G> right function type. 56 * @param <H> right function type. 57 * @param <L> left function type. 58 * @param <R> left function type. 59 */ 60 private static class Helper<G, H, L, R> implements BinaryPredicate<L, R>, Serializable { 61 /** 62 * serialVersionUID declaration. 63 */ 64 private static final long serialVersionUID = -3463108273324567825L; 65 /** 66 * BinaryPredicate to test <i>output(</i><code>f</code><i>), output(</i><code>g</code><i>)</i>. 67 */ 68 private BinaryPredicate<? super G, ? super H> f; 69 /** 70 * left UnaryFunction. 71 */ 72 private UnaryFunction<? super L, ? extends G> g; 73 /** 74 * right UnaryFunction. 75 */ 76 private UnaryFunction<? super R, ? extends H> h; 77 78 /** 79 * Create a new Helper. 80 * @param f BinaryPredicate to test <i>output(</i><code>f</code><i>), output(</i><code>g</code><i>)</i> 81 * @param g left UnaryFunction 82 * @param h right UnaryFunction 83 */ 84 public Helper(BinaryPredicate<? super G, ? super H> f, UnaryFunction<? super L, ? extends G> g, 85 UnaryFunction<? super R, ? extends H> h) { 86 this.f = f; 87 this.g = g; 88 this.h = h; 89 } 90 91 /** 92 * {@inheritDoc} 93 */ 94 public boolean test(L left, R right) { 95 return f.test(g.evaluate(left), h.evaluate(right)); 96 } 97 } 98 99 // attributes 100 // ------------------------------------------------------------------------ 101 /** 102 * The adapted helper. 103 */ 104 private final Helper<?, ?, L, R> helper; 105 106 // constructor 107 // ------------------------------------------------------------------------ 108 /** 109 * Create a new UnaryCompositeBinaryPredicate. 110 * 111 * @param <G> right function type. 112 * @param <H> right function type. 113 * @param f BinaryPredicate to test <i>output(</i><code>f</code><i>), output(</i><code>g</code><i>)</i> 114 * @param g left UnaryFunction 115 * @param h right UnaryFunction 116 */ 117 public <G, H> UnaryCompositeBinaryPredicate(final BinaryPredicate<? super G, ? super H> f, 118 final UnaryFunction<? super L, ? extends G> g, final UnaryFunction<? super R, ? extends H> h) { 119 helper = new Helper<G, H, L, R>( 120 Validate.notNull(f, "BinaryPredicate must not be null"), 121 Validate.notNull(g, "left UnaryFunction must not be null"), 122 Validate.notNull(h, "right UnaryFunction must not be null") 123 ); 124 } 125 126 // function interface 127 // ------------------------------------------------------------------------ 128 /** 129 * {@inheritDoc} 130 */ 131 public boolean test(L left, R right) { 132 return helper.test(left, right); 133 } 134 135 /** 136 * {@inheritDoc} 137 */ 138 @Override 139 public boolean equals(Object that) { 140 return that == this || (that instanceof UnaryCompositeBinaryPredicate<?, ?> 141 && equals((UnaryCompositeBinaryPredicate<?, ?>) that)); 142 } 143 144 /** 145 * Learn whether another UnaryCompositeBinaryPredicate is equal to this. 146 * @param that UnaryCompositeBinaryPredicate to test 147 * @return boolean 148 */ 149 public boolean equals(UnaryCompositeBinaryPredicate<?, ?> that) { 150 return null != that && helper.f.equals(that.helper.f) && helper.g.equals(that.helper.g) 151 && helper.h.equals(that.helper.h); 152 } 153 154 /** 155 * {@inheritDoc} 156 */ 157 @Override 158 public int hashCode() { 159 int hash = "UnaryCompositeBinaryPredicate".hashCode(); 160 hash <<= HASH_SHIFT; 161 hash ^= helper.f.hashCode(); 162 hash <<= HASH_SHIFT; 163 hash ^= helper.g.hashCode(); 164 hash <<= HASH_SHIFT; 165 hash ^= helper.h.hashCode(); 166 return hash; 167 } 168 169 /** 170 * {@inheritDoc} 171 */ 172 @Override 173 public String toString() { 174 return "UnaryCompositeBinaryPredicate<" + helper.f + ";" + helper.g + ";" + helper.h + ">"; 175 } 176 177 }