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.BinaryFunction;
022 import org.apache.commons.functor.UnaryFunction;
023
024 /**
025 * A {@link BinaryFunction BinaryFunction} composed of
026 * one binary function, <i>f</i>, and two unary
027 * functions, <i>g</i> and <i>h</i>,
028 * evaluating the ordered parameters <i>x</i>, <i>y</i>
029 * to <code><i>f</i>(<i>g</i>(<i>x</i>),<i>h</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 UnaryCompositeBinaryFunction<L, R, T> implements BinaryFunction<L, R, T>, Serializable {
042
043 /**
044 * serialVersionUID declaration.
045 */
046 private static final long serialVersionUID = 264219357293822629L;
047
048 private static class Helper<G, H, L, R, T> implements BinaryFunction<L, R, T>, Serializable {
049 /**
050 * serialVersionUID declaration.
051 */
052 private static final long serialVersionUID = 4513309646430305164L;
053 private BinaryFunction<? super G, ? super H, ? extends T> f;
054 private UnaryFunction<? super L, ? extends G> g;
055 private UnaryFunction<? super R, ? extends H> h;
056
057 /**
058 * Create a new Helper.
059 * @param f BinaryFunction to receive <code>(output(g), output(h))</code>
060 * @param g left UnaryFunction
061 * @param h right UnaryFunction
062 */
063 public Helper(BinaryFunction<? super G, ? super H, ? extends T> f, UnaryFunction<? super L, ? extends G> g,
064 UnaryFunction<? super R, ? extends H> h) {
065 this.f = f;
066 this.g = g;
067 this.h = h;
068 }
069
070 /**
071 * {@inheritDoc}
072 */
073 public T evaluate(L left, R right) {
074 return f.evaluate(g.evaluate(left), h.evaluate(right));
075 }
076 }
077
078 private final Helper<?, ?, L, R, T> helper;
079
080 // constructor
081 // ------------------------------------------------------------------------
082 /**
083 * Create a new UnaryCompositeBinaryFunction.
084 * @param f BinaryFunction to receive <code>(output(g), output(h))</code>
085 * @param g left UnaryFunction
086 * @param h right UnaryFunction
087 */
088 public <G, H> UnaryCompositeBinaryFunction(BinaryFunction<? super G, ? super H, ? extends T> f,
089 UnaryFunction<? super L, ? extends G> g, UnaryFunction<? super R, ? extends H> h) {
090 if (f == null) {
091 throw new IllegalArgumentException("BinaryFunction must not be null");
092 }
093 if (g == null || h == null) {
094 throw new IllegalArgumentException("Left and right UnaryFunctions may not be null");
095 }
096 this.helper = new Helper<G, H, L, R, T>(f, g, h);
097 }
098
099 // function interface
100 // ------------------------------------------------------------------------
101 /**
102 * {@inheritDoc}
103 */
104 public T evaluate(L left, R right) {
105 return helper.evaluate(left, right);
106 }
107
108 /**
109 * {@inheritDoc}
110 */
111 public boolean equals(Object that) {
112 return that == this || (that instanceof UnaryCompositeBinaryFunction<?, ?, ?>
113 && equals((UnaryCompositeBinaryFunction<?, ?, ?>) that));
114 }
115
116 /**
117 * Learn whether a given UnaryCompositeBinaryFunction is equal to this.
118 * @param that UnaryCompositeBinaryFunction to test
119 * @return boolean
120 */
121 public boolean equals(UnaryCompositeBinaryFunction<?, ?, ?> that) {
122 return null != that
123 && helper.f.equals(that.helper.f)
124 && helper.g.equals(that.helper.g)
125 && helper.h.equals(that.helper.h);
126 }
127
128 /**
129 * {@inheritDoc}
130 */
131 public int hashCode() {
132 int hash = "UnaryCompositeBinaryFunction".hashCode();
133 hash <<= 4;
134 hash ^= helper.f.hashCode();
135 hash <<= 4;
136 hash ^= helper.g.hashCode();
137 hash <<= 4;
138 hash ^= helper.h.hashCode();
139 return hash;
140 }
141
142 /**
143 * {@inheritDoc}
144 */
145 public String toString() {
146 return "UnaryCompositeBinaryFunction<" + helper.f + ";" + helper.g + ";" + helper.h + ">";
147 }
148
149 }