/*******************************************************************************
 * 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.internal.beaninfo.vm;

/*


 */

import java.beans.*;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.lang.reflect.*;
import java.util.*;

import org.eclipse.jem.beaninfo.common.IBaseBeanInfoConstants;
import org.eclipse.jem.beaninfo.vm.BaseBeanInfo;
import org.eclipse.jem.internal.beaninfo.common.*;
import org.eclipse.jem.internal.proxy.common.*;

/**
 * This class is the beaninfo class that is created when beaninfo modeling introspects a bean. Its purpose is to gather together and analyze the
 * beaninfo. For example, it checks with the supertype beaninfo to see if all of the supertype's descriptors are included in this list. If they are,
 * then it knows that it does a straight inheritance of the supertype's descriptors, and those descriptors can be removed from the list. This makes it
 * easier on the model side so that there isn't a great proliferation of descriptors all describing the same properties. In that case they can be
 * merged from the supertype model. If some are not found, then that means this beaninfo is trying to hide some of them, and in that case this is the
 * definitive list and inheritance shouldn't be used on the model side. However, for those features which are essentially the inherited feature (i.e.
 * the BeanInfo simply filtered out some inherited but not all), they will be returnable (by name). The IDE side will take these that are "inherited"
 * and will return the actual structured feature from the inherited class.
 * 
 * The test for seeing if the super feature is included in the beaninfo is first to see if the the feature is in the beaninfo by name, if it is then
 * it is marked as included. Then a check is made on equality, if they are equal, then the feature is removed from the beaninfo list, but the merge
 * flag is still left on, and removed inherited feature is added to the list of inherited features. If all inherited features are found, this list is
 * cleared and flag is set which simply says merge all inherited. This allows merging to occur but it also allows overrides to occur.
 * 
 * Note: Test for identity is different between JDK 1.5 and above and below. 1.5 and above, we can use actual equals() because the same descriptor is
 * returned from inherited features. In 1.3, clones were always returned and equals() would answer false, so we need to create a special equality
 * descriptor which turns the equals() into one that can test clones for semantic equality. See Java Bug ID#4996673 The problem was supposed to be
 * fixed in 1.4 but it was not fixed. Originally a new clone was created each time a beaninfo was requested. That is no longer done in 1.4, but the
 * processing to create the original beaninfo does a clone accidently under the covers. Looking at 1.5 it looks this was fixed, but it hasn't been
 * tested here yet.
 */

public abstract class ModelingBeanInfo implements ICallback {

	private static boolean PRE15;
	static {
		String version = System.getProperty("java.version", ""); //$NON-NLS-1$ //$NON-NLS-2$
		PRE15 = version.startsWith("1."); //$NON-NLS-1$
		if (PRE15) {
			// Continue to check, get the revision.
			int revision = 0;
			if (version.length() > 2) {
				int revEnd = version.indexOf('.', 2);
				revision = version.length() > 2 ? Integer.parseInt(revEnd != -1 ? version.substring(2, revEnd) : version.substring(2)) : 0;
				PRE15 = revision < 5;
			}
		}
	}

	static class FeatureEqualitySet extends HashSet {

		/**
		 * Comment for <code>serialVersionUID</code>
		 * 
		 * @since 1.1.0
		 */
		private static final long serialVersionUID = -3744776740604328324L;
		private FeatureDescriptorEquality workingKey;

		public FeatureEqualitySet(List features) {
			super(features.size());
			// Get first feature to fiqure out type of working key. This will not be reentrant.
			workingKey = FeatureDescriptorEquality.createEquality((FeatureDescriptor) features.get(0));
			this.addAll(features);
		}

		/**
		 * @see java.util.Collection#add(Object)
		 */
		public boolean add(Object o) {
			return super.add(FeatureDescriptorEquality.createEquality((FeatureDescriptor) o));
		}

		/**
		 * @see java.util.Collection#contains(Object)
		 */
		public boolean contains(Object o) {
			workingKey.setFeature((FeatureDescriptor) o);
			return super.contains(workingKey);
		}

	}

	// The following fields indicate if the super info should be merged
	// in on the model side. no merge means there were no inherited methods at all. So the
	// beaninfo presented is definitive. If merge, then get...Descriptors will return just
	// the ones for this level, and getSuper...Descriptors will return the inherited ones.
	// Though in this case, if the returned super list is null, then that means use ALL of
	// the inherited ones.
	// The super list returns simply the names, don't need to have the full descriptors in that case.
	protected boolean fMergeInheritedEvents = false, fMergeInheritedMethods = false, fMergeInheritedProperties = false;

