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.core.collection;
018
019import java.io.Serializable;
020import java.lang.reflect.Array;
021import java.util.Collection;
022
023import org.apache.commons.functor.BinaryPredicate;
024import org.apache.commons.functor.UnaryPredicate;
025import org.apache.commons.functor.adapter.RightBoundPredicate;
026import org.apache.commons.lang3.Validate;
027
028/**
029 * A {@link BinaryPredicate} that checks to see if the
030 * specified object is an element of the specified
031 * Collection.
032 *
033 * @param <L> the left argument type.
034 * @param <R> the right argument type.
035 * @since 1.0
036 * @version $Revision: 1345136 $ $Date: 2012-06-01 08:47:06 -0400 (Fri, 01 Jun 2012) $
037 */
038public final class IsElementOf<L, R> implements BinaryPredicate<L, R>, Serializable {
039    // static members
040    //---------------------------------------------------------------
041
042    /**
043     * serialVersionUID declaration.
044     */
045    private static final long serialVersionUID = -7639051806015321070L;
046    /**
047     * A static {@link IsElementOf} instance reference.
048     */
049    private static final IsElementOf<Object, Object> INSTANCE = new IsElementOf<Object, Object>();
050
051    // constructors
052    //---------------------------------------------------------------
053    /**
054     * Create a new IsElementOf.
055     */
056    public IsElementOf() {
057    }
058
059    // instance methods
060    //---------------------------------------------------------------
061    /**
062     * {@inheritDoc}
063     */
064    public boolean test(L obj, R col) {
065        Validate.notNull(col, "Right side argument must not be null.");
066        if (col instanceof Collection<?>) {
067            return testCollection(obj, (Collection<?>) col);
068        }
069        if (col.getClass().isArray()) {
070            return testArray(obj, col);
071        }
072        throw new IllegalArgumentException("Expected Collection or Array, found " + col.getClass());
073    }
074
075    /**
076     * {@inheritDoc}
077     */
078    @Override
079    public boolean equals(Object obj) {
080        return (obj instanceof IsElementOf<?, ?>);
081    }
082
083    /**
084     * {@inheritDoc}
085     */
086    @Override
087    public int hashCode() {
088        return "IsElementOf".hashCode();
089    }
090
091    /**
092     * {@inheritDoc}
093     */
094    @Override
095    public String toString() {
096        return "IsElementOf";
097    }
098
099    /**
100     * Test a collection.
101     * @param obj to find
102     * @param col to search
103     * @return boolean
104     */
105    private boolean testCollection(Object obj, Collection<?> col) {
106        return col.contains(obj);
107    }
108
109    /**
110     * Test an array.
111     * @param obj to find
112     * @param array to search
113     * @return boolean
114     */
115    private boolean testArray(Object obj, Object array) {
116        for (int i = 0, m = Array.getLength(array); i < m; i++) {
117            Object value = Array.get(array, i);
118            if (obj == value) {
119                return true;
120            }
121            if (obj != null && obj.equals(value)) {
122                return true;
123            }
124        }
125        return false;
126    }
127
128    // static methods
129    //---------------------------------------------------------------
130    /**
131     * Get an IsElementOf instance.
132     * @return IsElementOf
133     */
134    public static IsElementOf<Object, Object> instance() {
135        return INSTANCE;
136    }
137
138    /**
139     * Get an IsElementOf(collection|array) UnaryPredicate.
140     *
141     * @param <A> the UnaryPredicate argument generic type
142     * @param obj collection/array to search
143     * @return UnaryPredicate
144     */
145    public static <A> UnaryPredicate<A> instance(Object obj) {
146        if (null == obj) {
147            throw new NullPointerException("Argument must not be null");
148        } else if (obj instanceof Collection<?>) {
149            return new RightBoundPredicate<A>(new IsElementOf<A, Object>(), obj);
150        } else if (obj.getClass().isArray()) {
151            return new RightBoundPredicate<A>(new IsElementOf<A, Object>(), obj);
152        } else {
153            throw new IllegalArgumentException("Expected Collection or Array, found " + obj.getClass());
154        }
155    }
156
157}