/*******************************************************************************
 * Copyright (c) 2001, 2005 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jem.beaninfo.vm;

/*
 *  $RCSfile: BaseBeanInfo.java,v $
 *  $Revision: 1.12 $  $Date: 2006/02/06 17:14:43 $ 
 */

import java.awt.Image;
import java.beans.*;
import java.lang.reflect.*;

import org.eclipse.jem.beaninfo.common.IBaseBeanInfoConstants;


/**
 * A BaseBeanInfo that provides common support for BeanInfos within the JEM environment.
 * 
 * @since 1.1.0
 */
public abstract class BaseBeanInfo extends SimpleBeanInfo implements IBaseBeanInfoConstants {

	// Constants to use to create all descriptors etc.
	protected static java.util.ResourceBundle RESBUNDLE = java.util.ResourceBundle.getBundle("org.eclipse.jem.beaninfo.vm.beaninfo"); //$NON-NLS-1$

	/**
	 * Bound indicator for apply property arguments.
	 * 
	 * @since 1.1.0
	 */
	public static final String BOUND = "bound";//$NON-NLS-1$

	/**
	 * Constrained indicator for apply property arguments.
	 * 
	 * @since 1.1.0
	 */
	public static final String CONSTRAINED = "constrained";//$NON-NLS-1$

	/**
	 * Property editor class indicator for apply property arguments.
	 * 
	 * @since 1.1.0
	 */
	public static final String PROPERTYEDITORCLASS = "propertyEditorClass";//$NON-NLS-1$

	/**
	 * Read Method indicator for apply property arguments.
	 * 
	 * @since 1.1.0
	 */
	public static final String READMETHOD = "readMethod";//$NON-NLS-1$

	/**
	 * Write method indicator for apply property arguments.
	 * 
	 * @since 1.1.0
	 */
	public static final String WRITEMETHOD = "writeMethod";//$NON-NLS-1$

	/**
	 * Displayname indicator for apply property arguments.
	 * 
	 * @since 1.1.0
	 */
	public static final String DISPLAYNAME = "displayName";//$NON-NLS-1$
	
	/**
	 * Expert indicator for apply property arguments.
	 * 
	 * @since 1.1.0
	 */
	public static final String EXPERT = "expert";//$NON-NLS-1$

	/**
	 * Hidden indicator for apply property arguments.
	 * 
	 * @since 1.1.0
	 */
	public static final String HIDDEN = "hidden";//$NON-NLS-1$

	/**
	 * Preferred indicator for apply property arguments.
	 * 
	 * @since 1.1.0
	 */
	public static final String PREFERRED = "preferred";//$NON-NLS-1$

	/**
	 * Short description indicator for apply property arguments.
	 * 
	 * @since 1.1.0
	 */
	public static final String SHORTDESCRIPTION = "shortDescription";//$NON-NLS-1$

	/**
	 * Customizer class indicator for apply property arguments.
	 * 
	 * @since 1.1.0
	 */
	public static final String CUSTOMIZERCLASS = "customizerClass";//$NON-NLS-1$

	/**
	 * In Default eventset indicator for apply property arguments.
	 * 
	 * @since 1.1.0
	 */
	public static final String INDEFAULTEVENTSET = "inDefaultEventSet";//$NON-NLS-1$
	
	/**
	 * This is a Feature Attribute Key. When this key exists, the value is a java.lang.reflect.Field. It means this property
	 * is a field and not a getter/setter. The getter/setter will be ignored and the property type will be the type of the field.
	 * <p>
	 * At this time, do not use field on an indexed property. This is currently an undefined situation.
	 * 
	 * @since 1.1.0
	 */
	public static final String FIELDPROPERTY = "field"; //$NON-NLS-1$

	/**
	 * Obscure indicator for apply property arguments. Obsure is a pre-defined attribute name too. That is where the obscure setting is stored.
	 * <p>
	 * Obsure means most users don't need it. In the future such features won't even be cached so as to reduce the in-memory costs. Currently this
	 * flag is ignored.
	 * 
	 * @since 1.1.0
	 */
	public static final String OBSCURE = "ivjObscure";//$NON-NLS-1$

