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