	protected final BeanInfo fTargetBeanInfo; // The beaninfo being modeled.

	// Local descriptors
	protected EventSetDescriptor[] fEventSets;

	protected MethodDescriptor[] fMethods;

	protected PropertyDescriptor[] fProperties;

	// Not inherited descriptor names, will be null if no merge or if merge all. This is list of names to NOT merge. It is usually shorter than the list to merge from super.

	// Methods are special. You can have duplicates, so name is not sufficient.
	// So for methods,
	// will use an array of Strings where:
	//   For each one the full signature
	//   will be in the list, e.g. "name:methodName(argtype,..." where argtype is the fullyqualified
	//   classname (using "." notation for inner classes), and using format "java.lang.String[]" for
	//   arrays.
	//
	// This is because even if there are no duplicates, it will take less time/space to simply create the entries
	// then it would to create a set to see if there are duplicates and then create the final array.
	protected String[] fNotInheritedEventSets;

	protected String[] fNotInheritedMethods;

	protected String[] fNotInheritedProperties;
	
	protected int doFlags;

	/**
	 * Method used to do introspection and create the appropriate ModelingBeanInfo
	 * 
	 * This will always introspect.
	 */
	public static ModelingBeanInfo introspect(Class introspectClass, int doFlags) throws IntrospectionException {
		return introspect(introspectClass, true, doFlags);
	}

	/**
	 * Method used to do introspection and create the appropriate ModelingBeanInfo
	 * 
	 * introspectIfNoBeanInfo: If this is true, then if no explicit beaninfo was found for this class, then introspection will be done anyway. The
	 * Introspector will use reflection for local methods/events/properties of this class and then add in the results of the superclass introspection.
	 * If this parameter is false, then if the explicit beaninfo is not found, then no introspection will be done and null will be returned.
	 */
	public static ModelingBeanInfo introspect(Class introspectClass, boolean introspectIfNoBeanInfo, int doFlags) throws IntrospectionException {
		if (!Beans.isDesignTime())
			Beans.setDesignTime(true);	// Since this a jem beaninfo specific vm, we should also be considered design time.
		if (!introspectIfNoBeanInfo) {
			// Need to check if the beaninfo is explicitly supplied.
			// If not, then we return null.
			// The checks will be the same that Introspector will use.

			boolean found = false;
			// 1. Is there a BeanInfo class in the same package
			if (!classExists(introspectClass.getName() + "BeanInfo", introspectClass)) { //$NON-NLS-1$
				// 2. Is this class a BeanInfo class for itself.
				if (!(BeanInfo.class).isAssignableFrom(introspectClass)) {
					// 3. Can this class be found in the Beaninfo searchpath.
					String[] searchPath = Introspector.getBeanInfoSearchPath();
					int startClassname = introspectClass.getName().lastIndexOf(".") + 1; //$NON-NLS-1$
					String biName = "." + introspectClass.getName().substring(startClassname) + "BeanInfo"; //$NON-NLS-1$ //$NON-NLS-2$
					for (int i = 0; i < searchPath.length; i++) {
						if (classExists(searchPath[i] + biName, introspectClass)) {
							found = true;
							break;
						}
					}
				} else
					found = true;
			} else
				found = true;

			if (!found)
				return null;
		}

		BeanInfo bInfo = Introspector.getBeanInfo(introspectClass);
		Class superClass = introspectClass.getSuperclass();

		if (superClass == null)
			return PRE15 ? (ModelingBeanInfo) new ModelingBeanInfoPre15(bInfo, doFlags) : new ModelingBeanInfo15(bInfo, doFlags);
		else
			return PRE15 ? (ModelingBeanInfo) new ModelingBeanInfoPre15(bInfo, Introspector.getBeanInfo(superClass), doFlags) : new ModelingBeanInfo15(bInfo,
					Introspector.getBeanInfo(superClass), doFlags);
	}