	/**
	 * Design time indicator for apply property arguments. Design time is a pre-defined attribute name too. That is where the design time setting is
	 * stored.
	 * <p>
	 * Design time means:
	 * <ul>
	 * <li>Not set: Will be a property that can be connected to, and shows on property sheet (if not hidden).
	 * <li><code>true</code>: Special property (it will show on property sheet if not hidden), but it can't be connected to. Usually this is a
	 * property that is fluffed up for the IDE purposes but doesn't have a get/set method. This means it is a property for design time and not for
	 * runtime.
	 * <li><code>false</code>: This property will not show up on property sheet but it can be connected to.
	 * </ul>
	 * 
	 * @since 1.1.0
	 */
	public static final String DESIGNTIMEPROPERTY = "ivjDesignTimeProperty"; //$NON-NLS-1$
	
	/**
	 * EventAdapterClass indicator for apply property arguments. Event adapter class is a pre-defined attribute name too. That is where the event
	 * adapter is stored.
	 * <p>
	 * Adapter class for eventSetDescriptors that provide default no-op implementation of the interface methods. For example
	 * <code>java.awt.event.WindowListener</code> has an adapter of <code>java.awt.event.WindowAdapter</code>. What is stored is actually the
	 * class name, not the class itself.
	 * 
	 * @since 1.1.0
	 */
	public static final String EVENTADAPTERCLASS = "eventAdapterClass"; //$NON-NLS-1$


	public static final boolean JVM_1_3 = System.getProperty("java.version", "").startsWith("1.3"); //$NON-NLS-1$ //$NON-NLS-2$  //$NON-NLS-3$
	
	/**
	 * Empty args list for those descriptors that don't have arguments.
	 * @since 1.1.0
	 */
	public static final Object[] EMPTY_ARGS = new Object[0];

