/*
* $Id: BeanInfoSupport.java,v 1.2 2006/09/25 08:52:36 acaproni Exp $
*
* $Date: 2006/09/25 08:52:36 $
* $Revision: 1.2 $
* $Author: acaproni $
*
* Copyright CERN, All Rights Reserved.
*/
package cern.gp.beans;
import java.beans.BeanDescriptor;
import java.beans.BeanInfo;
import java.beans.EventSetDescriptor;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.MethodDescriptor;
import java.beans.PropertyChangeListener;
import java.beans.PropertyDescriptor;
import java.beans.SimpleBeanInfo;
/**
* Utility class that provides default implementation and caching for all aspect of
* the BeanInfo.
* <p>
* Should be subclassed in order to overwrite the protected methods.
* </p>
*
* @version $Revision: 1.2 $ $Date: 2006/09/25 08:52:36 $
* @author Lionel Mestre
*/
public class BeanInfoSupport extends SimpleBeanInfo {
/** Empty array of property set that you can return in <code>getPropertyDescriptorsLazy</code>
* in order not to have any property and to prevent the Introspector to introspect the
* properties from the bean */
protected static final PropertyDescriptor[] EMPTY_PROPERTY_SET = new PropertyDescriptor[0];
/** Empty array of method descriptors that you can return in <code>getMethodDescriptorsLazy</code>
* in order not to have any method descriptor and to prevent the Introspector to introspect the
* methods from the bean */
protected static final MethodDescriptor[] EMPTY_METHOD_SET = new MethodDescriptor[0];
/** Empty array of event set descriptor that you can return in <code>getEventSetDescriptorsLazy</code>
* in order not to have any event set and to prevent the Introspector to introspect the
* event set from the bean */
protected static final EventSetDescriptor[] EMPTY_EVENT_SET = new EventSetDescriptor[0];
private static final BeanInfo[] EMPTY_BEAN_INFO_SET = new BeanInfo[0];
/** cached value if the icon */
private java.awt.Image iconColor16;
/** cached value if the icon */
private java.awt.Image iconColor32;
/** cached value if the icon */
private java.awt.Image iconMono16;
/** cached value if the icon */
private java.awt.Image iconMono32;
/** cached value if the bean descriptor */
private BeanDescriptor beanDescriptor;
/** cached value if the property descriptors */
private PropertyDescriptor[] propertyDescriptors;
/** cached value if the event set descriptors */
private EventSetDescriptor[] eventSetDescriptors;
/** cached value if the method descriptors */
private MethodDescriptor[] methodDescriptors;
/** cached additional beaninfos */
private BeanInfo[] additionalBeanInfos;
//
// -- CONSTRUCTORS -----------------------------------------------
//
public BeanInfoSupport() {
setActionsFromAdditionalBeanInfo();
}
//
// -- PROTECTED METHODS -----------------------------------------------
//
/**
* Returns the bean descriptor for this bean info.
* @return the bean descriptor for this bean info.
*/
protected BeanDescriptor getBeanDescriptorLazy() {
return null;
}
/**
* Returns the property descriptors for this bean info. Default
* implementation returns null which means that the Introspector
* will perform the introspection to get the PropertyDescriptors
* This method is guarantee to be called once
* @return the property descriptors for this bean info.
*/
protected PropertyDescriptor[] getPropertyDescriptorsLazy() throws IntrospectionException {
return null;
}
/**
* Returns the event set descriptors for this bean info. Default
* implementation returns null which means that the Introspector
* will perform the introspection to get the EventSetDescriptors
* This method is guarantee to be called once
* @return the event set descriptors for this bean info.
*/
protected EventSetDescriptor[] getEventSetDescriptorsLazy() throws IntrospectionException {
return null;
}
/**
* Returns the method descriptors for this bean info. Default
* implementation returns null which means that the Introspector
* will perform the introspection to get the MethodDescriptors.
* This method is guarantee to be called once
* @return the method descriptors for this bean info.
*/
protected MethodDescriptor[] getMethodDescriptorsLazy() throws IntrospectionException {
return null;
}
/**
* Returns the name of the icon M16. Default
* implementation returns null.
* @return the name of the icon M16 or null if no icon.
*/
protected String getIconNameM16() { return null; }
/**
* Returns the name of the icon M32. Default
* implementation returns null.
* @return the name of the icon M32 or null if no icon.
*/
protected String getIconNameM32() { return null; }
/**
* Returns the name of the icon C16. Default
* implementation returns null.
* @return the name of the icon C16 or null if no icon.
*/
protected String getIconNameC16() { return null; }
/**
* Returns the name of the icon C32. Default
* implementation returns null.
* @return the name of the icon C32 or null if no icon.
*/
protected String getIconNameC32() { return null; }
/**
* Returns the index of the default property. Default
* implementation returns -1.
* @return the index of the default property.
*/
protected int getDefaultPropertyIndexLazy() { return -1; }
/**
* Returns the index of the event. Default
* implementation returns -1.
* @return the index of the default event.
*/
protected int getDefaultEventIndexLazy() { return -1; }
/**
* Returns the superclass of the class this bean info is for. This
* is used in order to look for additional BeanInfo. Default
* implementation returns null which means that there is no additional
* BeanInfo
* @return the superclass of the class this bean info is for or null.
*/
protected Class getSuperclass() { return null; }
/**
* Returns a new <code>EventSetDescriptor</code> for PropertyChangeEvent.
* Call this method inside the method <code>getEventSetDescriptorsLazy</code>
* in order to include PropertyChangeEvent in the array of <code>EventSetDescriptor</code>
* you return. You do that if the bean class has the methods <code>addPropertyChangeListener</code>
* and <code>removePropertyChangeListener</code>.
* @param <code>beanClass</code> the class of the bean this BeanInfo is for
* @return A EventSetDescriptor for the PropertyChange events.
* @exception IntrospectionException if the EventSetDescriptor cannot be built.
*/
protected EventSetDescriptor createPropertyChangeEventSet(Class beanClass) throws IntrospectionException {
return new EventSetDescriptor(beanClass, "PropertyChangeEvent", PropertyChangeListener.class, "propertyChange");
}
//
// -- PUBLIC STATIC METHODS -----------------------------------------------
//
//
// -- PUBLIC METHODS -----------------------------------------------
//
public final BeanInfo[] getAdditionalBeanInfo() {
if (additionalBeanInfos == null) {
Class superclass = getSuperclass();
if (superclass == null) {
additionalBeanInfos = EMPTY_BEAN_INFO_SET;
} else {
try {
additionalBeanInfos = new BeanInfo[] { Introspector.getBeanInfo(superclass) };
} catch (IntrospectionException ex) {
additionalBeanInfos = EMPTY_BEAN_INFO_SET;
}
}
}
return additionalBeanInfos;
}
/**
* Gets the bean's <code>BeanDescriptor</code>s.
*
* @return BeanDescriptor describing the editable
* properties of this bean. May return null if the
* information should be obtained by automatic analysis.
*/
public final BeanDescriptor getBeanDescriptor() {
if (beanDescriptor == null) {
beanDescriptor = getBeanDescriptorLazy();
}
return beanDescriptor;
}
/**
* Gets the bean's <code>PropertyDescriptor</code>s.
*
* @return An array of PropertyDescriptors describing the editable
* properties supported by this bean. May return null if the
* information should be obtained by automatic analysis.
* <p>
* If a property is indexed, then its entry in the result array will
* belong to the IndexedPropertyDescriptor subclass of PropertyDescriptor.
* A client of getPropertyDescriptors can use "instanceof" to check
* if a given PropertyDescriptor is an IndexedPropertyDescriptor.
*/
public final PropertyDescriptor[] getPropertyDescriptors() {
if (propertyDescriptors == null) {
try {
propertyDescriptors = getPropertyDescriptorsLazy();
} catch (IntrospectionException e) {
propertyDescriptors = EMPTY_PROPERTY_SET;
}
}
return propertyDescriptors;
}
/**
* Gets the bean's <code>EventSetDescriptor</code>s.
*
* @return An array of EventSetDescriptors describing the kinds of
* events fired by this bean. May return null if the information
* should be obtained by automatic analysis.
*/
public final EventSetDescriptor[] getEventSetDescriptors() {
if (eventSetDescriptors == null) {
try {
eventSetDescriptors = getEventSetDescriptorsLazy();
} catch (IntrospectionException e) {
eventSetDescriptors = EMPTY_EVENT_SET;
}
}
return eventSetDescriptors;
}
/**
* Gets the bean's <code>MethodDescriptor</code>s.
*
* @return An array of MethodDescriptors describing the methods
* implemented by this bean. May return null if the information
* should be obtained by automatic analysis.
*/
public final MethodDescriptor[] getMethodDescriptors() {
if (methodDescriptors == null) {
try {
methodDescriptors = getMethodDescriptorsLazy();
} catch (IntrospectionException e) {
methodDescriptors = EMPTY_METHOD_SET;
}
}
return methodDescriptors;
}
/**
* 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.
* @return Index of default property in the PropertyDescriptor array
* returned by getPropertyDescriptors.
* <P> Returns -1 if there is no default property.
*/
public final int getDefaultPropertyIndex() {
return getDefaultPropertyIndexLazy();
}
/**
* A bean may have a "default" event that is the event that will
* mostly commonly be used by human's when using the bean.
* @return Index of default event in the EventSetDescriptor array
* returned by getEventSetDescriptors.
* <P> Returns -1 if there is no default event.
*/
public final int getDefaultEventIndex() {
return getDefaultEventIndexLazy();
}
/**
* This method returns an image object that can be used to
* represent the bean in toolboxes, toolbars, etc. Icon images
* will typically be GIFs, but may in future include other formats.
* <p>
* Beans aren't required to provide icons and may return null from
* this method.
* <p>
* There are four possible flavors of icons (16x16 color,
* 32x32 color, 16x16 mono, 32x32 mono). If a bean choses to only
* support a single icon we recommend supporting 16x16 color.
* <p>
* We recommend that icons have a "transparent" background
* so they can be rendered onto an existing background.
*
* @param iconKind The kind of icon requested. This should be
* one of the constant values ICON_COLOR_16x16, ICON_COLOR_32x32,
* ICON_MONO_16x16, or ICON_MONO_32x32.
* @return An image object representing the requested icon. May
* return null if no suitable icon is available.
*/
public final java.awt.Image getIcon(int iconKind) {
switch (iconKind) {
case ICON_COLOR_16x16 :
if (iconColor16 == null) {
if (getIconNameC16() == null) return null;
iconColor16 = loadImage(getIconNameC16());
return iconColor16;
}
return iconColor16;
case ICON_COLOR_32x32 :
if (iconColor32 == null) {
if (getIconNameC32() == null) return null;
iconColor32 = loadImage(getIconNameC32());
return iconColor32;
}
return iconColor32;
case ICON_MONO_16x16 :
if (iconMono16 == null) {
if (getIconNameM16() == null) return null;
iconMono16 = loadImage(getIconNameM16());
return iconMono16;
}
return iconMono16;
case ICON_MONO_32x32 :
if (iconMono32 == null) {
if (getIconNameM32() == null) return null;
iconMono32 = loadImage(getIconNameM32());
return iconMono32;
}
return iconMono32;
default :
return null;
}
}
//
// -- PRIVATE METHODS -----------------------------------------------
//
/**
* Sets the qname of available actions for this BeanInfo by getting
* the ones of all additional BeanInfos.
*/
private void setActionsFromAdditionalBeanInfo() {
// A BeanInfo may reference additional BeanInfos that may
// defines action. Problem is that once the BeanInfo is reconstructed by the
// Intropector it will loose track of the additional BeanInfos. This is why we have
// to copy locally here the actions defined for additional BeanInfos.
BeanInfo[] infos = getAdditionalBeanInfo();
if (infos == null || infos.length == 0) return;
for (int i = 0; i < infos.length; i++) {
String[] actions = BeanTagger.getActions(infos[i]);
if (actions != null) BeanTagger.addActions(this, actions);
String defaultAction = BeanTagger.getDefaultAction(infos[i]);
if (defaultAction != null) BeanTagger.setDefaultAction(this, defaultAction);
}
}
}