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.adapter;
018
019import org.apache.commons.functor.BinaryFunction;
020import org.apache.commons.functor.Function;
021import org.apache.commons.lang3.Validate;
022
023/**
024 * Adapts a
025 * {@link BinaryFunction BinaryFunction}
026 * to the
027 * {@link Function Function} interface
028 * using a constant left-side argument.
029 *
030 * @param <A> the argument type.
031 * @param <T> the returned value type.
032 * @version $Revision: 1537906 $ $Date: 2013-11-01 12:47:33 +0100 (Fr, 01 Nov 2013) $
033 */
034public final class LeftBoundFunction<A, T> implements Function<A, T> {
035    /** The {@link BinaryFunction BinaryFunction} I'm wrapping. */
036    private final BinaryFunction<Object, ? super A, ? extends T> function;
037    /** The parameter to pass to {@code function}. */
038    private final Object param;
039
040    /**
041     * Create a new LeftBoundFunction instance.
042     * @param <L> bound arg type
043     * @param function the function to adapt
044     * @param arg the constant argument to use
045     */
046    @SuppressWarnings("unchecked")
047    public <L> LeftBoundFunction(BinaryFunction<? super L, ? super A, ? extends T> function, L arg) {
048        this.function =
049            (BinaryFunction<Object, ? super A, ? extends T>) Validate.notNull(
050                function, "BinaryFunction argument was null");
051        this.param = arg;
052    }
053
054    /**
055     * {@inheritDoc}
056     */
057    public T evaluate(A obj) {
058        return function.evaluate(param, obj);
059    }
060
061    /**
062     * {@inheritDoc}
063     */
064    @Override
065    public boolean equals(Object obj) {
066        if (obj == this) {
067            return true;
068        }
069        if (!(obj instanceof LeftBoundFunction<?, ?>)) {
070            return false;
071        }
072        LeftBoundFunction<?, ?> that = (LeftBoundFunction<?, ?>) obj;
073        return this.function.equals(that.function)
074                && (null == this.param ? null == that.param : this.param.equals(that.param));
075    }
076
077    /**
078     * {@inheritDoc}
079     */
080    @Override
081    public int hashCode() {
082        int hash = "LeftBoundFunction".hashCode();
083        hash <<= 2;
084        hash ^= function.hashCode();
085        if (null != param) {
086            hash <<= 2;
087            hash ^= param.hashCode();
088        }
089        return hash;
090    }
091
092    /**
093     * {@inheritDoc}
094     */
095    @Override
096    public String toString() {
097        return "LeftBoundFunction<" + function + "(" + param + ",?)>";
098    }
099
100    /**
101     * Adapt a BinaryFunction as a Function.
102     * @param <L> left type
103     * @param <R> right type
104     * @param <T> result type
105     * @param function to adapt
106     * @param arg left side argument
107     * @return LeftBoundFunction
108     */
109    public static <L, R, T> LeftBoundFunction<R, T> bind(
110            BinaryFunction<? super L, ? super R, ? extends T> function, L arg) {
111        return null == function ? null : new LeftBoundFunction<R, T>(function, arg);
112    }
113
114}