/*
 * Copyright (c) 1998, 2004, 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 sun.swing;

import java.beans.*;
import java.lang.reflect.Method;

public class BeanInfoUtils
{
    /* The values of these createPropertyDescriptor() and
     * createBeanDescriptor() keywords are the names of the
     * properties they're used to set.
     */
    public static final String BOUND = "bound";
    public static final String CONSTRAINED = "constrained";
    public static final String PROPERTYEDITORCLASS = "propertyEditorClass";
    public static final String READMETHOD = "readMethod";
    public static final String WRITEMETHOD = "writeMethod";
    public static final String DISPLAYNAME = "displayName";
    public static final String EXPERT = "expert";
    public static final String HIDDEN = "hidden";
    public static final String PREFERRED = "preferred";
    public static final String SHORTDESCRIPTION = "shortDescription";
    public static final String CUSTOMIZERCLASS = "customizerClass";

    static private void initFeatureDescriptor(FeatureDescriptor fd, String key, Object value)
    {
        if (DISPLAYNAME.equals(key)) {
            fd.setDisplayName((String)value);
        }

        if (EXPERT.equals(key)) {
            fd.setExpert(((Boolean)value).booleanValue());
        }

        if (HIDDEN.equals(key)) {
            fd.setHidden(((Boolean)value).booleanValue());
        }

        if (PREFERRED.equals(key)) {
            fd.setPreferred(((Boolean)value).booleanValue());
        }

        else if (SHORTDESCRIPTION.equals(key)) {
            fd.setShortDescription((String)value);
        }

        /* Otherwise assume that we have an arbitrary FeatureDescriptor
         * "attribute".
         */
        else {
            fd.setValue(key, value);
        }
    }

    /**
     * Create a beans PropertyDescriptor given an of keyword/value
     * arguments.  The following sample call shows all of the supported
     * keywords:
     *<pre>
     *      createPropertyDescriptor("contentPane", new Object[] {
     *                     BOUND, Boolean.TRUE,
     *               CONSTRAINED, Boolean.TRUE,
     *       PROPERTYEDITORCLASS, package.MyEditor.class,
     *                READMETHOD, "getContentPane",
     *               WRITEMETHOD, "setContentPane",
     *               DISPLAYNAME, "contentPane",
     *                    EXPERT, Boolean.FALSE,
     *                    HIDDEN, Boolean.FALSE,
     *                 PREFERRED, Boolean.TRUE,
     *          SHORTDESCRIPTION, "A top level window with a window manager border",
     *         "random attribute","random object value"
     *        }
     *     );
     * </pre>
     * The keywords correspond to <code>java.beans.PropertyDescriptor</code> and
     * <code>java.beans.FeatureDescriptor</code> properties, e.g. providing a value
     * for displayName is comparable to <code>FeatureDescriptor.setDisplayName()</code>.
     * Using createPropertyDescriptor instead of the PropertyDescriptor
     * constructor and set methods is preferrable in that it regularizes
     * the code in a <code>java.beans.BeanInfo.getPropertyDescriptors()</code>
     * method implementation.  One can use <code>createPropertyDescriptor</code>
     * to set <code>FeatureDescriptor</code> attributes, as in "random attribute"
     * "random object value".
     * <p>
     * All properties should provide a reasonable value for the
     * <code>SHORTDESCRIPTION</code> keyword and should set <code>BOUND</code>
     * to <code>Boolean.TRUE</code> if neccessary.  The remaining keywords
     * are optional.  There's no need to provide values for keywords like
     * READMETHOD if the correct value can be computed, i.e. if the properties
     * get/is method follows the standard beans pattern.
     * <p>
     * The PREFERRED keyword is not supported by the JDK1.1 java.beans package.
     * It's still worth setting it to true for properties that are most
     * likely to be interested to the average developer, e.g. AbstractButton.title
     * is a preferred property, AbstractButton.focusPainted is not.
     *
     * @see java.beans#BeanInfo
     * @see java.beans#PropertyDescriptor
     * @see java.beans#FeatureDescriptor
     */
    public static PropertyDescriptor createPropertyDescriptor(Class cls, String name, Object[] args)
    {
        PropertyDescriptor pd = null;
        try {
            pd = new PropertyDescriptor(name, cls);
        } catch (IntrospectionException e) {
            // Try creating a read-only property, in case setter isn't defined.
            try {
                pd = createReadOnlyPropertyDescriptor(name, cls);
            } catch (IntrospectionException ie) {
                throwError(ie, "Can't create PropertyDescriptor for " + name + " ");
            }
        }

        for(int i = 0; i < args.length; i += 2) {
            String key = (String)args[i];
            Object value = args[i + 1];

            if (BOUND.equals(key)) {
                pd.setBound(((Boolean)value).booleanValue());
            }

            else if (CONSTRAINED.equals(key)) {
                pd.setConstrained(((Boolean)value).booleanValue());
            }

            else if (PROPERTYEDITORCLASS.equals(key)) {
                pd.setPropertyEditorClass((Class)value);
            }

            else if (READMETHOD.equals(key)) {
                String methodName = (String)value;
                Method method;
                try {
                    method = cls.getMethod(methodName, new Class[0]);
                    pd.setReadMethod(method);
                }
                catch(Exception e) {
                    throwError(e, cls + " no such method as \"" + methodName + "\"");
                }
            }

            else if (WRITEMETHOD.equals(key)) {
                String methodName = (String)value;
                Method method;
                try {
                    Class type = pd.getPropertyType();
                    method = cls.getMethod(methodName, new Class[]{type});
                    pd.setWriteMethod(method);
                }
                catch(Exception e) {
                    throwError(e, cls + " no such method as \"" + methodName + "\"");
                }
            }

            else {
                initFeatureDescriptor(pd, key, value);
            }
        }

        return pd;
    }


    /**
     * Create a BeanDescriptor object given an of keyword/value
     * arguments.  The following sample call shows all of the supported
     * keywords:
     *<pre>
     *      createBeanDescriptor(JWindow..class, new Object[] {
     *           CUSTOMIZERCLASS, package.MyCustomizer.class,
     *               DISPLAYNAME, "JFrame",
     *                    EXPERT, Boolean.FALSE,
     *                    HIDDEN, Boolean.FALSE,
     *                 PREFERRED, Boolean.TRUE,
     *          SHORTDESCRIPTION, "A top level window with a window manager border",
     *         "random attribute","random object value"
     *        }
     *     );
     * </pre>
     * The keywords correspond to <code>java.beans.BeanDescriptor</code> and
     * <code>java.beans.FeatureDescriptor</code> properties, e.g. providing a value
     * for displayName is comparable to <code>FeatureDescriptor.setDisplayName()</code>.
     * Using createBeanDescriptor instead of the BeanDescriptor
     * constructor and set methods is preferrable in that it regularizes
     * the code in a <code>java.beans.BeanInfo.getBeanDescriptor()</code>
     * method implementation.  One can use <code>createBeanDescriptor</code>
     * to set <code>FeatureDescriptor</code> attributes, as in "random attribute"
     * "random object value".
     *
     * @see java.beans#BeanInfo
     * @see java.beans#PropertyDescriptor
     */
    public static BeanDescriptor createBeanDescriptor(Class cls, Object[] args)
    {
        Class customizerClass = null;

        /* For reasons I don't understand, customizerClass is a
         * readOnly property.  So we have to find it and pass it
         * to the constructor here.
         */
        for(int i = 0; i < args.length; i += 2) {
            if (CUSTOMIZERCLASS.equals((String)args[i])) {
                customizerClass = (Class)args[i + 1];
                break;
            }
        }

        BeanDescriptor bd = new BeanDescriptor(cls, customizerClass);

        for(int i = 0; i < args.length; i += 2) {
            String key = (String)args[i];
            Object value = args[i + 1];
            initFeatureDescriptor(bd, key, value);
        }

        return bd;
    }

    static private PropertyDescriptor createReadOnlyPropertyDescriptor(
        String name, Class cls) throws IntrospectionException {

        Method readMethod = null;
        String base = capitalize(name);
        Class[] parameters = new Class[0];

        // Is it a boolean?
        try {
            readMethod = cls.getMethod("is" + base, parameters);
        } catch (Exception ex) {}
        if (readMethod == null) {
            try {
                // Try normal accessor pattern.
                readMethod = cls.getMethod("get" + base, parameters);
            } catch (Exception ex2) {}
        }
        if (readMethod != null) {
            return new PropertyDescriptor(name, readMethod, null);
        }

        try {
            // Try indexed accessor pattern.
            parameters = new Class[1];
            parameters[0] = int.class;
            readMethod = cls.getMethod("get" + base, parameters);
        } catch (NoSuchMethodException nsme) {
            throw new IntrospectionException(
                "cannot find accessor method for " + name + " property.");
        }
        return new IndexedPropertyDescriptor(name, null, null, readMethod, null);
    }

    // Modified methods from java.beans.Introspector
    private static String capitalize(String s) {
        if (s.length() == 0) {
            return s;
        }
        char chars[] = s.toCharArray();
        chars[0] = Character.toUpperCase(chars[0]);
        return new String(chars);
    }

    /**
     * Fatal errors are handled by calling this method.
     */
    public static void throwError(Exception e, String s) {
        throw new Error(e.toString() + " " + s);
    }
}