	/**
	 * See if this class exists, first in the class loader of the sent class, then in the system loader, then the bootstrap loader, and finally the
	 * current thread context class loader.
	 */
	protected static boolean classExists(String className, Class fromClass) {
		if (fromClass.getClassLoader() != null)
			try {
				fromClass.getClassLoader().loadClass(className);
				return true;
			} catch (ClassNotFoundException e) {
			}
		if (ClassLoader.getSystemClassLoader() != null)
			try {
				ClassLoader.getSystemClassLoader().loadClass(className);
				return true;
			} catch (ClassNotFoundException e) {
			}
		try {
			Class.forName(className);
			return true;
		} catch (ClassNotFoundException e) {
		}

		try {
			// Use the classloader from the current Thread.
			ClassLoader cl = Thread.currentThread().getContextClassLoader();
			cl.loadClass(className);
			return true;
		} catch (ClassNotFoundException e) {
		}

		return false;

	}

	/**
	 * Used only for Object since that is the only bean that doesn't have a superclass. Superclass beaninfo required for all other classes. If this is
	 * constructed then this means no merge and the list is definitive.
	 */
	protected ModelingBeanInfo(BeanInfo beanInfo, int doFlags) {
		fTargetBeanInfo = beanInfo;
		this.doFlags = doFlags;
	}

	protected ModelingBeanInfo(BeanInfo beanInfo, BeanInfo superBeanInfo, int doFlags) {
		this(beanInfo, doFlags);

		// Now go through the beaninfo to determine the merge state.
		// The default is no merge.

		if ((doFlags & IBeanInfoIntrospectionConstants.DO_EVENTS) != 0) {
			List full = addAll(beanInfo.getEventSetDescriptors());
			List inherited = addAll(superBeanInfo.getEventSetDescriptors());

			fMergeInheritedEvents = stripList(full, inherited);
			if (fMergeInheritedEvents) {
				if (!full.isEmpty())
					fEventSets = (EventSetDescriptor[]) full.toArray(new EventSetDescriptor[full.size()]);
				if (!inherited.isEmpty())
					createEventArray(inherited); // This is actually a list of those NOT inherited.
			}
		}

		if ((doFlags & IBeanInfoIntrospectionConstants.DO_METHODS) != 0) {
			List full = addAll(beanInfo.getMethodDescriptors());
			List inherited = addAll(superBeanInfo.getMethodDescriptors());

			fMergeInheritedMethods = stripList(full, inherited);
			if (fMergeInheritedMethods) {
				if (!full.isEmpty())
					fMethods = (MethodDescriptor[]) full.toArray(new MethodDescriptor[full.size()]);
				if (!inherited.isEmpty())
					createMethodEntries(inherited); // This is actually a list of those NOT inherited.
			}
		}

		if ((doFlags & IBeanInfoIntrospectionConstants.DO_PROPERTIES) != 0) {
			List full = addAll(beanInfo.getPropertyDescriptors());
			List inherited = addAll(superBeanInfo.getPropertyDescriptors());

			fMergeInheritedProperties = stripList(full, inherited);
			if (fMergeInheritedProperties) {
				if (!full.isEmpty())
					fProperties = (PropertyDescriptor[]) full.toArray(new PropertyDescriptor[full.size()]);
				if (!inherited.isEmpty())
					createPropertyArray(inherited); // This is actually a list of those NOT inherited.
			}
		}
	}

	protected void createEventArray(List features) {
		fNotInheritedEventSets = createDescriptorNames(features);
	}

	protected void createMethodEntries(List features) {
		int s = features.size();
		fNotInheritedMethods = new String[s];
		for (int i = 0; i < s; i++) {
			fNotInheritedMethods[i] = longName((MethodDescriptor) features.get(i));
		}
	}

	protected String longName(MethodDescriptor md) {
		String n = md.getName();
		StringBuffer sb = new StringBuffer(n.length() + 20);
		sb.append(n);
		sb.append(':');
		Method m = md.getMethod();
		sb.append(m.getName());
		sb.append('(');
		Class[] parms = m.getParameterTypes();
		for (int j = 0; j < parms.length; j++) {
			if (j > 0)
				sb.append(',');
			if (!parms[j].isArray())
				sb.append(parms[j].getName().replace('$', '.'));
			else {
				Class finalType = parms[j].getComponentType();
				int insrt = sb.length();
				while (finalType.isArray()) {
					sb.append("[]"); //$NON-NLS-1$
					finalType = finalType.getComponentType();
				}
				sb.insert(insrt, finalType.getName().replace('$', '.'));
			}
		}
		return sb.toString();
	}