	/**
	 * Capitalize the string. This uppercases only the first character. So if you have property name of "abc" it will become "Abc".
	 * 
	 * @param s
	 * @return string with first letter capitalized.
	 * 
	 * @since 1.1.0
	 */
	public 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);
	}

	/**
	 * Create a BeanDescriptor object given an array of keyword/value arguments. Use the keywords defined in this class, e.g. BOUND, EXPERT, etc.
	 * 
	 * @param cls
	 *            bean for which the bean descriptor is being created.
	 * @param args
	 *            arg pairs, [0] keyword, [1] value, [2] keyword, [3] value, etc. or null if no args
	 * @return new bean descriptor
	 * 
	 * @since 1.1.0
	 */
	public static BeanDescriptor createBeanDescriptor(Class cls, Object[] args) {
		Class customizerClass = null;

		if (args != null) {
			/* Find the specified customizerClass */
			for (int i = 0; i < args.length; i += 2) {
				if (CUSTOMIZERCLASS.equals(args[i])) {
					customizerClass = (Class) args[i + 1];
					break;
				}
			}
		}

		BeanDescriptor bd = new BeanDescriptor(cls, customizerClass);

		if (args != null) {
			for (int i = 0; i < args.length; i += 2) {
				String key = (String) args[i];
				Object value = args[i + 1];
				setFeatureDescriptorValue(bd, key, value);
			}
		}		
		return bd;
	}

	/**
	 * Create a beans EventSetDescriptor given the following:
	 * 
	 * @param cls
	 *            The bean class
	 * @param name
	 *            Name of event set
	 * @param args
	 *            arg pairs, [0] keyword, [1] value, [2] keyword, [3] value, etc. or null if no args.
	 * @param lmds
	 *            array of MethodDescriptors defining the listener methods
	 * @param listenerType
	 *            type of listener
	 * @param addListenerName
	 *            add listener method name
	 * @param removeListenerNameremove
	 *            listener method name
	 * @return new event set descriptor
	 * @since 1.1.0
	 */
	public static EventSetDescriptor createEventSetDescriptor(Class cls, String name, Object[] args, MethodDescriptor[] lmds, Class listenerType,
			String addListenerName, String removeListenerName) {
		EventSetDescriptor esd = null;
		Class[] paramTypes = { listenerType};
		try {
			java.lang.reflect.Method addMethod = null;
			java.lang.reflect.Method removeMethod = null;
			try {
				/* get addListenerMethod with parameter types. */
				addMethod = cls.getMethod(addListenerName, paramTypes);
			} catch (Exception ie) {
				throwError(ie, java.text.MessageFormat.format(RESBUNDLE.getString("Cannot_get_the_meth1_EXC_"), //$NON-NLS-1$
						new Object[] { addListenerName}));
			}
			;
			try {
				/* get removeListenerMethod with parameter types. */
				removeMethod = cls.getMethod(removeListenerName, paramTypes);
			} catch (Exception ie) {
				throwError(ie, java.text.MessageFormat.format(RESBUNDLE.getString("Cannot_get_the_meth1_EXC_"), //$NON-NLS-1$
						new Object[] { removeListenerName}));
			}
			;

			esd = new EventSetDescriptor(name, listenerType, lmds, addMethod, removeMethod);
		} catch (Exception ie) {
			throwError(ie, java.text.MessageFormat.format(RESBUNDLE.getString("Cannot_create_the_E1_EXC_"), //$NON-NLS-1$
					new Object[] { name}));
		}
		;
		if (args != null) {
			// set the event set descriptor properties
			for (int i = 0; i < args.length; i += 2) {
				String key = (String) args[i];
				Object value = args[i + 1];
				if (INDEFAULTEVENTSET.equals(key)) {
					esd.setInDefaultEventSet(((Boolean) value).booleanValue());
				} else
					setFeatureDescriptorValue(esd, key, value);
			}
		}		
		return esd;
	}

	/**
	 * Create a bean's MethodDescriptor.
	 * 
	 * @param cls
	 *            class of the method.
	 * @param name
	 *            name of the method.
	 * @param args
	 *            arg pairs, [0] keyword, [1] value, [2] keyword, [3] value, etc. or null if no args
	 * @param params
	 *            parameter descriptors or <code>null</code> if no parameter descriptors.
	 * @param paramTypes
	 *            parameter types
	 * @return new method descriptor
	 * 
	 * @since 1.1.0
	 */
	public static MethodDescriptor createMethodDescriptor(Class cls, String name, Object[] args, ParameterDescriptor[] params, Class[] paramTypes) {
		MethodDescriptor md = null;
		try {
			java.lang.reflect.Method aMethod = null;
			try {
				/* getMethod with parameter types. */
				aMethod = cls.getMethod(name, paramTypes);
			} catch (Exception ie) {
				throwError(ie, java.text.MessageFormat.format(RESBUNDLE.getString("Cannot_get_the_meth1_EXC_"), //$NON-NLS-1$
						new Object[] { name}));
			}
			;
			if (params != null && params.length > 0)
				md = new MethodDescriptor(aMethod, params);
			else
				md = new MethodDescriptor(aMethod);
		} catch (Exception ie) {
			throwError(ie, java.text.MessageFormat.format(RESBUNDLE.getString("Cannot_create_Method_EXC_"), //$NON-NLS-1$
					new Object[] { name}));
		}
		;
		if (args != null) {
			// set the method properties
			for (int i = 0; i < args.length; i += 2) {
				String key = (String) args[i];
				Object value = args[i + 1];
				setFeatureDescriptorValue(md, key, value);
			}
		}		
		return md;
	}

	private static PropertyDescriptor createOtherPropertyDescriptor(String name, Class cls) throws IntrospectionException {
		Method readMethod = null;
		Method writeMethod = null;
		String base = capitalize(name);
		Class[] parameters = new Class[0];

		// First we try boolean accessor pattern
		try {
			readMethod = cls.getMethod("is" + base, parameters);//$NON-NLS-1$
		} catch (Exception ex1) {
		}
		if (readMethod == null) {
			try {
				// Else we try the get accessor pattern.
				readMethod = cls.getMethod("get" + base, parameters);//$NON-NLS-1$
			} catch (Exception ex2) {
				// Find by matching methods of the class
				readMethod = findMethod(cls, "get" + base, 0);//$NON-NLS-1$
			}
		}

		if (readMethod == null) {
			// For write-only properties, find the write method
			writeMethod = findMethod(cls, "set" + base, 1);//$NON-NLS-1$
		} else {
			// In Sun's code, reflection fails if there are two
			// setters with the same name and the first setter located
			// does not have the same return type of the getter.
			// This fixes that.
			parameters = new Class[1];
			parameters[0] = readMethod.getReturnType();
			try {
				writeMethod = cls.getMethod("set" + base, parameters);//$NON-NLS-1$
			} catch (Exception ex3) {
			}
		}
		// create the property descriptor
		if ((readMethod != null) || (writeMethod != null)) {
			return new PropertyDescriptor(name, readMethod, writeMethod);
		} else {
			throw new IntrospectionException(java.text.MessageFormat.format(RESBUNDLE.getString("Cannot_find_the_acc1_EXC_"), //$NON-NLS-1$
					new Object[] { name}));
		}
	}

	/**
	 * Create a beans parameter descriptor.
	 * 
	 * @param name
	 *            name of parameter
	 * @param args
	 *            arg pairs, [0] keyword, [1] value, [2] keyword, [3] value, etc. or null if no args
	 * @return new parameter descriptor
	 * 
	 * @since 1.1.0
	 */
	public static ParameterDescriptor createParameterDescriptor(String name, Object[] args) {
		ParameterDescriptor pd = null;
		try {
			pd = new ParameterDescriptor();
		} catch (Exception ie) {
			throwError(ie, java.text.MessageFormat.format(RESBUNDLE.getString("Cannot_create_Param1_EXC_"), //$NON-NLS-1$
					new Object[] { name}));
		}
		;
		// set the name
		pd.setName(name);
		if (args != null) {
			// set the method properties
			for (int i = 0; i < args.length; i += 2) {
				String key = (String) args[i];
				Object value = args[i + 1];
				setFeatureDescriptorValue(pd, key, value);
			}
		}		
		return pd;
	}
	
	private static Method GETCLASS; 
	
	static {
		try {
			GETCLASS = Object.class.getMethod("getClass", null); //$NON-NLS-1$
		} catch (SecurityException e) {
		} catch (NoSuchMethodException e) {
		}
	}
	/**
	 * Create a property descriptor describing a field property.
	 * <p>
	 * Note: This is non-standard. The VE knows how to handle this, but any one else using BeanInfo will see this as a property with
	 * no getter or setter.
	 * @param name
	 * @param field
	 * @param args arg pairs, [0] keyword, [1] value, [2] keyword, [3] value, etc. or null if no args
	 * @return
	 * 
	 * @since 1.1.0
	 */
	public static PropertyDescriptor createFieldPropertyDescriptor(String name, Field field, Object[] args) {
		try {
			PropertyDescriptor pd = new PropertyDescriptor(name, null, null);
			pd.setValue(FIELDPROPERTY, field);	// Set the field property so we know it is a field.
			applyFieldArguments(pd, args);
			// Need to set in a phony read method because Introspector will throw it away otherwise. We just use Object.getClass for this.
			// We will ignore the property type for fields. If used outside of VE then it will look like a class property.
			pd.setReadMethod(GETCLASS);
			return pd;
		} catch (IntrospectionException e) {
			throwError(e, java.text.MessageFormat.format(RESBUNDLE.getString("Cannot_create_the_P1_EXC_"), //$NON-NLS-1$
					new Object[] { name}));
			return null;
		}
	}

	/**
	 * Create a bean's property descriptor.
	 * 
	 * @param cls
	 *            class of who owns the property (usually the bean). It is used to look up get/set methods for the property.
	 * @param name
	 *            name of the property. It will use get{Name} and set{Name} to find get/set methods.
	 * @param args
	 *            arg pairs, [0] keyword, [1] value, [2] keyword, [3] value, etc.
	 * @return new property descriptor
	 * 
	 * @since 1.1.0
	 */
	public static PropertyDescriptor createPropertyDescriptor(Class cls, String name, Object[] args) {
		PropertyDescriptor pd = null;
		try {
			// Create assuming that the getter/setter follows reflection patterns
			pd = new PropertyDescriptor(name, cls);
		} catch (IntrospectionException e) {
			// Try creating a property descriptor for read-only, write-only
			// or if Sun's reflection fails
			try {
				pd = createOtherPropertyDescriptor(name, cls);
			} catch (IntrospectionException ie) {
				throwError(ie, java.text.MessageFormat.format(RESBUNDLE.getString("Cannot_create_the_P1_EXC_"), //$NON-NLS-1$
						new Object[] { name}));
			}
		}

		applyPropertyArguments(pd, args, cls);

		return pd;
	}


	/**
	 * Create a new PropertyDescriptor based upon the PD sent in. It will clone the sent in one, and apply the args to override any specific setting.
	 * Class cls is used for finding read/write methods, if any.
	 * 
	 * This is used when wanting to override only a few specific settings from a property descriptor from the super class.
	 * 
	 * @param fromPDS
	 *            The PropertyDescriptor array to find the entry to clone. It will be changed in place in the array.
	 * @param name
	 *            The name of the property to find and clone and override.
	 * @param cls
	 *            The class to use to find read/write methods in args. If no read/write methods specified, then this may be null.
	 * @param args
	 *            The arguments to override from fromPD. arg pairs, [0] keyword, [1] value, [2] keyword, [3] value, etc. or null if none to override
	 */
	public void replacePropertyDescriptor(PropertyDescriptor[] pds, String name, Class cls, Object[] args) {
		PropertyDescriptor pd = null;
		int iPD = findPropertyDescriptor(pds, name);
		if (iPD == -1)
			return;
		PropertyDescriptor fromPD = pds[iPD];
		try {

			pd = pds[iPD] = new PropertyDescriptor(fromPD.getName(), null, null);
		} catch (IntrospectionException e) {
			throwError(e, java.text.MessageFormat.format(RESBUNDLE.getString("Cannot_create_the_P1_EXC_"), //$NON-NLS-1$
					new Object[] { fromPD.getName()}));
		}

		// Now copy over the contents of fromPD.
		clonePropertySettings(fromPD, pd);

		// Now apply the overrides
		applyPropertyArguments(pd, args, cls);
		return;
	}

	private void clonePropertySettings(PropertyDescriptor fromPD, PropertyDescriptor pd) {
		try {
			pd.setReadMethod(fromPD.getReadMethod());
			pd.setWriteMethod(fromPD.getWriteMethod());
			pd.setPropertyEditorClass(fromPD.getPropertyEditorClass());
			pd.setBound(fromPD.isBound());
			pd.setConstrained(fromPD.isConstrained());
			cloneFeatureSettings(fromPD, pd);
		} catch (IntrospectionException e) {
			throwError(e, java.text.MessageFormat.format(RESBUNDLE.getString("Cannot_create_the_P1_EXC_"), //$NON-NLS-1$
					new Object[] { fromPD.getName()}));
		}
	}

	private void cloneFeatureSettings(FeatureDescriptor fromFD, FeatureDescriptor fd) {
		fd.setExpert(fromFD.isExpert());
		fd.setHidden(fromFD.isHidden());
		fd.setPreferred(fromFD.isPreferred());
		fd.setShortDescription(fromFD.getShortDescription());
		fd.setDisplayName(fromFD.getDisplayName());

		java.util.Enumeration keys = fromFD.attributeNames();
		while (keys.hasMoreElements()) {
			String key = (String) keys.nextElement();
			Object value = fromFD.getValue(key);
			fd.setValue(key, value);
		}
	}

	/*
	 * The common property arguments between field and standard properties.
	 */
	private static boolean applyCommonPropertyArguments(PropertyDescriptor pd, String key, Object value) {
		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 (FIELDPROPERTY.equals(key))
			return true;	// This should not be applied except through createFieldProperty.
		else
			return false;
		return true;
	
	}
	
	private static void applyPropertyArguments(PropertyDescriptor pd, Object[] args, Class cls) {
		if (args != null) {
			for (int i = 0; i < args.length; i += 2) {
				String key = (String) args[i];
				Object value = args[i + 1];
				
				if (!applyCommonPropertyArguments(pd, key, value)) {
					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, java.text.MessageFormat.format(RESBUNDLE.getString("{0}_no_read_method_EXC_"), //$NON-NLS-1$
									new Object[] { cls, methodName}));
						}
					} else if (WRITEMETHOD.equals(key)) {
						String methodName = (String) value;
						try {
							if (methodName == null) {
								pd.setWriteMethod(null);
							} else {
								Method method;
								Class type = pd.getPropertyType();
								method = cls.getMethod(methodName, new Class[] { type});
								pd.setWriteMethod(method);
							}
						} catch (Exception e) {
							throwError(e, java.text.MessageFormat.format(RESBUNDLE.getString("{0}_no_write_method_EXC_"), //$NON-NLS-1$
									new Object[] { cls, methodName}));
						}
					} else {
						// arbitrary value
						setFeatureDescriptorValue(pd, key, value);
					}
				}
			}
		}
	}

	private static void applyFieldArguments(PropertyDescriptor pd, Object[] args) {
		if (args != null) {
			for (int i = 0; i < args.length; i += 2) {
				String key = (String) args[i];
				Object value = args[i + 1];

				if (!applyCommonPropertyArguments(pd, key, value)) {
					if (READMETHOD.equals(key)) {
						// ignored for field.
					} else if (WRITEMETHOD.equals(key)) {
						// ignored for field.
					} else {
						// arbitrary value
						setFeatureDescriptorValue(pd, key, value);
					}
				}
			}
		}		
	}

	/**
	 * Find the method by comparing (name & parameter size) against the methods in the class. This is an expensive call and should be used only if
	 * getMethod with specific parameter types can't find method.
	 * 
	 * @return java.lang.reflect.Method
	 * @param aClass
	 *            java.lang.Class
	 * @param methodName
	 *            java.lang.String
	 * @param parameterCount
	 *            int
	 */
	public static java.lang.reflect.Method findMethod(java.lang.Class aClass, java.lang.String methodName, int parameterCount) {
		try {
			/*
			 * Since this method attempts to find a method by getting all methods from the class, this method should only be called if getMethod
			 * cannot find the method.
			 */
			java.lang.reflect.Method methods[] = aClass.getMethods();
			for (int index = 0; index < methods.length; index++) {
				java.lang.reflect.Method method = methods[index];
				if ((method.getParameterTypes().length == parameterCount) && (method.getName().equals(methodName))) { return method; }
				;
			}
			;
		} catch (java.lang.Throwable exception) {
			return null;
		}
		;
		return null;
	}

	/**
	 * Find a property descriptor of a given name in the list.
	 * 
	 * @param pds
	 *            The array of property descriptors to search, may be null.
	 * @param name
	 *            The name to search for.
	 * @return The found property descriptor index, or -1 if not found.
	 */
	public static int findPropertyDescriptor(PropertyDescriptor[] pds, String name) {
		for (int i = 0; i < pds.length; i++) {
			if (name.equals(pds[i].getName()))
				return i;
		}
		return -1;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.beans.BeanInfo#getDefaultEventIndex()
	 */
	public int getDefaultEventIndex() {
		return -1;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.beans.BeanInfo#getDefaultPropertyIndex()
	 */
	public int getDefaultPropertyIndex() {
		return -1;
	}
	
	
	/* (non-Javadoc)
	 * @see java.beans.SimpleBeanInfo#getBeanDescriptor()
	 */
	public BeanDescriptor getBeanDescriptor() {
		// Default is to create an empty one.
		return createBeanDescriptor(getBeanClass(), EMPTY_ARGS);
	}

	/**
	 * Implementation for BeanInfo. This implementation will return the BeanInfo of the superclass.
	 * 
	 * @see BeanInfo#getAdditionalBeanInfo()
	 * @since 1.1.0
	 */
	public BeanInfo[] getAdditionalBeanInfo() {
		try {
			BeanInfo[] result = new BeanInfo[] { Introspector.getBeanInfo(getBeanClass().getSuperclass())};
			PropertyDescriptor[] oPDs = result[0].getPropertyDescriptors();
			PropertyDescriptor[] nPDs = overridePropertyDescriptors(oPDs);
			if (oPDs != nPDs)
				result[0] = new OverridePDBeanInfo(result[0], nPDs);
			return result;
		} catch (IntrospectionException e) {
			return new BeanInfo[0];
		}
	}

	private static class OverridePDBeanInfo implements BeanInfo {

		private BeanInfo originalBeanInfo;

		private PropertyDescriptor[] overridePDs;

		public OverridePDBeanInfo(BeanInfo bi, PropertyDescriptor[] pds) {
			originalBeanInfo = bi;
			overridePDs = pds;
		}

		public BeanInfo[] getAdditionalBeanInfo() {
			return originalBeanInfo.getAdditionalBeanInfo();
		}

		public BeanDescriptor getBeanDescriptor() {
			return originalBeanInfo.getBeanDescriptor();
		}

		public int getDefaultEventIndex() {
			return originalBeanInfo.getDefaultEventIndex();
		}

		public int getDefaultPropertyIndex() {
			return originalBeanInfo.getDefaultPropertyIndex();
		}

		public EventSetDescriptor[] getEventSetDescriptors() {
			return originalBeanInfo.getEventSetDescriptors();
		}

		public Image getIcon(int iconKind) {
			return originalBeanInfo.getIcon(iconKind);
		}

		public MethodDescriptor[] getMethodDescriptors() {
			return originalBeanInfo.getMethodDescriptors();
		}

		public PropertyDescriptor[] getPropertyDescriptors() {
			return overridePDs;
		}
	}

	/**
	 * Allow overrides to parent beaninfo. Subclasses should override this method if they wish to override and change any inherited properties. This
	 * allows removal of inherited properties or changes of specific properties (such as change from hidden to not hidden).
	 * 
	 * Note: If there any changes, this must return a DIFFERENT array. If it returns the same array, then the changes will not be accepted. If just
	 * overriding, should use pds.clone() to get the new array and then change the specific entries.
	 * 
	 * @param pds
	 * @return The new changed array or the same array if no changes.
	 * @since 1.1.0
	 */
	protected PropertyDescriptor[] overridePropertyDescriptors(PropertyDescriptor[] pds) {
		return pds;
	}

	/**
	 * Get the bean class this beaninfo is for. Used by subclasses to quickly get the bean class without having to code it over and over.
	 * 
	 * @return bean class for this beaninfo.
	 * 
	 * @since 1.1.0
	 */
	public abstract Class getBeanClass();

	/**
	 * Called whenever the bean information class throws an exception. By default it prints a message and then a stacktrace to sys err.
	 * 
	 * @param exception
	 *            java.lang.Throwable
	 * @since 1.1.0
	 */
	public void handleException(Throwable exception) {
		System.err.println(RESBUNDLE.getString("UNCAUGHT_EXC_")); //$NON-NLS-1$
		exception.printStackTrace();
	}

	private static void setFeatureDescriptorValue(FeatureDescriptor fd, String key, Object value) {
		if (DISPLAYNAME.equals(key)) {
			fd.setDisplayName((String) value);
		} else if (EXPERT.equals(key)) {
			fd.setExpert(((Boolean) value).booleanValue());
		} else if (HIDDEN.equals(key)) {
			fd.setHidden(((Boolean) value).booleanValue());
		} else if (PREFERRED.equals(key)) {
			fd.setPreferred(((Boolean) value).booleanValue());
			if (JVM_1_3) {
				// Bug in 1.3 doesn't preserve the preferred flag, so we will put it into the attributes too.
				fd.setValue(PREFERRED, value);
			}
		} else if (SHORTDESCRIPTION.equals(key)) {
			fd.setShortDescription((String) value);
		}
		// Otherwise assume an arbitrary-named value
		// Assume that the FeatureDescriptor private hashTable\
		// contains only arbitrary-named attributes
		else {
			fd.setValue(key, value);
		}
	}

	/**
	 * Fatal errors are handled by calling this method. By default it throws an Error exception.
	 * 
	 * @param e
	 *            exception exception message placed into the new Error thrown.
	 * @param s
	 *            message added to exception message. <code>null</code> if nothing to add.
	 * 
	 * @throws Error
	 *             turns exception into an Error.
	 * @since 1.1.0
	 */
	protected static void throwError(Exception e, String s) {
		throw new Error(e.toString() + " " + s);//$NON-NLS-1$
	}
}
