001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.commons.functor.core.composite; 018 019 import java.io.Serializable; 020 021 import org.apache.commons.functor.BinaryPredicate; 022 import org.apache.commons.functor.UnaryFunction; 023 024 /** 025 * A {@link BinaryPredicate BinaryPredicate} composed of 026 * one binary predicate, <i>p</i>, and two unary 027 * functions, <i>f</i> and <i>g</i>, 028 * evaluating the ordered parameters <i>x</i>, <i>y</i> 029 * to <code><i>p</i>(<i>f</i>(<i>x</i>),<i>g</i>(<i>y</i>))</code>. 030 * <p> 031 * Note that although this class implements 032 * {@link Serializable}, a given instance will 033 * only be truly <code>Serializable</code> if all the 034 * underlying functors are. Attempts to serialize 035 * an instance whose delegates are not all 036 * <code>Serializable</code> will result in an exception. 037 * </p> 038 * @version $Revision: 1156337 $ $Date: 2011-08-10 21:44:54 +0200 (Wed, 10 Aug 2011) $ 039 * @author Rodney Waldhoff 040 */ 041 public class UnaryCompositeBinaryPredicate<L, R> implements BinaryPredicate<L, R>, Serializable { 042 /** 043 * serialVersionUID declaration. 044 */ 045 private static final long serialVersionUID = 3841123079006929493L; 046 047 private static class Helper<G, H, L, R> implements BinaryPredicate<L, R>, Serializable { 048 /** 049 * serialVersionUID declaration. 050 */ 051 private static final long serialVersionUID = -3463108273324567825L; 052 private BinaryPredicate<? super G, ? super H> f; 053 private UnaryFunction<? super L, ? extends G> g; 054 private UnaryFunction<? super R, ? extends H> h; 055 056 /** 057 * Create a new Helper. 058 * @param f BinaryPredicate to test <i>output(</i><code>f</code><i>), output(</i><code>g</code><i>)</i> 059 * @param g left UnaryFunction 060 * @param h right UnaryFunction 061 */ 062 public Helper(BinaryPredicate<? super G, ? super H> f, UnaryFunction<? super L, ? extends G> g, 063 UnaryFunction<? super R, ? extends H> h) { 064 this.f = f; 065 this.g = g; 066 this.h = h; 067 } 068 069 /** 070 * {@inheritDoc} 071 */ 072 public boolean test(L left, R right) { 073 return f.test(g.evaluate(left), h.evaluate(right)); 074 } 075 } 076 077 // attributes 078 // ------------------------------------------------------------------------ 079 private final Helper<?, ?, L, R> helper; 080 081 // constructor 082 // ------------------------------------------------------------------------ 083 /** 084 * Create a new UnaryCompositeBinaryPredicate. 085 * @param f BinaryPredicate to test <i>output(</i><code>f</code><i>), output(</i><code>g</code><i>)</i> 086 * @param g left UnaryFunction 087 * @param h right UnaryFunction 088 */ 089 public <G, H> UnaryCompositeBinaryPredicate(final BinaryPredicate<? super G, ? super H> f, 090 final UnaryFunction<? super L, ? extends G> g, final UnaryFunction<? super R, ? extends H> h) { 091 if (f == null) { 092 throw new IllegalArgumentException("BinaryPredicate must not be null"); 093 } 094 if (g == null || h == null) { 095 throw new IllegalArgumentException("Left and right UnaryFunctions may not be null"); 096 } 097 helper = new Helper<G, H, L, R>(f, g, h); 098 } 099 100 // function interface 101 // ------------------------------------------------------------------------ 102 /** 103 * {@inheritDoc} 104 */ 105 public boolean test(L left, R right) { 106 return helper.test(left, right); 107 } 108 109 /** 110 * {@inheritDoc} 111 */ 112 public boolean equals(Object that) { 113 return that == this || (that instanceof UnaryCompositeBinaryPredicate<?, ?> 114 && equals((UnaryCompositeBinaryPredicate<?, ?>) that)); 115 } 116 117 /** 118 * Learn whether another UnaryCompositeBinaryPredicate is equal to this. 119 * @param that UnaryCompositeBinaryPredicate to test 120 * @return boolean 121 */ 122 public boolean equals(UnaryCompositeBinaryPredicate<?, ?> that) { 123 return null != that && helper.f.equals(that.helper.f) && helper.g.equals(that.helper.g) 124 && helper.h.equals(that.helper.h); 125 } 126 127 /** 128 * {@inheritDoc} 129 */ 130 public int hashCode() { 131 int hash = "UnaryCompositeBinaryPredicate".hashCode(); 132 hash <<= 4; 133 hash ^= helper.f.hashCode(); 134 hash <<= 4; 135 hash ^= helper.g.hashCode(); 136 hash <<= 4; 137 hash ^= helper.h.hashCode(); 138 return hash; 139 } 140 141 /** 142 * {@inheritDoc} 143 */ 144 public String toString() { 145 return "UnaryCompositeBinaryPredicate<" + helper.f + ";" + helper.g + ";" + helper.h + ">"; 146 } 147 148 }