	protected void createPropertyArray(List features) {
		fNotInheritedProperties = createDescriptorNames(features);
	}

	protected String[] createDescriptorNames(List features) {
		String[] result = new String[features.size()];
		for (int i = 0; i < result.length; i++) {
			result[i] = ((FeatureDescriptor) features.get(i)).getName();
		}
		return result;
	}

	protected List addAll(Object[] set) {
		if (set != null) {
			ArrayList l = new ArrayList(set.length);
			for (int i = 0; i < set.length; i++) {
				l.add(set[i]);
			}
			return l;
		} else
			return Collections.EMPTY_LIST;
	}

	/**
	 * If this returns true, then all of the super class's events should be merged in. If it returns false, then the events returned are it, there are
	 * no others.
	 */
	public boolean isMergeInheritedEvents() {
		return fMergeInheritedEvents;
	}

	/**
	 * If this returns true, then all of the super class's methods should be merged in. If it returns false, then the methods returned are it, there
	 * are no others.
	 */
	public boolean isMergeInheritedMethods() {
		return fMergeInheritedMethods;
	}

	/**
	 * If this returns true, then all of the super class's properties should be merged in. If it returns false, then the properties returned are it,
	 * there are no others.
	 */
	public boolean isMergeInheritedProperties() {
		return fMergeInheritedProperties;
	}

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

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

	public EventSetDescriptor[] getEventSetDescriptors() {
		return fMergeInheritedEvents ? fEventSets : fTargetBeanInfo.getEventSetDescriptors();
	}

	public java.awt.Image getIcon(int iconKind) {
		return fTargetBeanInfo.getIcon(iconKind);
	}

	public MethodDescriptor[] getMethodDescriptors() {
		return fMergeInheritedMethods ? fMethods : fTargetBeanInfo.getMethodDescriptors();
	}

	public PropertyDescriptor[] getPropertyDescriptors() {
		return fMergeInheritedProperties ? fProperties : fTargetBeanInfo.getPropertyDescriptors();
	}

	public String[] getNotInheritedEventSetDescriptors() {
		return fNotInheritedEventSets;
	}

	public String[] getNotInheritedMethodDescriptors() {
		return fNotInheritedMethods;
	}

	public String[] getNotInheritedPropertyDescriptors() {
		return fNotInheritedProperties;
	}

	protected String computeKey(FeatureDescriptor feature) {
		return feature instanceof MethodDescriptor ? longName((MethodDescriptor) feature) : feature.getName();
	}

