View Javadoc

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  
23  /**
24   * A {@link BinaryFunction BinaryFunction} composed of
25   * three binary functions, <i>f</i>, <i>g</i> and <i>h</i>,
26   * evaluating the ordered parameters <i>x</i>, <i>y</i>
27   * to <code><i>f</i>(<i>g</i>(<i>x</i>,<i>y</i>),<i>h</i>(<i>x</i>,<i>y</i>))</code>.
28   * <p>
29   * Note that although this class implements
30   * {@link Serializable}, a given instance will
31   * only be truly <code>Serializable</code> if all the
32   * underlying functors are.  Attempts to serialize
33   * an instance whose delegates are not all
34   * <code>Serializable</code> will result in an exception.
35   * </p>
36   * @version $Revision: 1171154 $ $Date: 2011-09-15 17:58:38 +0200 (Thu, 15 Sep 2011) $
37   * @author Rodney Waldhoff
38   */
39  public class BinaryCompositeBinaryFunction<L, R, T> implements BinaryFunction<L, R, T>, Serializable {
40  
41      /**
42       * serialVersionUID declaration.
43       */
44      private static final long serialVersionUID = 2570517284319064043L;
45  
46      /** Base hash integer used to shift hash */
47      private static final int HASH_SHIFT = 4;
48  
49      /**
50       * Type-remembering Helper
51       *
52       * @param <G>
53       * @param <H>
54       */
55      private static class Helper<G, H, L, R, T> implements BinaryFunction<L, R, T>, Serializable {
56          /**
57           * serialVersionUID declaration.
58           */
59          private static final long serialVersionUID = 6013646799505641592L;
60          private BinaryFunction<? super G, ? super H, ? extends T> f;
61          private BinaryFunction<? super L, ? super R, ? extends G> g;
62          private BinaryFunction<? super L, ? super R, ? extends H> h;
63  
64          /**
65           * Create a new Helper.
66           * @param f final BinaryFunction to evaluate
67           * @param g left preceding BinaryFunction
68           * @param h right preceding BinaryFunction
69           */
70          public Helper(BinaryFunction<? super G, ? super H, ? extends T> f,
71                  BinaryFunction<? super L, ? super R, ? extends G> g,
72                  BinaryFunction<? super L, ? super R, ? extends H> h) {
73              this.f = f;
74              this.g = g;
75              this.h = h;
76          }
77  
78          /**
79           * {@inheritDoc}
80           */
81          public T evaluate(L left, R right) {
82              return f.evaluate(g.evaluate(left, right), h.evaluate(left, right));
83          }
84      }
85  
86      private final Helper<?, ?, L, R, T> helper;
87  
88      // constructor
89      // ------------------------------------------------------------------------
90      /**
91       * Create a new BinaryCompositeBinaryFunction.
92       * @param f final BinaryFunction to evaluate
93       * @param g left preceding BinaryFunction
94       * @param h right preceding BinaryFunction
95       */
96      public <G, H> BinaryCompositeBinaryFunction(BinaryFunction<? super G, ? super H, ? extends T> f,
97              BinaryFunction<? super L, ? super R, ? extends G> g, BinaryFunction<? super L, ? super R, ? extends H> h) {
98          if (f == null || g == null || h == null) {
99              throw new IllegalArgumentException("BinaryFunction arguments may not be null");
100         }
101         this.helper = new Helper<G, H, L, R, T>(f, g, h);
102     }
103 
104     // function interface
105     // ------------------------------------------------------------------------
106     /**
107      * {@inheritDoc}
108      */
109     public final T evaluate(L left, R right) {
110         return helper.evaluate(left, right);
111     }
112 
113     /**
114      * {@inheritDoc}
115      */
116     public final boolean equals(Object that) {
117         return that == this || (that instanceof BinaryCompositeBinaryFunction<?, ?, ?>
118                                     && equals((BinaryCompositeBinaryFunction<?, ?, ?>) that));
119     }
120 
121     /**
122      * Learn whether another BinaryCompositeBinaryFunction is equal to this.
123      * @param that BinaryCompositeBinaryFunction to test
124      * @return boolean
125      */
126     public final boolean equals(BinaryCompositeBinaryFunction<?, ?, ?> that) {
127         return null != that
128                 && helper.f.equals(that.helper.f)
129                 && helper.g.equals(that.helper.g)
130                 && helper.h.equals(that.helper.h);
131     }
132 
133     /**
134      * {@inheritDoc}
135      */
136     public int hashCode() {
137         int hash = "BinaryCompositeBinaryFunction".hashCode();
138             hash <<= HASH_SHIFT;
139             hash ^= helper.f.hashCode();
140             hash <<= HASH_SHIFT;
141             hash ^= helper.g.hashCode();
142             hash <<= HASH_SHIFT;
143             hash ^= helper.h.hashCode();
144         return hash;
145     }
146 
147     /**
148      * {@inheritDoc}
149      */
150     public String toString() {
151         return "BinaryCompositeBinaryFunction<" + helper.f + ";" + helper.g + ";" + helper.h + ">";
152     }
153 
154 }