⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 propertyutilsbean.java

📁 这是一个有关common beanutils 的源码
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.commons.beanutils;


import java.beans.BeanInfo;
import java.beans.IndexedPropertyDescriptor;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.expression.DefaultResolver;
import org.apache.commons.beanutils.expression.Resolver;
import org.apache.commons.collections.FastHashMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


/**
 * Utility methods for using Java Reflection APIs to facilitate generic
 * property getter and setter operations on Java objects.  Much of this
 * code was originally included in <code>BeanUtils</code>, but has been
 * separated because of the volume of code involved.
 * <p>
 * In general, the objects that are examined and modified using these
 * methods are expected to conform to the property getter and setter method
 * naming conventions described in the JavaBeans Specification (Version 1.0.1).
 * No data type conversions are performed, and there are no usage of any
 * <code>PropertyEditor</code> classes that have been registered, although
 * a convenient way to access the registered classes themselves is included.
 * <p>
 * For the purposes of this class, five formats for referencing a particular
 * property value of a bean are defined, with the <i>default</i> layout of an
 * identifying String in parentheses. However the notation for these formats
 * and how they are resolved is now (since BeanUtils 1.8.0) controlled by
 * the configured {@link Resolver} implementation:
 * <ul>
 * <li><strong>Simple (<code>name</code>)</strong> - The specified
 *     <code>name</code> identifies an individual property of a particular
 *     JavaBean.  The name of the actual getter or setter method to be used
 *     is determined using standard JavaBeans instrospection, so that (unless
 *     overridden by a <code>BeanInfo</code> class, a property named "xyz"
 *     will have a getter method named <code>getXyz()</code> or (for boolean
 *     properties only) <code>isXyz()</code>, and a setter method named
 *     <code>setXyz()</code>.</li>
 * <li><strong>Nested (<code>name1.name2.name3</code>)</strong> The first
 *     name element is used to select a property getter, as for simple
 *     references above.  The object returned for this property is then
 *     consulted, using the same approach, for a property getter for a
 *     property named <code>name2</code>, and so on.  The property value that
 *     is ultimately retrieved or modified is the one identified by the
 *     last name element.</li>
 * <li><strong>Indexed (<code>name[index]</code>)</strong> - The underlying
 *     property value is assumed to be an array, or this JavaBean is assumed
 *     to have indexed property getter and setter methods.  The appropriate
 *     (zero-relative) entry in the array is selected.  <code>List</code>
 *     objects are now also supported for read/write.  You simply need to define
 *     a getter that returns the <code>List</code></li>
 * <li><strong>Mapped (<code>name(key)</code>)</strong> - The JavaBean
 *     is assumed to have an property getter and setter methods with an
 *     additional attribute of type <code>java.lang.String</code>.</li>
 * <li><strong>Combined (<code>name1.name2[index].name3(key)</code>)</strong> -
 *     Combining mapped, nested, and indexed references is also
 *     supported.</li>
 * </ul>
 *
 * @author Craig R. McClanahan
 * @author Ralph Schaer
 * @author Chris Audley
 * @author Rey Francois
 * @author Gregor Rayman
 * @author Jan Sorensen
 * @author Scott Sanders
 * @author Erik Meade
 * @version $Revision: 687190 $ $Date: 2008-08-19 23:51:19 +0100 (Tue, 19 Aug 2008) $
 * @see Resolver
 * @see PropertyUtils
 * @since 1.7
 */

public class PropertyUtilsBean {

    private Resolver resolver = new DefaultResolver();

    // --------------------------------------------------------- Class Methods

    /**
     * Return the PropertyUtils bean instance.
     * @return The PropertyUtils bean instance
     */
    protected static PropertyUtilsBean getInstance() {
        return BeanUtilsBean.getInstance().getPropertyUtils();
    }

    // --------------------------------------------------------- Variables

    /**
     * The cache of PropertyDescriptor arrays for beans we have already
     * introspected, keyed by the java.lang.Class of this object.
     */
    private WeakFastHashMap descriptorsCache = null;
    private WeakFastHashMap mappedDescriptorsCache = null;
    private static final Class[] EMPTY_CLASS_PARAMETERS = new Class[0];
    private static final Class[] LIST_CLASS_PARAMETER = new Class[] {java.util.List.class};
    
