/*
 * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package com.sun.beans.decoder;

import com.sun.beans.finder.MethodFinder;

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;

/**
 * This class is intended to handle &lt;property&gt; element.
 * This element simplifies access to the properties.
 * If the {@code index} attribute is specified
 * this element uses additional {@code int} parameter.
 * If the {@code name} attribute is not specified
 * this element uses method "get" as getter
 * and method "set" as setter.
 * This element defines getter if it contains no argument.
 * It returns the value of the property in this case.
 * For example:<pre>
 * &lt;property name="object" index="10"/&gt;</pre>
 * is shortcut to<pre>
 * &lt;method name="getObject"&gt;
 *     &lt;int&gt;10&lt;/int&gt;
 * &lt;/method&gt;</pre>
 * which is equivalent to {@code getObject(10)} in Java code.
 * This element defines setter if it contains one argument.
 * It does not return the value of the property in this case.
 * For example:<pre>
 * &lt;property&gt;&lt;int&gt;0&lt;/int&gt;&lt;/property&gt;</pre>
 * is shortcut to<pre>
 * &lt;method name="set"&gt;
 *     &lt;int&gt;0&lt;/int&gt;
 * &lt;/method&gt;</pre>
 * which is equivalent to {@code set(0)} in Java code.
 * <p>The following atributes are supported:
 * <dl>
 * <dt>name
 * <dd>the property name
 * <dt>index
 * <dd>the property index
 * <dt>id
 * <dd>the identifier of the variable that is intended to store the result
 * </dl>
 *
 * @since 1.7
 *
 * @author Sergey A. Malenkov
 */
final class PropertyElementHandler extends AccessorElementHandler {
    static final String GETTER = "get"; // NON-NLS: the getter prefix
    static final String SETTER = "set"; // NON-NLS: the setter prefix

    private Integer index;

    /**
     * Parses attributes of the element.
     * The following atributes are supported:
     * <dl>
     * <dt>name
     * <dd>the property name
     * <dt>index
     * <dd>the property index
     * <dt>id
     * <dd>the identifier of the variable that is intended to store the result
     * </dl>
     *
     * @param name   the attribute name
     * @param value  the attribute value
     */
    @Override
    public void addAttribute(String name, String value) {
        if (name.equals("index")) { // NON-NLS: the attribute name
            this.index = Integer.valueOf(value);
        } else {
            super.addAttribute(name, value);
        }
    }

    /**
     * Tests whether the value of this element can be used
     * as an argument of the element that contained in this one.
     *
     * @return {@code true} if the value of this element should be used
     *         as an argument of the element that contained in this one,
     *         {@code false} otherwise
     */
    @Override
    protected boolean isArgument() {
        return false; // non-static accessor cannot be used an argument
    }

    /**
     * Returns the value of the property with specified {@code name}.
     *
     * @param name  the name of the property
     * @return the value of the specified property
     */
    @Override
    protected Object getValue(String name) {
        try {
            return getPropertyValue(getContextBean(), name, this.index);
        }
        catch (Exception exception) {
            getOwner().handleException(exception);
        }
        return null;
    }

    /**
     * Sets the new value for the property with specified {@code name}.
     *
     * @param name   the name of the property
     * @param value  the new value for the specified property
     */
    @Override
    protected void setValue(String name, Object value) {
        try {
            setPropertyValue(getContextBean(), name, this.index, value);
        }
        catch (Exception exception) {
            getOwner().handleException(exception);
        }
    }

    /**
     * Performs the search of the getter for the property
     * with specified {@code name} in specified class
     * and returns value of the property.
     *
     * @param bean   the context bean that contains property
     * @param name   the name of the property
     * @param index  the index of the indexed property
     * @return the value of the property
     * @throws IllegalAccessException    if the property is not accesible
     * @throws IntrospectionException    if the bean introspection is failed
     * @throws InvocationTargetException if the getter cannot be invoked
     * @throws NoSuchMethodException     if the getter is not found
     */
    private static Object getPropertyValue(Object bean, String name, Integer index) throws IllegalAccessException, IntrospectionException, InvocationTargetException, NoSuchMethodException {
        Class<?> type = bean.getClass();
        if (index == null) {
            return findGetter(type, name).invoke(bean);
        } else if (type.isArray() && (name == null)) {
            return Array.get(bean, index);
        } else {
            return findGetter(type, name, int.class).invoke(bean, index);
        }
    }