	/*
	 * Strip the list down using the Equality objects.
	 */
	protected boolean stripList(List fullList, List inheritedList) {
		// The process is to create a boolean list mirroring the inheritedList.
		// This boolean list indicates if the corresponding (by index)
		// entry from the inheritedList is to be retained in the final computed
		// list.
		//
		// A Hashmap is created where the key is the computedKey from the inheritedList
		// and the value is the index into the inheritedList. This is so that we can quickly determine if the
		// entry is matching.
		//
		// Then the fullList will be stepped through and see if there is
		// an entry in the Hashmap for it. If there is an entry, then
		// the entry is checked to see if it is semantically equal.
		// If it is, then the boolean list entry is marked so that
		// the inheritedList entry will be retained, the fullList entry removed and the counter
		// of the number of entries in the inheritedList copy is incremented.
		// If they aren't semantically equal, then we know that this is
		// an override. In that case, the fullList entry is kept, the inheritedList
		// entry is not retained, but we don't prevent merge later.
		//
		// If the fullList entry is not found in the HashMap, then we know it is not
		// from the inheritedList, so it will be retained in the fullList.
		//
		// If we get all of the way through, then we know that what is left
		// in fullList is just this level.
		//
		// When we return we know that
		//   a) fullList has only the features that are found at the local level
		//   b) inheritedList if not empty contains the ones from super that SHOULD NOT be inherited.
		//      If it is empty, then if this method returns true, then ALL should be inherited,
		//      or if this method returns false, then it doesn't matter because we aren't merging any.
		//
		// All of this is based upon the assumption that the list can
		// get quite large (which it does for javax.swing) and that
		// a simple n-squared order search would be too slow.

		if (fullList.isEmpty()) {
			return false; // There are none in the full list, so there should be none, and don't merge.
		} else if (inheritedList.isEmpty())
			return false; // There are no inheritedList features, so treat as no merge.

		// We have some features and some inheritedList features, so we need to go through the lists.

		// Create a working copy of the FeatureDescriptorEquality for fullList and stripList and just reuse them
		FeatureDescriptorEquality workingStrip = FeatureDescriptorEquality.createEquality((FeatureDescriptor) inheritedList.get(0));
		FeatureDescriptorEquality workingFull = FeatureDescriptorEquality.createEquality((FeatureDescriptor) fullList.get(0));

		int inheritedSize = inheritedList.size();
		boolean[] copy = new boolean[inheritedSize];

		HashMap inheritedMap = new HashMap(inheritedSize);
		for (int i = 0; i < inheritedSize; i++) {
			FeatureDescriptor f = (FeatureDescriptor) inheritedList.get(i);
			String key = computeKey(f);
			Object value = inheritedMap.get(key);
			if (value == null)
				inheritedMap.put(key, new Integer(i));
			else {
				// Shouldn't occur.
			}

		}

		// When we are done with this processing, inheritedList will contain the super that should not be used, and full list will contain only the locals
		// (those defined at this class level).;
		int inheritedRetained = 0;
		Iterator fullItr = fullList.iterator();
		// Continue while we've retained less than the full super amount. If we've retained all of the inheritedList, there is no
		// need to continue processing the fullList because there can't possibly be any inheritedList entries left to find.
		while (inheritedRetained < inheritedSize && fullItr.hasNext()) {
			FeatureDescriptor f = (FeatureDescriptor) fullItr.next();
			boolean foundFull = false;
			Object index = inheritedMap.get(computeKey(f));
			if (index != null) {
				workingFull.setFeature(f);
				int ndx = ((Integer) index).intValue();
				workingStrip.setFeature((FeatureDescriptor) inheritedList.get(ndx));
				if (workingFull.equals(workingStrip)) {
					// They are semantically identical, so retain in the inheritedList.
					copy[ndx] = true;
					foundFull = true;
					inheritedRetained++;
				}
			}

			if (foundFull) {
				// We found the inheritedList entry semantically equal in the full list somewhere, so we need to remove the full entry.
				fullItr.remove();
			}
		}

		if (inheritedRetained == inheritedSize) {
			inheritedList.clear(); // All were found in inheritedList, so just clear the inheritedList and return just what was left in the found.
								   // Those in full found in super had been removed from full during the processing.
			return true; // We merge with all inherited. 
		} else	if (inheritedRetained != 0) {
			// Some were retained, take out of the list those that were retained.
			// When done the list will contain those that should be dropped from the inherited list.
			// We start from end because the actual number of bytes moved overall will be less than if we started from the front.
			for (ListIterator itr = inheritedList.listIterator(inheritedList.size()); itr.hasPrevious();) {
				int i = itr.previousIndex();
				itr.previous();	// To back up the itr so that remove can remove it. We actually don't care what the value is.
				if (copy[i])
					itr.remove();
			}
			return true;	// We merge, and the list is not empty but it did have some removed, so we leave the list alone. Those are not inherited.
		} else
			return false;	// All were removed (retained == 0). None were retained. So we just don't do a merge. The list will be ignored.
	}

	// The modeling beaninfo is also used to send itself back in serialized mode as a callback.

	private IVMCallbackServer vmServer;

	private int callbackID;

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jem.internal.proxy.common.ICallback#initializeCallback(org.eclipse.jem.internal.proxy.common.IVMServer, int)
	 */
	public void initializeCallback(IVMCallbackServer vmServer, int callbackID) {
		this.vmServer = vmServer;
		this.callbackID = callbackID;
	}
	
	public void send() throws IOException, CommandException {
		if (doFlags != 0) {
			ObjectOutputStream stream = new ObjectOutputStream(vmServer.requestStream(callbackID, 0));
			if ((doFlags & IBeanInfoIntrospectionConstants.DO_BEAN_DECOR) != 0)
				sendBeanDecorator(stream);
			if ((doFlags & IBeanInfoIntrospectionConstants.DO_PROPERTIES) != 0)
				sendPropertyDecorators(stream);
			if ((doFlags & IBeanInfoIntrospectionConstants.DO_METHODS) != 0)
				sendMethodDecorators(stream);
			if ((doFlags & IBeanInfoIntrospectionConstants.DO_EVENTS) != 0)
				sendEventDecorators(stream);
			stream.writeInt(IBeanInfoIntrospectionConstants.DONE);
			stream.close();
		}
	}

