[Chapter 10] 10.5 Specifying Bean Information
Author: David Flanagan
Date: Thu Jul 31 15:57:49 1997

#

| Chapter 10 Java Beans |

## 10.5 Specifying Bean Information

The `YesNoDialog` class itself and the `AnswerEvent` and `AnswerListener` classes it relies on are all a required part of our bean. When an application that uses the bean is shipped, it has to include all three of these class files. There are other kinds of classes, however, that are often bundled with a bean that are not intended for use by the application developer. These classes are used by the beanbox tool that manipulates the bean. The bean class itself does not refer to any of these auxiliary beanbox classes so that it is not dependent on them and they do not have to be shipped with the bean in finished products.

The first of these optional, auxiliary classes is a `BeanInfo` class. As explained earlier, a beanbox discovers the properties, events, and methods exported by a bean through "introspection" based on the Java Reflection API. A bean developer who wants to provide additional information about a bean, or who wants to refine the (somewhat rough) information available through introspection, should define a class that implements the `BeanInfo` interface to provide that information. A `BeanInfo` class typically subclasses `SimpleBeanInfo`, which provides a no-op implementation of the `BeanInfo` interface. When you only want to override one or two methods, it is easier to subclass `SimpleBeanInfo` than to implement `BeanInfo` directly. Beanbox tools rely on a naming convention in order to find the `BeanInfo` class for a given bean: a `BeanInfo` class should have the same name as the bean, with the string "BeanInfo" appended. Example 10.5 shows an implementation of the `YesNoDialogBeanInfo` class.

This `BeanInfo` class specifies a number of pieces of information for our bean:

- An icon that can be used to represent the bean.

- A `BeanDescriptor` object, which includes a reference to a `Customizer` class for the bean. We'll see an implementation of this class later in the chapter.

- A list of the supported properties of the bean, along with a short description of each one. Some beanbox tools (but not Sun's beanbox) display these strings to the user in some useful way.

- A method that returns the most commonly customized property of the bean--this is called the "default" property.

- References to `PropertyEditor` classes for two of the properties. We'll see implementations of these property editor classes later in the chapter.

- A list of the methods supported by the bean, again with a short description of each one.

Besides specifying this information, a `BeanInfo` class can also provide information about the events it generates and specify a default event. The various `FeatureDescriptor` objects used to provide information about such things as properties and methods can also include other information not provided by `YesNoDialogBeanInfo`, such as a localized display name that is distinct from the programmatic name.

#### Example 10.5: The YesNoDialogBeanInfo Class

    package oreilly.beans.yesno;
    import java.beans.*;
    import java.lang.reflect.*;
    import java.awt.*;
    /** The BeanInfo class for the YesNoDialog bean. */
    public class YesNoDialogBeanInfo extends SimpleBeanInfo {
      /** Return an icon for the bean.  We should really check the kind argument
       *  to see what size icon the beanbox wants, but since we only have one
       *  icon to offer, we just return it and let the beanbox deal with it. */
      public Image getIcon(int kind) {
        return loadImage("YesNoDialogIcon.gif");
      }
      /** Return a descriptor for the bean itself.  It specifies a customizer
       *  for the bean class.  We could also add a description string here. */
      public BeanDescriptor getBeanDescriptor() {
        return new BeanDescriptor(YesNoDialog.class, YesNoDialogCustomizer.class);
      }
      /** This is a convenience routine for creating PropertyDescriptor objects. */
      public static PropertyDescriptor property(String name, String description)
           throws IntrospectionException
      {
        PropertyDescriptor p = new PropertyDescriptor(name, YesNoDialog.class);
        p.setShortDescription(description);
        return p;
      }
      /** This method returns an array of PropertyDescriptor objects that specify
       *  additional information about the properties supported by the bean.
       *  By explicitly specifying property descriptors, we are able to provide
       *  simple help strings for each property; these would not be available to
       *  the beanbox through simple introspection.  We are also able to register
       *  special property editors for two of the properties.
       */
      public PropertyDescriptor[] getPropertyDescriptors() {
        try {
          PropertyDescriptor[] props = {
            property("title", "The string that appears in the dialog title bar"),
            property("message", "The string that appears in the dialog body"),
            property("yesLabel", "The label for the 'Yes' button, if any"),
            property("noLabel", "The label for the 'No' button, if any"),
            property("cancelLabel", "The label for the 'Cancel' button, if any"),
            property("alignment", "The alignment of the message text"),
            property("font", "The font to use for message and buttons"),
            property("background", "The background color for the dialog"),
            property("foreground", "The text color for message and buttons")
          };
          props[1].setPropertyEditorClass(YesNoDialogMessageEditor.class);
          props[5].setPropertyEditorClass(YesNoDialogAlignmentEditor.class);
          return props;
        }
        catch (IntrospectionException e) {return super.getPropertyDescriptors(); }
      }
      /** The message property is most often customized; make it the default. */
      public int getDefaultPropertyIndex() { return 1; }
      /** This is a convenience method for creating MethodDescriptors.  Note that
       *  it assumes we are talking about methods with no arguments. */
      public static MethodDescriptor method(String name, String description)
           throws NoSuchMethodException, SecurityException {
        Method m = YesNoDialog.class.getMethod(name, new Class[] {});
        MethodDescriptor md = new MethodDescriptor(m);
        md.setShortDescription(description);
        return md;
      }
      /** This method returns an array of method descriptors for the supported
       *  methods of a bean. This allows us to provide useful description strings,
       *  but it also allows us to filter out non-useful methods like wait()
       *  and notify() that the bean inherits and which might otherwise be
       *  displayed by the beanbox.
       */
      public MethodDescriptor[] getMethodDescriptors() {
        try {
          MethodDescriptor[] methods = {
            method("display", "Pop up the dialog; make it visible")
          };
          return methods;
        }
        catch (Exception e) {
          return super.getMethodDescriptors();
        }
      }
    }

Custom Events |  | Defining a Simple Property Editor