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
018package org.apache.commons.beanutils;
019
020import java.lang.reflect.InvocationTargetException;
021
022import org.apache.commons.collections.Predicate;
023import org.apache.commons.logging.Log;
024import org.apache.commons.logging.LogFactory;
025
026/**
027 * <p>Predicate implementation that applies the given <code>Predicate</code>
028 * to the result of calling the given property getter.
029 * </p>
030 *
031 */
032public class BeanPredicate implements Predicate {
033
034    private final Log log = LogFactory.getLog(this.getClass());
035
036    /** Name of the property whose value will be predicated */
037    private String propertyName;
038    /** <code>Predicate</code> to be applied to the property value */
039    private Predicate predicate;
040
041    /**
042     * Constructs a <code>BeanPredicate</code> that applies the given
043     * <code>Predicate</code> to the named property value.
044     * @param propertyName the name of the property whose value is to be predicated,
045     * not null
046     * @param predicate the <code>Predicate</code> to be applied,
047     * not null
048     */
049    public BeanPredicate(final String propertyName, final Predicate predicate) {
050        this.propertyName = propertyName;
051        this.predicate = predicate;
052    }
053
054    /**
055     * Evaluates the given object by applying the {@link #getPredicate()}
056     * to a property value named by {@link #getPropertyName()}.
057     *
058     * @param object The object being evaluated
059     * @return the result of the predicate evaluation
060     * @throws IllegalArgumentException when the property cannot be evaluated
061     */
062    @Override
063    public boolean evaluate(final Object object) {
064
065        boolean evaluation = false;
066
067        try {
068            final Object propValue = PropertyUtils.getProperty( object, propertyName );
069            evaluation = predicate.evaluate(propValue);
070        } catch (final IllegalArgumentException e) {
071            final String errorMsg = "Problem during evaluation.";
072            log.error("ERROR: " + errorMsg, e);
073            throw e;
074        } catch (final IllegalAccessException e) {
075            final String errorMsg = "Unable to access the property provided.";
076            log.error(errorMsg, e);
077            throw new IllegalArgumentException(errorMsg);
078        } catch (final InvocationTargetException e) {
079            final String errorMsg = "Exception occurred in property's getter";
080            log.error(errorMsg, e);
081            throw new IllegalArgumentException(errorMsg);
082        } catch (final NoSuchMethodException e) {
083            final String errorMsg = "Property not found.";
084            log.error(errorMsg, e);
085            throw new IllegalArgumentException(errorMsg);
086        }
087
088        return evaluation;
089    }
090
091    /**
092     * Gets the <code>Predicate</code> to be applied to the value of the named property
093     * during {@link #evaluate}.
094     * @return <code>Predicate</code>, not null
095     */
096    public Predicate getPredicate() {
097        return predicate;
098    }
099
100    /**
101     * Gets the name of the property whose value is to be predicated.
102     * in the evaluation.
103     * @return the property name, not null
104     */
105    public String getPropertyName() {
106        return propertyName;
107    }
108
109    /**
110     * Sets the <code>Predicate</code> to be applied to the value of the named property
111     * during {@link #evaluate(Object)}.
112     * @param predicate <code>Predicate</code>, not null
113     */
114    public void setPredicate(final Predicate predicate) {
115        this.predicate = predicate;
116    }
117
118    /**
119     * Sets the name of the property whose value is to be predicated.
120     * @param propertyName the name of the property whose value is to be predicated,
121     * not null
122     */
123    public void setPropertyName(final String propertyName) {
124        this.propertyName = propertyName;
125    }
126
127}