/*******************************************************************************
 * Copyright (c) 2001, 2006 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.13 $  $Date: 2006/05/17 20:13:00 $ 
 */

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$
	}
}
