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.adapter;
018    
019    import java.io.Serializable;
020    
021    import org.apache.commons.functor.BinaryFunction;
022    import org.apache.commons.functor.BinaryPredicate;
023    
024    /**
025     * Adapts a <code>Boolean</code>-valued {@link BinaryFunction BinaryFunction} to
026     * the {@link BinaryPredicate BinaryPredicate} interface. <p> Note that although
027     * this class implements {@link Serializable}, a given instance will only be
028     * truly <code>Serializable</code> if the underlying functor is. Attempts to
029     * serialize an instance whose delegate is not <code>Serializable</code> will
030     * result in an exception. </p>
031     * @param <L> the left argument type.
032     * @param <R> the right argument type.
033     * @version $Revision: 1156745 $ $Date: 2011-08-11 21:08:49 +0200 (Thu, 11 Aug 2011) $
034     * @author Rodney Waldhoff
035     */
036    public final class BinaryFunctionBinaryPredicate<L, R> implements BinaryPredicate<L, R>, Serializable {
037        /**
038         * serialVersionUID declaration.
039         */
040        private static final long serialVersionUID = -5150315320718936186L;
041        /** The {@link BinaryFunction BinaryFunction} I'm wrapping. */
042        private final BinaryFunction<? super L, ? super R, Boolean> function;
043    
044        /**
045         * Create an {@link BinaryPredicate BinaryPredicate} wrapping the given
046         * {@link BinaryFunction BinaryFunction}.
047         * @param function the {@link BinaryFunction BinaryFunction} to wrap
048         */
049        public BinaryFunctionBinaryPredicate(final BinaryFunction<? super L, ? super R, Boolean> function) {
050            if (function == null) {
051                throw new IllegalArgumentException("BinaryFunction argument must not be null");
052            }
053            this.function = function;
054        }
055    
056        /**
057         * {@inheritDoc} Returns the <code>boolean</code> value of the
058         * non-<code>null</code> <code>Boolean</code> returned by the
059         * {@link BinaryFunction#evaluate evaluate} method of my underlying
060         * function.
061         *
062         * The mehod throws NullPointerException if the underlying function returns
063         * <code>null</code>, and
064         * ClassCastException if the underlying function returns a
065         * non-<code>Boolean</code>
066         */
067        public boolean test(final L left, final R right) {
068            return function.evaluate(left, right);
069        }
070    
071        /**
072         * {@inheritDoc}
073         */
074        public boolean equals(final Object that) {
075            return that == this
076                    || (that instanceof BinaryFunctionBinaryPredicate<?, ?>
077                    && equals((BinaryFunctionBinaryPredicate<?, ?>) that));
078        }
079    
080        /**
081         * Learn whether another BinaryFunctionBinaryPredicate is equal to this.
082         * @param that BinaryFunctionBinaryPredicate to test
083         * @return boolean
084         */
085        public boolean equals(final BinaryFunctionBinaryPredicate<?, ?> that) {
086            return null != that && (null == function ? null == that.function : function.equals(that.function));
087        }
088    
089        /**
090         * {@inheritDoc}
091         */
092        public int hashCode() {
093            int hash = "BinaryFunctionBinaryPredicate".hashCode();
094            if (null != function) {
095                hash ^= function.hashCode();
096            }
097            return hash;
098        }
099    
100        /**
101         * {@inheritDoc}
102         */
103        public String toString() {
104            return "BinaryFunctionBinaryPredicate<" + function + ">";
105        }
106    
107        /**
108         * Adapt the given, possibly-<code>null</code>, {@link BinaryFunction
109         * BinaryFunction} to the {@link BinaryPredicate BinaryPredicate} interface.
110         * When the given <code>BinaryFunction</code> is <code>null</code>, returns
111         * <code>null</code>.
112         *
113         * @param <L> left type
114         * @param <R> right type
115         * @param <T> result type
116         * @param function the possibly-<code>null</code> {@link BinaryFunction
117         * BinaryFunction} to adapt
118         * @return a <code>BinaryFunctionBinaryPredicate</code> wrapping the given
119         * {@link BinaryFunction BinaryFunction}, or <code>null</code> if the given
120         * <code>BinaryFunction</code> is <code>null</code>
121         */
122        public static <L, R, T> BinaryFunctionBinaryPredicate<L, R> adapt(
123                final BinaryFunction<? super L, ? super R, Boolean> function) {
124            return null == function ? null : new BinaryFunctionBinaryPredicate<L, R>(function);
125        }
126    
127    }