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.core.comparator;
018    
019    import java.io.Serializable;
020    import java.util.Comparator;
021    
022    import org.apache.commons.functor.BinaryPredicate;
023    import org.apache.commons.functor.UnaryPredicate;
024    import org.apache.commons.functor.adapter.RightBoundPredicate;
025    
026    /**
027     * A {@link BinaryPredicate BinaryPredicate} that {@link #test tests}
028     * <code>true</code> iff the left argument is equal to the
029     * right argument under the specified {@link Comparator}.
030     * When no (or a <code>null</code> <code>Comparator</code> is specified,
031     * a {@link Comparable Comparable} <code>Comparator</code> is used.
032     *
033     * @see org.apache.commons.functor.core.IsEqual
034     *
035     * @version $Revision: 1166340 $ $Date: 2011-09-07 21:44:28 +0200 (Wed, 07 Sep 2011) $
036     * @author Rodney Waldhoff
037     *
038     */
039    public final class IsEquivalent<T> implements BinaryPredicate<T, T>, Serializable {
040    
041        /**
042         * Basic IsEquivalent instance.
043         */
044        public static final IsEquivalent<Comparable<?>> INSTANCE = IsEquivalent.<Comparable<?>> instance();
045    
046        /**
047         * serialVersionUID declaration.
048         */
049        private static final long serialVersionUID = -6392784113015793664L;
050    
051        private final Comparator<? super T> comparator;
052    
053        /**
054         * Create a new IsEquivalent.
055         */
056        @SuppressWarnings("unchecked")
057        public IsEquivalent() {
058            this(ComparableComparator.INSTANCE);
059        }
060    
061        /**
062         * Construct an <code>IsEquivalent</code> {@link BinaryPredicate predicate}
063         * for the given {@link Comparator Comparator}.
064         *
065         * @param comparator the {@link Comparator Comparator}, when <code>null</code>,
066         *        a <code>Comparator</code> for {@link Comparable Comparable}s will
067         *        be used.
068         */
069        public IsEquivalent(Comparator<? super T> comparator) {
070            if (comparator == null) {
071                throw new IllegalArgumentException("Comparator must not be null");
072            }
073            this.comparator = comparator;
074        }
075    
076        /**
077         * Return <code>true</code> iff the <i>left</i> parameter is
078         * equal to the <i>right</i> parameter under my current
079         * {@link Comparator Comparator}.
080         * {@inheritDoc}
081         */
082        public boolean test(T left, T right) {
083            return comparator.compare(left, right) == 0;
084        }
085    
086        /**
087         * {@inheritDoc}
088         */
089        public boolean equals(Object that) {
090            return that == this || (that instanceof IsEquivalent<?> && equals((IsEquivalent<?>) that));
091        }
092    
093        /**
094         * Learn whether a given IsEquivalent is equal to this.
095         * @param that IsEquivalent to test
096         * @return boolean
097         */
098        public boolean equals(IsEquivalent<?> that) {
099            if (null != that) {
100                if (null == comparator) {
101                    return null == that.comparator;
102                }
103                return comparator.equals(that.comparator);
104            }
105            return false;
106        }
107    
108        /**
109         * {@inheritDoc}
110         */
111        public int hashCode() {
112            int hash = "IsEquivalent".hashCode();
113            // by construction, comparator is never null
114            hash ^= comparator.hashCode();
115            return hash;
116        }
117    
118        /**
119         * {@inheritDoc}
120         */
121        public String toString() {
122            return "IsEquivalent<" + comparator + ">";
123        }
124    
125        /**
126         * Get a basic IsEquivalent instance.
127         * @param T
128         * @return IsEquivalent<T>
129         */
130        @SuppressWarnings("unchecked")
131        public static <T extends Comparable<?>> IsEquivalent<T> instance() {
132            return new IsEquivalent<T>(ComparableComparator.INSTANCE);
133        }
134    
135        /**
136         * Get an IsEquivalent instance that always compares to <code>arg</code>.
137         * @param right argument
138         * @return UnaryPredicate
139         */
140        public static <T extends Comparable<?>> UnaryPredicate<T> instance(T right) {
141            return RightBoundPredicate.bind(instance(), right);
142        }
143    
144    }