Package org.apache.ojb.broker.metadata.fieldaccess

Source Code of org.apache.ojb.broker.metadata.fieldaccess.PersistentFieldIntrospectorImpl

package org.apache.ojb.broker.metadata.fieldaccess;

/* Copyright 2003-2005 The Apache Software Foundation
*
* Licensed 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.
*/

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.ojb.broker.core.proxy.ProxyHelper;
import org.apache.ojb.broker.metadata.MetadataException;
import org.apache.ojb.broker.util.ClassHelper;
import org.apache.ojb.broker.util.logging.Logger;

/**
* A {@link PersistentField} implementation using
* JavaBeans compliant calls only to access persistent attributes.
* No Reflection is needed. But for each attribute xxx there must be
* public getXxx() and setXxx() methods. In metadata the field name must be
* the bean compliant 'xxx'.
*
* @version $Id: PersistentFieldIntrospectorImpl.java,v 1.11.2.2 2005/12/21 22:26:41 tomdz Exp $
*/
public class PersistentFieldIntrospectorImpl extends PersistentFieldBase
{
    private static final long serialVersionUID = 8805309492150404444L;
    private Class type;
    private transient List propertyGraph;

    public PersistentFieldIntrospectorImpl()
    {
        super();
    }

    public PersistentFieldIntrospectorImpl(Class aClass, String aPropertyName)
    {
        super(aClass, aPropertyName);
    }

    public Class getType()
    {
        if (type == null)
        {
            type = getPropertyDescriptor().getPropertyType();
        }
        return type;
    }

    public void set(Object target, Object value) throws MetadataException
    {
        if(target == null) return;
        List propertyDescriptors = getPropertyGraph();
        int size = propertyDescriptors.size() - 1;
        PropertyDescriptor pd;
        for (int i = 0; i < size; i++)
        {
            Object attribute;
            pd = (PropertyDescriptor) propertyDescriptors.get(i);
            attribute = getValueFrom(pd, target);
            if (attribute != null || value != null)
            {
                if (attribute == null)
                {
                    try
                    {
                        attribute = ClassHelper.newInstance(pd.getPropertyType());
                    }
                    catch (Exception e)
                    {
                        throw new MetadataException("Can't instantiate nested object of type '"
                                + pd.getPropertyType() + "' for field '"
                                + pd.getName() + "'", e);
                    }
                }
                setValueFor(pd, target, attribute);
            }
            else
            {
                return;
            }
            target = attribute;
        }
        pd = (PropertyDescriptor) propertyDescriptors.get(size);
        setValueFor(pd, target, value);
    }

    public Object get(Object target) throws MetadataException
    {
        List propertyDescriptors = getPropertyGraph();
        for (int i = 0; i < propertyDescriptors.size(); i++)
        {
            PropertyDescriptor pd = (PropertyDescriptor) propertyDescriptors.get(i);
            target = getValueFrom(pd, target);
            if (target == null) break;
        }
        return target;
    }

    private Object getValueFrom(PropertyDescriptor pd, Object target)
    {
        if (target == null) return null;
        Method m = pd.getReadMethod();
        if (m != null)
        {
            try
            {
                return m.invoke(ProxyHelper.getRealObject(target), null);
            }
            catch (Throwable e)
            {
                logProblem(pd, target, null, "Can't read value from given object");
                throw new MetadataException("Error invoking method:" + m.getName() + " in object " + target.getClass().getName(), e);
            }
        }
        else
        {
            throw new MetadataException("Can't get ReadMethod for property:" + pd.getName() + " in object " + target.getClass().getName());
        }
    }

