SDSU CS 696 Emerging Technologies: Distributed Objects
Spring Semester, 1998
Bean Introspection & Customization

To Lecture Notes Index
© 1998, All Rights Reserved, SDSU & Roger Whitney
San Diego State University -- This page last updated 05-May-98

Contents of Doc 33, Bean Introspection & Customization

  1. References
  2. Introspection
    1. Design Patterns
      1. Properties
      2. Events
      3. Capital Letters in Name Patterns
    2. Analyzing A Bean
    3. BeanInfo Interface
      1. getIcon
      2. java.beans.FeatureDescriptor
      3. getBeanDescriptor
      4. PropertyDescriptor
      5. getPropertyDescriptors
    4. Property Editors

References


Java in a Nutshell: A Desktop Quick Reference, 2nd Ed. David Flanagan, O'Reilly, 1997, Chapter 10 Java Beans pp. 178-200

JavaBeans(TM) API Specification Version 1.01, July 24, 1997, Graham Hamilton, editor, Sun Microsystems, chapter 8-9, pp. 54-96

Developing Java Beans, Englander, O'Reilly, 1997, chapters 9-10, pp. 191-252



Doc 33, Bean Introspection & Customization Slide # 2

Introspection

Design Patterns


Introspection is the process of a builder tool determining important information about the bean

JavaBeans use a standard naming convention to allow implicit introspection of a bean

Properties


Simple Properties
   public < PropertyType> get< PropertyName>();
   public void set< PropertyName>(< PropertyType> a);

   public Wombat getFoo();
   public void setFoo(Wombat w);

Boolean Properties

Boolean properties also have the following pattern:
   public boolean is< PropertyName>();

   public boolean getFoo();
   public void setFoo(boolean w);
   public boolean isFoo()


Doc 33, Bean Introspection & Customization Slide # 3

Indexed Properties
   public < PropertyElement> get< PropertyName>(int index);
   public void set< PropertyName>(int index, < PropertyElement> b);
   public < PropertyElement>[] get< PropertyName>();
   public void set< PropertyName>( < PropertyElement>[] b);

   public Bah[] getFoo();
   public void setFoo(Bah a[]);
   public Bah getFoo(int a);
   public void setFoo(int a, Bah b);

Bound Properties

Same as regular properties, but needs add/remove listener methods

Events


Multicast Events
   public void add< EventListenerType>(< EventListenerType> a)
   public void remove< EventListenerType>(< EventListenerType> a)

   public void addFredListener(FredListener t);
   public void removeFredListener(FredListener t);

Unicast Events

Throwing a java.util.TooManyListenersException indicates a unicast event
   public void addJackListener(JackListener t)
      throws java.util.TooManyListenersException;
   public void removeJackListener(JackListener t);


Doc 33, Bean Introspection & Customization Slide # 4

Capital Letters in Name Patterns



Using the naming patterns to extract a property or event name from the middle of an existing Java name
normally the first character is converted to lower case
if the first two characters of the name are both upper case then do not change the first letter

"FooBah" becomes "fooBah"
"Z" becomes "z"
"URL" becomes "URL"

Analyzing A Bean


The class java.beans.Introspector analyses a bean using the naming conventions (design patterns) given above

If a bean has a BeanInfo class then the Introspector uses the information in the BeanInfo to override the naming conventions

If a class X is a bean, then its BeanInfo class must be called XBeanInfo


Doc 33, Bean Introspection & Customization Slide # 5
Reasons for using a BeanInfo class

BeanInfo can provide more information about the bean than the naming conventions

If you avoid using the naming conventions in your bean then:
The builder tools can use the BeanInfo class
Applications using your bean do not need the BeanInfo class
Users can not extract the bean from the application and use it in a builder tool
This allows you sell beans to developers without giving it way to users of their applications

BeanInfo Interface


A bean's BeanInfo class must implement the java.beans.BeanInfo interface

If one of the BeanInfo methods return null, then the design pattern introspection will be use

The class java.beans.SimpleBeanInfo implements the BeanInfo interface, with all the methods returning null

Subclass SimpleBeanInfo and just implement the methods you wish to support


Doc 33, Bean Introspection & Customization Slide # 6
java.beans.BeanInfo Methods
getIcon(int)
Returns an image to be used to represent the bean in toolboxes, toolbars, etc.

