/*
 * Copyright 1998-2004 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.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);
    }
}
