jdk/make/data/swingbeaninfo/sun/swing/BeanInfoUtils.java
changeset 36959 d839463825a2
parent 36853 9001df2d68e9
parent 36958 8a320111d9fe
child 36960 d7731fdfe7c3
equal deleted inserted replaced
36853:9001df2d68e9 36959:d839463825a2
     1 /*
       
     2  * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 package sun.swing;
       
    27 
       
    28 import java.beans.*;
       
    29 import java.lang.reflect.Method;
       
    30 
       
    31 public class BeanInfoUtils
       
    32 {
       
    33     /* The values of these createPropertyDescriptor() and
       
    34      * createBeanDescriptor() keywords are the names of the
       
    35      * properties they're used to set.
       
    36      */
       
    37     public static final String BOUND = "bound";
       
    38     public static final String CONSTRAINED = "constrained";
       
    39     public static final String PROPERTYEDITORCLASS = "propertyEditorClass";
       
    40     public static final String READMETHOD = "readMethod";
       
    41     public static final String WRITEMETHOD = "writeMethod";
       
    42     public static final String DISPLAYNAME = "displayName";
       
    43     public static final String EXPERT = "expert";
       
    44     public static final String HIDDEN = "hidden";
       
    45     public static final String PREFERRED = "preferred";
       
    46     public static final String SHORTDESCRIPTION = "shortDescription";
       
    47     public static final String CUSTOMIZERCLASS = "customizerClass";
       
    48 
       
    49     static private void initFeatureDescriptor(FeatureDescriptor fd, String key, Object value)
       
    50     {
       
    51         if (DISPLAYNAME.equals(key)) {
       
    52             fd.setDisplayName((String)value);
       
    53         }
       
    54 
       
    55         if (EXPERT.equals(key)) {
       
    56             fd.setExpert(((Boolean)value).booleanValue());
       
    57         }
       
    58 
       
    59         if (HIDDEN.equals(key)) {
       
    60             fd.setHidden(((Boolean)value).booleanValue());
       
    61         }
       
    62 
       
    63         if (PREFERRED.equals(key)) {
       
    64             fd.setPreferred(((Boolean)value).booleanValue());
       
    65         }
       
    66 
       
    67         else if (SHORTDESCRIPTION.equals(key)) {
       
    68             fd.setShortDescription((String)value);
       
    69         }
       
    70 
       
    71         /* Otherwise assume that we have an arbitrary FeatureDescriptor
       
    72          * "attribute".
       
    73          */
       
    74         else {
       
    75             fd.setValue(key, value);
       
    76         }
       
    77     }
       
    78 
       
    79     /**
       
    80      * Create a beans PropertyDescriptor given an of keyword/value
       
    81      * arguments.  The following sample call shows all of the supported
       
    82      * keywords:
       
    83      *<pre>
       
    84      *      createPropertyDescriptor("contentPane", new Object[] {
       
    85      *                     BOUND, Boolean.TRUE,
       
    86      *               CONSTRAINED, Boolean.TRUE,
       
    87      *       PROPERTYEDITORCLASS, package.MyEditor.class,
       
    88      *                READMETHOD, "getContentPane",
       
    89      *               WRITEMETHOD, "setContentPane",
       
    90      *               DISPLAYNAME, "contentPane",
       
    91      *                    EXPERT, Boolean.FALSE,
       
    92      *                    HIDDEN, Boolean.FALSE,
       
    93      *                 PREFERRED, Boolean.TRUE,
       
    94      *          SHORTDESCRIPTION, "A top level window with a window manager border",
       
    95      *         "random attribute","random object value"
       
    96      *        }
       
    97      *     );
       
    98      * </pre>
       
    99      * The keywords correspond to <code>java.beans.PropertyDescriptor</code> and
       
   100      * <code>java.beans.FeatureDescriptor</code> properties, e.g. providing a value
       
   101      * for displayName is comparable to <code>FeatureDescriptor.setDisplayName()</code>.
       
   102      * Using createPropertyDescriptor instead of the PropertyDescriptor
       
   103      * constructor and set methods is preferrable in that it regularizes
       
   104      * the code in a <code>java.beans.BeanInfo.getPropertyDescriptors()</code>
       
   105      * method implementation.  One can use <code>createPropertyDescriptor</code>
       
   106      * to set <code>FeatureDescriptor</code> attributes, as in "random attribute"
       
   107      * "random object value".
       
   108      * <p>
       
   109      * All properties should provide a reasonable value for the
       
   110      * <code>SHORTDESCRIPTION</code> keyword and should set <code>BOUND</code>
       
   111      * to <code>Boolean.TRUE</code> if neccessary.  The remaining keywords
       
   112      * are optional.  There's no need to provide values for keywords like
       
   113      * READMETHOD if the correct value can be computed, i.e. if the properties
       
   114      * get/is method follows the standard beans pattern.
       
   115      * <p>
       
   116      * The PREFERRED keyword is not supported by the JDK1.1 java.beans package.
       
   117      * It's still worth setting it to true for properties that are most
       
   118      * likely to be interested to the average developer, e.g. AbstractButton.title
       
   119      * is a preferred property, AbstractButton.focusPainted is not.
       
   120      *
       
   121      * @see java.beans#BeanInfo
       
   122      * @see java.beans#PropertyDescriptor
       
   123      * @see java.beans#FeatureDescriptor
       
   124      */
       
   125     public static PropertyDescriptor createPropertyDescriptor(Class<?> cls, String name, Object[] args)
       
   126     {
       
   127         PropertyDescriptor pd = null;
       
   128         try {
       
   129             pd = new PropertyDescriptor(name, cls);
       
   130         } catch (IntrospectionException e) {
       
   131             // Try creating a read-only property, in case setter isn't defined.
       
   132             try {
       
   133                 pd = createReadOnlyPropertyDescriptor(name, cls);
       
   134             } catch (IntrospectionException ie) {
       
   135                 throwError(ie, "Can't create PropertyDescriptor for " + name + " ");
       
   136             }
       
   137         }
       
   138 
       
   139         for(int i = 0; i < args.length; i += 2) {
       
   140             String key = (String)args[i];
       
   141             Object value = args[i + 1];
       
   142 
       
   143             if (BOUND.equals(key)) {
       
   144                 pd.setBound(((Boolean)value).booleanValue());
       
   145             }
       
   146 
       
   147             else if (CONSTRAINED.equals(key)) {
       
   148                 pd.setConstrained(((Boolean)value).booleanValue());
       
   149             }
       
   150 
       
   151             else if (PROPERTYEDITORCLASS.equals(key)) {
       
   152                 pd.setPropertyEditorClass((Class)value);
       
   153             }
       
   154 
       
   155             else if (READMETHOD.equals(key)) {
       
   156                 String methodName = (String)value;
       
   157                 Method method;
       
   158                 try {
       
   159                     method = cls.getMethod(methodName, new Class<?>[0]);
       
   160                     pd.setReadMethod(method);
       
   161                 }
       
   162                 catch(Exception e) {
       
   163                     throwError(e, cls + " no such method as \"" + methodName + "\"");
       
   164                 }
       
   165             }
       
   166 
       
   167             else if (WRITEMETHOD.equals(key)) {
       
   168                 String methodName = (String)value;
       
   169                 Method method;
       
   170                 try {
       
   171                     Class<?> type = pd.getPropertyType();
       
   172                     method = cls.getMethod(methodName, new Class<?>[]{type});
       
   173                     pd.setWriteMethod(method);
       
   174                 }
       
   175                 catch(Exception e) {
       
   176                     throwError(e, cls + " no such method as \"" + methodName + "\"");
       
   177                 }
       
   178             }
       
   179 
       
   180             else {
       
   181                 initFeatureDescriptor(pd, key, value);
       
   182             }
       
   183         }
       
   184 
       
   185         return pd;
       
   186     }
       
   187 
       
   188 
       
   189     /**
       
   190      * Create a BeanDescriptor object given an of keyword/value
       
   191      * arguments.  The following sample call shows all of the supported
       
   192      * keywords:
       
   193      *<pre>
       
   194      *      createBeanDescriptor(JWindow..class, new Object[] {
       
   195      *           CUSTOMIZERCLASS, package.MyCustomizer.class,
       
   196      *               DISPLAYNAME, "JFrame",
       
   197      *                    EXPERT, Boolean.FALSE,
       
   198      *                    HIDDEN, Boolean.FALSE,
       
   199      *                 PREFERRED, Boolean.TRUE,
       
   200      *          SHORTDESCRIPTION, "A top level window with a window manager border",
       
   201      *         "random attribute","random object value"
       
   202      *        }
       
   203      *     );
       
   204      * </pre>
       
   205      * The keywords correspond to <code>java.beans.BeanDescriptor</code> and
       
   206      * <code>java.beans.FeatureDescriptor</code> properties, e.g. providing a value
       
   207      * for displayName is comparable to <code>FeatureDescriptor.setDisplayName()</code>.
       
   208      * Using createBeanDescriptor instead of the BeanDescriptor
       
   209      * constructor and set methods is preferrable in that it regularizes
       
   210      * the code in a <code>java.beans.BeanInfo.getBeanDescriptor()</code>
       
   211      * method implementation.  One can use <code>createBeanDescriptor</code>
       
   212      * to set <code>FeatureDescriptor</code> attributes, as in "random attribute"
       
   213      * "random object value".
       
   214      *
       
   215      * @see java.beans#BeanInfo
       
   216      * @see java.beans#PropertyDescriptor
       
   217      */
       
   218     public static BeanDescriptor createBeanDescriptor(Class<?> cls, Object[] args)
       
   219     {
       
   220         Class<?> customizerClass = null;
       
   221 
       
   222         /* For reasons I don't understand, customizerClass is a
       
   223          * readOnly property.  So we have to find it and pass it
       
   224          * to the constructor here.
       
   225          */
       
   226         for(int i = 0; i < args.length; i += 2) {
       
   227             if (CUSTOMIZERCLASS.equals((String)args[i])) {
       
   228                 customizerClass = (Class)args[i + 1];
       
   229                 break;
       
   230             }
       
   231         }
       
   232 
       
   233         BeanDescriptor bd = new BeanDescriptor(cls, customizerClass);
       
   234 
       
   235         for(int i = 0; i < args.length; i += 2) {
       
   236             String key = (String)args[i];
       
   237             Object value = args[i + 1];
       
   238             initFeatureDescriptor(bd, key, value);
       
   239         }
       
   240 
       
   241         return bd;
       
   242     }
       
   243 
       
   244     static private PropertyDescriptor createReadOnlyPropertyDescriptor(
       
   245         String name, Class<?> cls) throws IntrospectionException {
       
   246 
       
   247         Method readMethod = null;
       
   248         String base = capitalize(name);
       
   249         Class<?>[] parameters = new Class<?>[0];
       
   250 
       
   251         // Is it a boolean?
       
   252         try {
       
   253             readMethod = cls.getMethod("is" + base, parameters);
       
   254         } catch (Exception ex) {}
       
   255         if (readMethod == null) {
       
   256             try {
       
   257                 // Try normal accessor pattern.
       
   258                 readMethod = cls.getMethod("get" + base, parameters);
       
   259             } catch (Exception ex2) {}
       
   260         }
       
   261         if (readMethod != null) {
       
   262             return new PropertyDescriptor(name, readMethod, null);
       
   263         }
       
   264 
       
   265         try {
       
   266             // Try indexed accessor pattern.
       
   267             parameters = new Class<?>[1];
       
   268             parameters[0] = int.class;
       
   269             readMethod = cls.getMethod("get" + base, parameters);
       
   270         } catch (NoSuchMethodException nsme) {
       
   271             throw new IntrospectionException(
       
   272                 "cannot find accessor method for " + name + " property.");
       
   273         }
       
   274         return new IndexedPropertyDescriptor(name, null, null, readMethod, null);
       
   275     }
       
   276 
       
   277     // Modified methods from java.beans.Introspector
       
   278     private static String capitalize(String s) {
       
   279         if (s.length() == 0) {
       
   280             return s;
       
   281         }
       
   282         char chars[] = s.toCharArray();
       
   283         chars[0] = Character.toUpperCase(chars[0]);
       
   284         return new String(chars);
       
   285     }
       
   286 
       
   287     /**
       
   288      * Fatal errors are handled by calling this method.
       
   289      */
       
   290     public static void throwError(Exception e, String s) {
       
   291         throw new Error(e.toString() + " " + s);
       
   292     }
       
   293 }