getBeanDescriptor()
Returns overall information about the bean, such as its displayName,
getMethodDescriptors()
Returns a list of methods supported by the bean with a description of each method
getPropertyDescriptors()
Returns a list of properties supported by the bean with a description of each property

getEventSetDescriptors()
Returns a list of events fired by the bean with a description of each event

getAdditionalBeanInfo()
This method allows a BeanInfo object to return an arbitrary collection of other BeanInfo objects that provide additional information on the current bean
getDefaultEventIndex()
A bean may have a "default" event that is the event that will mostly commonly be used by human's when using the bean
getDefaultPropertyIndex()
A bean may have a "default" property that is the property that will mostly commonly be initially chosen for update by human's who are customizing the bean


Doc 33, Bean Introspection & Customization Slide # 7

getIcon

package beanExamples;
import java.beans.*;

public class SDSUReporterBeanInfo extends SimpleBeanInfo
   {
   public java.awt.Image getIcon( int kind )
      {
      if ((kind == ICON_MONO_16x16 ) || 
         (kind == ICON_COLOR_16x16  ))
         return loadImage( "sample.gif");
      else
         return null;
      }
   }

There are four types of icon supported:
ICON_MONO_16x16
ICON_COLOR_16x16
ICON_MONO_32x32
ICON_COLOR_32x32

These constants are defined in java.beans.BeanInfo

The sizes refer to the pixel size of the images

loadImage is defined in java.beans.SimpleBeanInfo

public Image loadImage(String resourceName)
resourceName - A pathname relative to the directory holding the class file of the current class. For example, "wombat.gif".


Doc 33, Bean Introspection & Customization Slide # 8

java.beans.FeatureDescriptor


Most of the methods in java.beans.BeanInfo return descriptors

java.beans.FeatureDescriptor is the parent class for all bean descriptors

setDisplayName(String)
getDisplayName()
The name displayed in builder tool for this item

setName(String)
getName()
The programmatic name of the property/method/event

setShortDescription(String)
getShortDescription()
You can associate a short descriptive string with a feature

attributeNames()
setValue(String, Object)
getValue(String)
Supports name/value pairs with this feature
setExpert(boolean)
isExpert()
Distinguishes between features for expert users from those for normal users
setHidden(boolean)
isHidden()
Identifies features that are intended only for tool use, and which should not be exposed to humans


Doc 33, Bean Introspection & Customization Slide # 9

getBeanDescriptor

package beanExamples;
import java.beans.*;

public class SDSUReporterBeanInfo extends SimpleBeanInfo
   {
   public java.awt.Image getIcon( int kind )
      {
      if ((kind == ICON_MONO_16x16 ) || 
         (kind == ICON_COLOR_16x16  ))
         return loadImage( "sample.gif");
      else
         return null;
      }
   
   public BeanDescriptor getBeanDescriptor()
      {
      BeanDescriptor myInfo = 
         new BeanDescriptor( SDSUReporter.class );
      myInfo.setDisplayName( "Hot Stuff");
      return myInfo;
      }
   }

BeanDescriptor constructor takes the class of the class we are describing

It can also take the class of a customizer



Doc 33, Bean Introspection & Customization Slide # 10

PropertyDescriptor

Constructors
public PropertyDescriptor(String propertyName, 
      Class beanClass) throws IntrospectionException
public PropertyDescriptor(String propertyName, 
      Class beanClass, String getterName, 
      String setterName) throws IntrospectionException
public PropertyDescriptor(String propertyName, Method getter, 
      Method setter) throws IntrospectionException

propertyName
The programmatic name of the property
getter
The method used for reading the property value. Set null if the property is write-only

setter
The method used for writing the property value. Set null if the property is read-only

beanClass
The Class object for the target bean
Methods
getPropertyType() setConstrained(boolean)
getReadMethod() isConstrained()
getWriteMethod()
setBound(boolean) setPropertyEditorClass(Class)
isBound()getPropertyEditorClass()


Doc 33, Bean Introspection & Customization Slide # 11

getPropertyDescriptors

package beanExamples;
import java.beans.*;