    private void setValueFor(PropertyDescriptor pd, Object target, Object value)
    {
        Method m = pd.getWriteMethod();
        Object[] args = {value};
        if (m != null)
        {
            try
            {
                /**
                 * MBAIRD: it is safe to call getParameterTypes()[0] because this is
                 * the "set" method and it needs to take one parameter only.
                 * we need to be able to set values to null. We can only set something to null if
                 * the type is not a primitive (assignable from Object).
                 */
                if ((value != null) || !m.getParameterTypes()[0].isPrimitive())
                {
                    m.invoke(ProxyHelper.getRealObject(target), args);
                }
            }
            catch (Throwable e)
            {
                logProblem(pd, target, value, "Can't set value on given object.");
                throw new MetadataException("Error invoking method:" + m.getName() + " in object:" + target.getClass().getName(), e);
            }
        }
        else
        {
            throw new MetadataException("Can't get WriteMethod for property:" + pd.getName() + " in object:" + target.getClass().getName());
        }
    }

    private List getPropertyGraph()
    {
        if (propertyGraph == null)
        {
            propertyGraph = buildPropertyGraph();
        }
        return propertyGraph;
    }

    private List buildPropertyGraph()
    {
        List result = new ArrayList();
        String[] fields = StringUtils.split(getName(), PATH_TOKEN);
        PropertyDescriptor pd = null;
        for (int i = 0; i < fields.length; i++)
        {
            String fieldName = fields[i];
            if (pd == null)
            {
                pd = findPropertyDescriptor(getDeclaringClass(), fieldName);
            }
            else
            {
                pd = findPropertyDescriptor(pd.getPropertyType(), fieldName);
            }
            result.add(pd);
        }
        return result;
    }

    /**
     * Get the PropertyDescriptor for aClass and aPropertyName
     */
    protected static PropertyDescriptor findPropertyDescriptor(Class aClass, String aPropertyName)
    {
        BeanInfo info;
        PropertyDescriptor[] pd;
        PropertyDescriptor descriptor = null;

        try
        {
            info = Introspector.getBeanInfo(aClass);
            pd = info.getPropertyDescriptors();
            for (int i = 0; i < pd.length; i++)
            {
                if (pd[i].getName().equals(aPropertyName))
                {
                    descriptor = pd[i];
                    break;
                }
            }
            if (descriptor == null)
            {
                /*
         * Daren Drummond:   Throw here so we are consistent
         *           with PersistentFieldDefaultImpl.
         */
                throw new MetadataException("Can't find property " + aPropertyName + " in " + aClass.getName());
            }
            return descriptor;
        }
        catch (IntrospectionException ex)
        {
            /*
       * Daren Drummond:   Throw here so we are consistent
       *           with PersistentFieldDefaultImpl.
       */
            throw new MetadataException("Can't find property " + aPropertyName + " in " + aClass.getName(), ex);
        }
    }

    /**
     * Returns the PropertyDescriptor.
     *
     * @return java.beans.PropertyDescriptor
     */
    protected PropertyDescriptor getPropertyDescriptor()
    {
        return (PropertyDescriptor) getPropertyGraph().get(getPropertyGraph().size() - 1);
    }

    /**
     * This implementation returns always 'false'.
     */
    public boolean makeAccessible()
    {
        return false;
    }

    /**
     * Always returns 'false'.
     *
     * @see PersistentField#usesAccessorsAndMutators
     */
    public boolean usesAccessorsAndMutators()
    {
        return true;
    }

    /**
     * Let's give the user some hints as to what could be wrong.
     */
    protected void logProblem(PropertyDescriptor pd, Object anObject, Object aValue, String msg)
    {
        Logger logger = getLog();
        logger.error("Error in [PersistentFieldPropertyImpl], " + msg);
        logger.error("Declaring class [" + getDeclaringClass().getName() + "]");
        logger.error("Property Name [" + getName() + "]");
        logger.error("Property Type [" + pd.getPropertyType().getName() + "]");

        if (anObject != null)
        {
            logger.error("anObject was class [" + anObject.getClass().getName() + "]");
        }
        else
        {
            logger.error("anObject was null");
        }
        if (aValue != null)
        {
            logger.error("aValue was class [" + aValue.getClass().getName() + "]");
        }
        else
        {
            logger.error("aValue was null");
        }
    }
}
TOP

Related Classes of org.apache.ojb.broker.metadata.fieldaccess.PersistentFieldIntrospectorImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.