	/**
	 * Called by IDE to send the bean decorator information back through the callback.
	 * @throws CommandException
	 * @throws IOException
	 * 
	 * @since 1.1.0
	 */
	public void sendBeanDecorator(ObjectOutputStream stream) throws IOException, CommandException {
		BeanRecord br = new BeanRecord();
		BeanDescriptor bd = getBeanDescriptor();

		if (bd != null) {
			br.customizerClassName = getClassName(bd.getCustomizerClass());
			br.mergeInheritedProperties = isMergeInheritedProperties();
			br.mergeInheritedOperations = isMergeInheritedMethods();
			br.mergeInheritedEvents = isMergeInheritedEvents();
			br.notInheritedPropertyNames = getNotInheritedPropertyDescriptors();
			br.notInheritedOperationNames = getNotInheritedMethodDescriptors();
			br.notInheritedEventNames = getNotInheritedEventSetDescriptors();
			fill(bd, br, BEAN_RECORD_TYPE);
		}
		stream.writeInt(IBeanInfoIntrospectionConstants.BEAN_DECORATOR_SENT);
		stream.writeObject(br);
	}

	/**
	 * Called by IDE to send the property decorators information back through the callback.
	 * 
	 * @throws CommandException
	 * @throws IOException
	 * @since 1.1.0
	 */
	public void sendPropertyDecorators(ObjectOutputStream stream) throws IOException, CommandException {
		PropertyDescriptor[] properties = getPropertyDescriptors();
		if (properties != null && properties.length > 0) {
			// Now start writing the records.
			stream.writeInt(IBeanInfoIntrospectionConstants.PROPERTY_DECORATORS_SENT);
			stream.writeInt(properties.length);
			for (int i = 0; i < properties.length; i++) {
				PropertyDescriptor pd = properties[i];
				// Much of the two types are common, so if indexed, fill in the index part and then pass on to property part.
				PropertyRecord usepr = null;
				int useType = 0;
				if (pd.getClass() == IndexedPropertyDescriptor.class) {
					IndexedPropertyDescriptor ipd = (IndexedPropertyDescriptor) pd;
					IndexedPropertyRecord ipr = new IndexedPropertyRecord();
					usepr = ipr;
					useType = INDEXEDPROPERTY_RECORD_TYPE;
					ipr.indexedReadMethod = getReflectedMethodRecord(ipd.getIndexedReadMethod());
					ipr.indexedWriteMethod = getReflectedMethodRecord(ipd.getIndexedWriteMethod());
					ipr.indexedPropertyTypeName = getClassName(ipd.getIndexedPropertyType());
				} else {
					usepr = new PropertyRecord();
					useType = PROPERTY_RECORD_TYPE;
				}
				usepr.propertyEditorClassName = getClassName(pd.getPropertyEditorClass());
				usepr.propertyTypeName = getClassName(pd.getPropertyType());
				usepr.readMethod = getReflectedMethodRecord(pd.getReadMethod());
				usepr.writeMethod = getReflectedMethodRecord((pd.getWriteMethod()));
				usepr.bound = pd.isBound();
				usepr.constrained = pd.isConstrained();
				usepr.designTime = null;
				usepr.field = null;
				fill(pd, usepr, useType);
				stream.writeObject(usepr);
			}
		}
	}

	/**
	 * Called by IDE to send the method decorators information back through the callback.
	 * 
	 * @throws CommandException
	 * @throws IOException
	 * @since 1.1.0
	 */
	public void sendMethodDecorators(ObjectOutputStream stream) throws IOException, CommandException {
		MethodDescriptor[] methods = getMethodDescriptors();
		if (methods != null && methods.length > 0) {
			// Now start writing the records.
			stream.writeInt(IBeanInfoIntrospectionConstants.METHOD_DECORATORS_SENT);
			stream.writeInt(methods.length);
			for (int i = 0; i < methods.length; i++) {
				MethodRecord mr = new MethodRecord();
				fill(mr, methods[i]);
				stream.writeObject(mr);
			}
		}
	}