public class SDSUReporterBeanInfo extends SimpleBeanInfo {
   public java.awt.Image getIcon( int kind ) {
      if ((kind == ICON_MONO_16x16 ) || 
         (kind == ICON_COLOR_16x16  ))
         return loadImage( "sample.gif");
      else
         return null;
   }
   
   public BeanDescriptor getBeanDescriptor() {
      BeanDescriptor myInfo = 
         new BeanDescriptor( SDSUReporter.class );
      myInfo.setDisplayName( "Hot Stuff");
      return myInfo;
   }
      
   public PropertyDescriptor[] getPropertyDescriptors() {
      try {
         PropertyDescriptor nameProperty = 
            new PropertyDescriptor( "name", SDSUReporter.class );
         nameProperty.setDisplayName( "Reporter's Name");
         nameProperty.setShortDescription(
            "This is the name of your reporter");       
         
         PropertyDescriptor[] allProperties = { nameProperty };
         return allProperties;
      }
      catch ( IntrospectionException error ) {
         return super.getPropertyDescriptors(); // use default if there is an error
      }
   }
}


Doc 33, Bean Introspection & Customization Slide # 12

Property Editors


You can customize the way the builder tool allows the user to change the values of a property

Implement an Editor class that either implements the java.beans.PropertyEditor interface or extends the java.beans.PropertyEditorSupport class

You have 3 ways to display a value and two ways to edit a value
Displaying the value of a Property

As a String
Use the getAsText() method to convert a property to a string and display it

As an enumerated value
Use the getTags() method to display a dropdown menu of the allowed values

In a graphical display
Use the paintValue() method to display the value using a graphical format
You need to use isPaintable to specify that a graphical format is supported


Doc 33, Bean Introspection & Customization Slide # 13
Editing Techniques

String Editing
User types value into a simple text field

Custom Editing
Using the methods getCustomEditor() and supportsCustomEditor() you can have the BeanBox use a custom editing window that you supply


Doc 33, Bean Introspection & Customization Slide # 14
java.beans.PropertyEditor InterfaceMethods

addPropertyChangeListener(PropertyChangeListener)
removePropertyChangeListener(PropertyChangeListener)

getAsText()
setAsText(String)
Set the property value by parsing a given String.

supportsCustomEditor()
getCustomEditor()
A PropertyEditor may choose to make available a full custom Component that edits its property value.

getJavaInitializationString()
This method is intended for use when generating Java code to set the value of the property.
getTags()
If the property value must be one of a set of known tagged values, then this method should return an array of the tags.

getValue()
setValue(Object)
Set (or change) the object that is to be edited.

isPaintable()
paintValue(Graphics, Rectangle)
Paint a representation of the value into a given area of screen real estate.


Doc 33, Bean Introspection & Customization Slide # 15
Example

package beanExamples;
import java.beans.*;

public class School
   {
   public static final int SDSU = 1;
   public static final int USD = 2;
   public static final int UCSD = 3;
   
   private int aSchool;
   
   public School( int id ){aSchool = id;}
   
   public int getType(){   return aSchool;}

   public String getName()
      {
      switch ( aSchool )
         {
         case 1:
            return "SDSU";
         case 2:
            return "USD";
         case 3:
            return "UCSD";
         default:
            return "Not Known";
         }
         
      }
   }


Doc 33, Bean Introspection & Customization Slide # 16

package beanExamples;
import java.beans.*;

public class SchoolEditor extends PropertyEditorSupport {
   
   public String[] getTags() {
      return new String[] { "SDSU", "USD", "UCSD" };
   }
   
   public void setAsText( String input ) {
      if ( input.equals( "SDSU" ) )
         setValue( new School( School.SDSU ));
      else if ( input.equals( "USD" ) )
         setValue( new School( School.USD ));
      else if  ( input.equals( "UCSD" ) )
         setValue( new School( School.UCSD ));
      else 
         throw new IllegalArgumentException( input );
   }
   
   public String getJavaInitializationString() {
      School value =  (School) getValue();
      int type = value.getType();
      
      switch ( type ) {
         default:
         case 1: return "new School( School.SDSU )";
         case  2: return "new School( School.USD )";
         case 3: return "new School( School.UCSD )";
      }
   }
}



Copyright © 1998 SDSU & Roger Whitney, 5500 Campanile Drive, San Diego, CA 92182-7700 USA.
All rights reserved.

visitors since 05-May-98