    /**
     * Performs the search of the setter for the property
     * with specified {@code name} in specified class
     * and updates value of the property.
     *
     * @param bean   the context bean that contains property
     * @param name   the name of the property
     * @param index  the index of the indexed property
     * @param value  the new value for the property
     * @throws IllegalAccessException    if the property is not accesible
     * @throws IntrospectionException    if the bean introspection is failed
     * @throws InvocationTargetException if the setter cannot be invoked
     * @throws NoSuchMethodException     if the setter is not found
     */
    private static void setPropertyValue(Object bean, String name, Integer index, Object value) throws IllegalAccessException, IntrospectionException, InvocationTargetException, NoSuchMethodException {
        Class<?> type = bean.getClass();
        Class<?> param = (value != null)
                ? value.getClass()
                : null;

        if (index == null) {
            findSetter(type, name, param).invoke(bean, value);
        } else if (type.isArray() && (name == null)) {
            Array.set(bean, index, value);
        } else {
            findSetter(type, name, int.class, param).invoke(bean, index, value);
        }
    }

    /**
     * Performs the search of the getter for the property
     * with specified {@code name} in specified class.
     *
     * @param type  the class that contains method
     * @param name  the name of the property
     * @param args  the method arguments
     * @return method object that represents found getter
     * @throws IntrospectionException if the bean introspection is failed
     * @throws NoSuchMethodException  if method is not found
     */
    private static Method findGetter(Class<?> type, String name, Class<?>...args) throws IntrospectionException, NoSuchMethodException {
        if (name == null) {
            return MethodFinder.findInstanceMethod(type, GETTER, args);
        }
        PropertyDescriptor pd = getProperty(type, name);
        if (args.length == 0) {
            Method method = pd.getReadMethod();
            if (method != null) {
                return method;
            }
        } else if (pd instanceof IndexedPropertyDescriptor) {
            IndexedPropertyDescriptor ipd = (IndexedPropertyDescriptor) pd;
            Method method = ipd.getIndexedReadMethod();
            if (method != null) {
                return method;
            }
        }
        throw new IntrospectionException("Could not find getter for the " + name + " property");
    }

    /**
     * Performs the search of the setter for the property
     * with specified {@code name} in specified class.
     *
     * @param type  the class that contains method
     * @param name  the name of the property
     * @param args  the method arguments
     * @return method object that represents found setter
     * @throws IntrospectionException if the bean introspection is failed
     * @throws NoSuchMethodException  if method is not found
     */
    private static Method findSetter(Class<?> type, String name, Class<?>...args) throws IntrospectionException, NoSuchMethodException {
        if (name == null) {
            return MethodFinder.findInstanceMethod(type, SETTER, args);
        }
        PropertyDescriptor pd = getProperty(type, name);
        if (args.length == 1) {
            Method method = pd.getWriteMethod();
            if (method != null) {
                return method;
            }
        } else if (pd instanceof IndexedPropertyDescriptor) {
            IndexedPropertyDescriptor ipd = (IndexedPropertyDescriptor) pd;
            Method method = ipd.getIndexedWriteMethod();
            if (method != null) {
                return method;
            }
        }
        throw new IntrospectionException("Could not find setter for the " + name + " property");
    }

    /**
     * Performs the search of the descriptor for the property
     * with specified {@code name} in specified class.
     *
     * @param type  the class to introspect
     * @param name  the property name
     * @return descriptor for the named property
     * @throws IntrospectionException if property descriptor is not found
     */
    private static PropertyDescriptor getProperty(Class<?> type, String name) throws IntrospectionException {
        for (PropertyDescriptor pd : Introspector.getBeanInfo(type).getPropertyDescriptors()) {
            if (name.equals(pd.getName())) {
                return pd;
            }
        }
        throw new IntrospectionException("Could not find the " + name + " property descriptor");
    }
}