	/**
	 * Fill in a MethodRecord from the MethodDescriptor.
	 * @param mr
	 * @param md
	 * 
	 * @since 1.1.0
	 */
	protected void fill(MethodRecord mr, MethodDescriptor md) {
		mr.methodForDescriptor = getReflectedMethodRecord(md.getMethod());
		ParameterDescriptor[] parms = md.getParameterDescriptors();
		if (parms == null)
			mr.parameters = null;
		else {
			mr.parameters = new ParameterRecord[parms.length];
			for (int j = 0; j < parms.length; j++) {
				ParameterRecord pr = new ParameterRecord();
				fill(parms[j], pr, PARAMETER_RECORD_TYPE);
				mr.parameters[j] = pr;
			}
		}
		fill(md, mr, METHOD_RECORD_TYPE);
	}

	/**
	 * Called by IDE to send the event set decorators information back through the callback.
	 * 
	 * @throws CommandException
	 * @throws IOException
	 * @since 1.1.0
	 */
	public void sendEventDecorators(ObjectOutputStream stream ) throws IOException, CommandException {
		EventSetDescriptor[] events = getEventSetDescriptors();
		if (events != null && events.length > 0) {
			// Now start writing the records.
			stream.writeInt(IBeanInfoIntrospectionConstants.EVENT_DECORATORS_SENT);
			stream.writeInt(events.length);
			for (int i = 0; i < events.length; i++) {
				EventSetDescriptor ed = events[i];
				EventSetRecord er = new EventSetRecord();
				er.addListenerMethod = getReflectedMethodRecord(ed.getAddListenerMethod());
				MethodDescriptor[] mds = ed.getListenerMethodDescriptors();
				if (mds == null)
					er.listenerMethodDescriptors = null;
				else {
					er.listenerMethodDescriptors = new MethodRecord[mds.length];
					for (int j = 0; j < mds.length; j++) {
						fill(er.listenerMethodDescriptors[j] = new MethodRecord(), mds[j]);
					}
				}
				er.listenerTypeName = getClassName(ed.getListenerType());
				er.removeListenerMethod = getReflectedMethodRecord(ed.getRemoveListenerMethod());
				er.inDefaultEventSet = ed.isInDefaultEventSet();
				er.unicast = ed.isUnicast();
				er.eventAdapterClassName = null;
				fill(ed, er, EVENTSET_RECORD_TYPE);
				stream.writeObject(er);
			}
		}
	}

	protected static final int BEAN_RECORD_TYPE = 0;

	protected static final int PROPERTY_RECORD_TYPE = 1;

	protected static final int INDEXEDPROPERTY_RECORD_TYPE = 2;
	
	protected static final int METHOD_RECORD_TYPE = 3;
	
	protected static final int PARAMETER_RECORD_TYPE = 4;
	
	protected static final int EVENTSET_RECORD_TYPE = 5;

	/**
	 * Fill in the special attr/values for the given record type. The default handles the standard ones.
	 * 
	 * @param record
	 * @param descr
	 * @param attributeName
	 * @param recordType
	 *            type of record ultimately being processed.
	 * @return <code>true</code> if this attribute is a special one and processed, <code>false</code> if not special and should be added to
	 *         attributes list transferred to IDE.
	 * 
	 * @see ModelingBeanInfo#PROPERTY_RECORD_TYPE
	 * @since 1.1.0
	 */
	protected boolean fillFromAttributes(FeatureRecord record, FeatureDescriptor descr, String attributeName, int recordType) {
		switch (recordType) {
			case INDEXEDPROPERTY_RECORD_TYPE:
			case PROPERTY_RECORD_TYPE:
				if (BaseBeanInfo.DESIGNTIMEPROPERTY.equals(attributeName)) {
					((PropertyRecord) record).designTime = (Boolean) descr.getValue(attributeName);
					return true;
				} else if (BaseBeanInfo.FIELDPROPERTY.equals(attributeName)) {
					Field f = (Field) descr.getValue(attributeName);
					// We have a field, set the property type to this since we couldn't correctly create this otherwise.
					PropertyRecord pr = (PropertyRecord) record;
					pr.propertyTypeName = getClassName(f.getType());
					pr.field = getReflectedFieldRecord(f);
					pr.readMethod = null;	// Need to wipe out our dummy.
					pr.writeMethod = null;	// Or if it set, not valid for a field.
					return true;
				}
				break;
			case EVENTSET_RECORD_TYPE:
				if (BaseBeanInfo.EVENTADAPTERCLASS.equals(attributeName)) {
					((EventSetRecord) record).eventAdapterClassName = (String) descr.getValue(attributeName);
					return true;
				}
				break;
			default:
				break; // Didn't handle it.
		}
		return false;
	}

