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.BinaryPredicate;
020import org.apache.commons.functor.Predicate;
021import org.apache.commons.lang3.Validate;
022
023/**
024 * Adapts a
025 * {@link BinaryPredicate BinaryPredicate}
026 * to the
027 * {@link Predicate Predicate} interface
028 * using a constant left-side argument.
029 *
030 * @param <A> the argument type.
031 * @version $Revision: 1537906 $ $Date: 2013-11-01 12:47:33 +0100 (Fr, 01 Nov 2013) $
032 */
033public final class LeftBoundPredicate<A> implements Predicate<A> {
034
035    /** The {@link BinaryPredicate BinaryPredicate} I'm wrapping. */
036    private final BinaryPredicate<Object, ? super A> predicate;
037    /** The parameter to pass to {@code predicate}. */
038    private final Object param;
039
040    /**
041     * Create a new LeftBoundPredicate.
042     * @param <L> the left argument type.
043     * @param predicate the predicate to adapt
044     * @param arg the constant argument to use
045     */
046    @SuppressWarnings("unchecked")
047    public <L> LeftBoundPredicate(BinaryPredicate<? super L, ? super A> predicate, L arg) {
048        this.predicate =
049            (BinaryPredicate<Object, ? super A>) Validate.notNull(predicate,
050                "BinaryPredicate argument was null");
051        this.param = arg;
052    }
053
054    /**
055     * {@inheritDoc}
056     */
057    public boolean test(A obj) {
058        return predicate.test(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 LeftBoundPredicate<?>)) {
070            return false;
071        }
072        LeftBoundPredicate<?> that = (LeftBoundPredicate<?>) obj;
073        return predicate.equals(that.predicate)
074                && (null == param ? null == that.param : param.equals(that.param));
075    }
076
077    /**
078     * {@inheritDoc}
079     */
080    @Override
081    public int hashCode() {
082        int hash = "LeftBoundPredicate".hashCode();
083        hash <<= 2;
084        hash ^= predicate.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 "LeftBoundPredicate<" + predicate + "(" + param + ",?)>";
098    }
099
100    /**
101     * Adapt a BinaryPredicate to the Predicate interface.
102     * @param <L> the left argument type.
103     * @param <R> the right argument type.
104     * @param predicate to adapt
105     * @param arg Object argument to always send as the left operand to the wrapped function
106     * @return LeftBoundPredicate
107     */
108    public static <L, R> LeftBoundPredicate<R> bind(BinaryPredicate<? super L, ? super R> predicate, L arg) {
109        return null == predicate ? null : new LeftBoundPredicate<R>(predicate, arg);
110    }
111}