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 */ 017package org.apache.commons.functor.core.composite; 018 019import java.io.Serializable; 020 021import org.apache.commons.functor.BinaryFunction; 022import org.apache.commons.lang3.Validate; 023 024/** 025 * A {@link BinaryFunction BinaryFunction} composed of 026 * three binary functions, <i>f</i>, <i>g</i> and <i>h</i>, 027 * evaluating the ordered parameters <i>x</i>, <i>y</i> 028 * to <code><i>f</i>(<i>g</i>(<i>x</i>,<i>y</i>),<i>h</i>(<i>x</i>,<i>y</i>))</code>. 029 * <p> 030 * Note that although this class implements 031 * {@link Serializable}, a given instance will 032 * only be truly <code>Serializable</code> if all the 033 * underlying functors are. Attempts to serialize 034 * an instance whose delegates are not all 035 * <code>Serializable</code> will result in an exception. 036 * </p> 037 * @param <L> the function left argument type. 038 * @param <R> the function right argument type. 039 * @param <T> the function returned value type. 040 * @version $Revision: 1345136 $ $Date: 2012-06-01 08:47:06 -0400 (Fri, 01 Jun 2012) $ 041 */ 042public class BinaryCompositeBinaryFunction<L, R, T> implements BinaryFunction<L, R, T>, Serializable { 043 044 /** 045 * serialVersionUID declaration. 046 */ 047 private static final long serialVersionUID = 2570517284319064043L; 048 049 /** Base hash integer used to shift hash. */ 050 private static final int HASH_SHIFT = 4; 051 052 /** 053 * Type-remembering Helper. 054 * 055 * @param <G> the function left argument type. 056 * @param <H> the function right argument type. 057 */ 058 private static class Helper<G, H, L, R, T> implements BinaryFunction<L, R, T>, Serializable { 059 /** 060 * serialVersionUID declaration. 061 */ 062 private static final long serialVersionUID = 6013646799505641592L; 063 /** 064 * Global evaluator. 065 */ 066 private BinaryFunction<? super G, ? super H, ? extends T> f; 067 /** 068 * This function evaluation will be the left argument of main evaluator. 069 */ 070 private BinaryFunction<? super L, ? super R, ? extends G> g; 071 /** 072 * This function evaluation will be the right argument of main evaluator. 073 */ 074 private BinaryFunction<? super L, ? super R, ? extends H> h; 075 076 /** 077 * Create a new Helper. 078 * @param f final BinaryFunction to evaluate 079 * @param g left preceding BinaryFunction 080 * @param h right preceding BinaryFunction 081 */ 082 public Helper(BinaryFunction<? super G, ? super H, ? extends T> f, 083 BinaryFunction<? super L, ? super R, ? extends G> g, 084 BinaryFunction<? super L, ? super R, ? extends H> h) { 085 this.f = f; 086 this.g = g; 087 this.h = h; 088 } 089 090 /** 091 * {@inheritDoc} 092 */ 093 public T evaluate(L left, R right) { 094 return f.evaluate(g.evaluate(left, right), h.evaluate(left, right)); 095 } 096 } 097 098 /** 099 * The helper used for the evaluation. 100 */ 101 private final Helper<?, ?, L, R, T> helper; 102 103 // constructor 104 // ------------------------------------------------------------------------ 105 /** 106 * Create a new BinaryCompositeBinaryFunction. 107 * 108 * @param <G> the main function left argument type. 109 * @param <H> the main function right argument type. 110 * @param f final BinaryFunction to evaluate 111 * @param g left preceding BinaryFunction 112 * @param h right preceding BinaryFunction 113 */ 114 public <G, H> BinaryCompositeBinaryFunction(BinaryFunction<? super G, ? super H, ? extends T> f, 115 BinaryFunction<? super L, ? super R, ? extends G> g, BinaryFunction<? super L, ? super R, ? extends H> h) { 116 this.helper = new Helper<G, H, L, R, T>( 117 Validate.notNull(f, "final BinaryFunction argument must not be null"), 118 Validate.notNull(g, "left preceding BinaryFunction argument must not be null"), 119 Validate.notNull(h, "right preceding BinaryFunction argument must not be null") 120 ); 121 } 122 123 // function interface 124 // ------------------------------------------------------------------------ 125 /** 126 * {@inheritDoc} 127 */ 128 public final T evaluate(L left, R right) { 129 return helper.evaluate(left, right); 130 } 131 132 /** 133 * {@inheritDoc} 134 */ 135 @Override 136 public final boolean equals(Object that) { 137 return that == this || (that instanceof BinaryCompositeBinaryFunction<?, ?, ?> 138 && equals((BinaryCompositeBinaryFunction<?, ?, ?>) that)); 139 } 140 141 /** 142 * Learn whether another BinaryCompositeBinaryFunction is equal to this. 143 * @param that BinaryCompositeBinaryFunction to test 144 * @return boolean 145 */ 146 public final boolean equals(BinaryCompositeBinaryFunction<?, ?, ?> that) { 147 return null != that 148 && helper.f.equals(that.helper.f) 149 && helper.g.equals(that.helper.g) 150 && helper.h.equals(that.helper.h); 151 } 152 153 /** 154 * {@inheritDoc} 155 */ 156 @Override 157 public int hashCode() { 158 int hash = "BinaryCompositeBinaryFunction".hashCode(); 159 hash <<= HASH_SHIFT; 160 hash ^= helper.f.hashCode(); 161 hash <<= HASH_SHIFT; 162 hash ^= helper.g.hashCode(); 163 hash <<= HASH_SHIFT; 164 hash ^= helper.h.hashCode(); 165 return hash; 166 } 167 168 /** 169 * {@inheritDoc} 170 */ 171 @Override 172 public String toString() { 173 return "BinaryCompositeBinaryFunction<" + helper.f + ";" + helper.g + ";" + helper.h + ">"; 174 } 175 176}