	/**
	 * Fill in the feature portion of the Descriptor into the record. We can be reusing some records (so we don't keep allocating when not needed), so
	 * we will null out unset fields.
	 * 
	 * @param descr
	 * @param record
	 * @param recordType
	 *            type of record ultimately being processed. Used for fillFromAttributes.
	 * 
	 * @see ModelingBeanInfo#PROPERTY_RECORD_TYPE
	 * @since 1.1.0
	 */
	protected void fill(FeatureDescriptor descr, FeatureRecord record, int recordType) {
		record.name = descr.getName();
		String dn = descr.getDisplayName();
		if (!record.name.equals(dn))
			record.displayName = dn; // display name returns name if display name not set. We don't want to send it if identical. (Note some Beaninfos are setting displayname the same text but not same string).
		else
			record.displayName = null;
		String shd = descr.getShortDescription();
		if (!dn.equals(shd))
			record.shortDescription = shd; // short description returns displayname if short description not set. We don't want to send it if
										   // identical.
		else
			record.shortDescription = null;
		record.expert = descr.isExpert();
		record.hidden = descr.isHidden();
		record.preferred = descr.isPreferred();
		record.category = null; // Clear out in case not set.
		Enumeration attrs = descr.attributeNames();
		if (attrs.hasMoreElements()) {
			// We don't have a way of knowing how many there are ahead of time, so we will build into lists and then turn into arrays at the end.
			List names = new ArrayList();
			List values = new ArrayList();
			while (attrs.hasMoreElements()) {
				String attrName = (String) attrs.nextElement();
				if (attrName.equals(IBaseBeanInfoConstants.CATEGORY))
					record.category = (String) descr.getValue(IBaseBeanInfoConstants.CATEGORY);
				else if (attrName.equals(BaseBeanInfo.PREFERRED)) {
					// A bug in Java 1.3, doing setPreferred was lost. So for those also stored it in attributes. So if set here, then use it.
					record.preferred = ((Boolean) descr.getValue(BaseBeanInfo.PREFERRED)).booleanValue();
				} else if (!fillFromAttributes(record, descr, attrName, recordType)) {
					// Just copy accross. FillfromAttributes didn't handle it.
					FeatureAttributeValue fv = new FeatureAttributeValue();
					fv.setValue(descr.getValue(attrName));
					names.add(attrName);
					values.add(fv);
				}
			}
			if (!names.isEmpty()) {
				record.attributeNames = (String[]) names.toArray(new String[names.size()]);
				record.attributeValues = (FeatureAttributeValue[]) values.toArray(new FeatureAttributeValue[values.size()]);
			} else {
				record.attributeNames = null;
				record.attributeValues = null;
			}
		} else {
			record.attributeNames = null;
			record.attributeValues = null;
		}

	}

	/*
	 * Get the classname from the class. If classs is null, then this return null.
	 */
	private String getClassName(Class classs) {
		return classs != null ? classs.getName() : null;
	}

	private ReflectMethodRecord getReflectedMethodRecord(Method method) {
		if (method != null) {
			ReflectMethodRecord rmr = new ReflectMethodRecord();
			rmr.className = getClassName(method.getDeclaringClass());
			rmr.methodName = method.getName();
			Class[] parmTypes = method.getParameterTypes();
			if (parmTypes.length > 0) {
				rmr.parameterTypeNames = new String[parmTypes.length];
				for (int i = 0; i < parmTypes.length; i++) {
					rmr.parameterTypeNames[i] = getClassName(parmTypes[i]);
				}
			}
			return rmr;
		} else
			return null;
	}
	
	private ReflectFieldRecord getReflectedFieldRecord(Field field) {
		if (field != null) {
			ReflectFieldRecord rf = new ReflectFieldRecord();
			rf.className = getClassName(field.getDeclaringClass());
			rf.fieldName = field.getName();
			rf.readOnly = Modifier.isFinal(field.getModifiers());
			return rf;
		} else
			return null;
	}
}
