/*******************************************************************************
 * 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;

/*
 *  $RCSfile: ModelingBeanInfo.java,v $
 *  $Revision: 1.11 $  $Date: 2005/10/18 15:32:19 $ 
 */

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