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