    /** An empty object array */
    private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];

    /** Log instance */
    private Log log = LogFactory.getLog(PropertyUtils.class);
    
    // ---------------------------------------------------------- Constructors
    
    /** Base constructor */
    public PropertyUtilsBean() {
        descriptorsCache = new WeakFastHashMap();
        descriptorsCache.setFast(true);
        mappedDescriptorsCache = new WeakFastHashMap();
        mappedDescriptorsCache.setFast(true);
    }


    // --------------------------------------------------------- Public Methods


    /**
     * Return the configured {@link Resolver} implementation used by BeanUtils.
     * <p>
     * The {@link Resolver} handles the <i>property name</i>
     * expressions and the implementation in use effectively
     * controls the dialect of the <i>expression language</i>
     * that BeanUtils recongnises.
     * <p>
     * {@link DefaultResolver} is the default implementation used.
     *
     * @return resolver The property expression resolver.
     */
    public Resolver getResolver() {
        return resolver;
    }

    /**
     * Configure the {@link Resolver} implementation used by BeanUtils.
     * <p>
     * The {@link Resolver} handles the <i>property name</i>
     * expressions and the implementation in use effectively
     * controls the dialect of the <i>expression language</i>
     * that BeanUtils recongnises.
     * <p>
     * {@link DefaultResolver} is the default implementation used.
     *
     * @param resolver The property expression resolver.
     */
    public void setResolver(Resolver resolver) {
        if (resolver == null) {
            this.resolver = new DefaultResolver();
        } else {
            this.resolver = resolver;
        }
    }

    /**
     * Clear any cached property descriptors information for all classes
     * loaded by any class loaders.  This is useful in cases where class
     * loaders are thrown away to implement class reloading.
     */
    public void clearDescriptors() {

        descriptorsCache.clear();
        mappedDescriptorsCache.clear();
        Introspector.flushCaches();

    }


    /**
     * <p>Copy property values from the "origin" bean to the "destination" bean
     * for all cases where the property names are the same (even though the
     * actual getter and setter methods might have been customized via
     * <code>BeanInfo</code> classes).  No conversions are performed on the
     * actual property values -- it is assumed that the values retrieved from
     * the origin bean are assignment-compatible with the types expected by
     * the destination bean.</p>
     *
     * <p>If the origin "bean" is actually a <code>Map</code>, it is assumed
     * to contain String-valued <strong>simple</strong> property names as the keys, pointing
     * at the corresponding property values that will be set in the destination
     * bean.<strong>Note</strong> that this method is intended to perform 
     * a "shallow copy" of the properties and so complex properties 
     * (for example, nested ones) will not be copied.</p>
     * 
     * <p>Note, that this method will not copy a List to a List, or an Object[] 
     * to an Object[]. It's specifically for copying JavaBean properties. </p>
     *
     * @param dest Destination bean whose properties are modified
     * @param orig Origin bean whose properties are retrieved
     *
     * @exception IllegalAccessException if the caller does not have
     *  access to the property accessor method
     * @exception IllegalArgumentException if the <code>dest</code> or
     *  <code>orig</code> argument is null
     * @exception InvocationTargetException if the property accessor method
     *  throws an exception
     * @exception NoSuchMethodException if an accessor method for this
     *  propety cannot be found
     */
    public void copyProperties(Object dest, Object orig)
            throws IllegalAccessException, InvocationTargetException,
            NoSuchMethodException {

        if (dest == null) {
            throw new IllegalArgumentException
                    ("No destination bean specified");
        }
        if (orig == null) {
            throw new IllegalArgumentException("No origin bean specified");
        }

        if (orig instanceof DynaBean) {
            DynaProperty[] origDescriptors =
                ((DynaBean) orig).getDynaClass().getDynaProperties();
            for (int i = 0; i < origDescriptors.length; i++) {
                String name = origDescriptors[i].getName();
                if (isReadable(orig, name) && isWriteable(dest, name)) {
                    try {
                        Object value = ((DynaBean) orig).get(name);
                        if (dest instanceof DynaBean) {
                            ((DynaBean) dest).set(name, value);
                        } else {
                                setSimpleProperty(dest, name, value);
                        }
                    } catch (NoSuchMethodException e) {
                        if (log.isDebugEnabled()) {
                            log.debug("Error writing to '" + name + "' on class '" + dest.getClass() + "'", e);
                        }
                    }
                }
            }
        } else if (orig instanceof Map) {
            Iterator entries = ((Map) orig).entrySet().iterator();
            while (entries.hasNext()) {
                Map.Entry entry = (Map.Entry) entries.next();
                String name = (String)entry.getKey();
                if (isWriteable(dest, name)) {
                    try {
                        if (dest instanceof DynaBean) {
                            ((DynaBean) dest).set(name, entry.getValue());
                        } else {
                            setSimpleProperty(dest, name, entry.getValue());
                        }
                    } catch (NoSuchMethodException e) {
                        if (log.isDebugEnabled()) {
                            log.debug("Error writing to '" + name + "' on class '" + dest.getClass() + "'", e);
                        }
                    }
                }
            }
        } else /* if (orig is a standard JavaBean) */ {
            PropertyDescriptor[] origDescriptors =
                getPropertyDescriptors(orig);
            for (int i = 0; i < origDescriptors.length; i++) {
                String name = origDescriptors[i].getName();
                if (isReadable(orig, name) && isWriteable(dest, name)) {
                    try {
                        Object value = getSimpleProperty(orig, name);
                        if (dest instanceof DynaBean) {
                            ((DynaBean) dest).set(name, value);
                        } else {
                                setSimpleProperty(dest, name, value);
                        }
                    } catch (NoSuchMethodException e) {
                        if (log.isDebugEnabled()) {
                            log.debug("Error writing to '" + name + "' on class '" + dest.getClass() + "'", e);
                        }
                    }
                }
            }
        }

    }


    /**
     * <p>Return the entire set of properties for which the specified bean
     * provides a read method.  This map contains the unconverted property
     * values for all properties for which a read method is provided
     * (i.e. where the <code>getReadMethod()</code> returns non-null).</p>
     *
     * <p><strong>FIXME</strong> - Does not account for mapped properties.</p>
     *
     * @param bean Bean whose properties are to be extracted
     * @return The set of properties for the bean
     *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -