/*******************************************************************************
 * Copyright (c) 2001, 2004 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.adapters;
/*
 *  $RCSfile: BeaninfoClassAdapter.java,v $
 *  $Revision: 1.35 $  $Date: 2005/05/19 21:34:29 $ 
 */

import java.io.FileNotFoundException;
import java.lang.ref.WeakReference;
import java.text.MessageFormat;
import java.util.*;
import java.util.logging.Level;

import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.common.util.*;
import org.eclipse.emf.ecore.*;
import org.eclipse.emf.ecore.change.ChangeDescription;
import org.eclipse.emf.ecore.change.ChangeFactory;
import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.eclipse.emf.ecore.impl.ESuperAdapter;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreEList;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.xmi.XMIResource;

import org.eclipse.jem.internal.beaninfo.*;
import org.eclipse.jem.internal.beaninfo.common.*;
import org.eclipse.jem.internal.beaninfo.core.*;
import org.eclipse.jem.internal.java.beaninfo.IIntrospectionAdapter;
import org.eclipse.jem.internal.proxy.core.*;
import org.eclipse.jem.java.*;
import org.eclipse.jem.java.impl.JavaClassImpl;
import org.eclipse.jem.util.TimerTests;
import org.eclipse.jem.util.logger.proxy.Logger;

import com.ibm.etools.emf.event.EventFactory;
import com.ibm.etools.emf.event.EventUtil;

/**
 * Beaninfo adapter for doing introspection on a Java Model class.
 * <p>
 * The first time a introspect request is made, it will use the ClassEntry from the cache controller to determine if it should load from the
 * cache or do a complete introspection. After that it will always do a complete introspection when it is marked as needing introspection.
 * This is because the cache is useless to us then. At that point in time we already know that we or one of our superclasses or one of 
 * outer classes has changed, thereby requiring us to reintrospect, the cache is invalid at that point. Also once we did an introspection we
 * don't want to do a load from cache but instead do a merge because someone may of been holding onto the features and we don't want to
 * throw them away unnecessarily.
 * <p> 
 * TODO Need to re-look into this to see if we can do a merge with the cache file because if it was an external jar and it has now gone
 * valid, why waste time reintrospecting. But this needs to be carefully thought about. 
 * <p> 
 * The resource change listener
 * will automatically mark any subclasses (both the BeaninfoClassAdapter and the ClassEntry) as being stale for us. That way we don't need
 * to waste time checking the ce and superclasses everytime. We will keep the ClassEntry around simply to make the marking of it as stale easier for the
 * resource listener. Finding the ce everytime would be expensive.
 * <p> 
 * This is the process for determining if introspection required:
 * <ol>
 * <li>If needsIntrospection flag is false, then do nothing. Doesn't need introspection.
 * <li>If class is undefined, then just set up for an undefined class and return. (In this case the CE should be thrown away, it should of been deleted).
 * <li>If never introspected (not RETRIEVED_FULL_DOCUMENT), get the CE, get the modification stamp and call isStaleStamp. This determines if this
 * stamp or any super class stamp is stale wrt to current stamp. If it is not stale, then load from cache because the cache is good. 
 * <li>If no cache or cache is stale or has introspected once, then introspect and replace cache.
 * </ol>
 * 
 */

public class BeaninfoClassAdapter extends AdapterImpl implements IIntrospectionAdapter {
	
	public static final String REFLECT_PROPERTIES = "Reflect properties";	// Reflect properties in IDE //$NON-NLS-1$
	public static final String APPLY_EXTENSIONS = "Apply Overrides";	// Apply override files //$NON-NLS-1$
	public static final String REMOTE_INTROSPECT = "Remote Introspect";	// Introspect on remote //$NON-NLS-1$
	public static final String INTROSPECT = "Introspect";	// Straight introspection, whether load from cache or introspect. //$NON-NLS-1$
	public static final String LOAD_FROM_CACHE = "Load from Cache"; //$NON-NLS-1$
	
	// TODO Put this back (if necessary, not sure since haven't done it yet) when we do override change recording too to handle overrides. 
	// This will make it even faster because such
	// overrides rarely change and so can be glombed together into one large change. So then we would have two change caches per
	// class, one is the override record, which will be created once, the first time the class is referenced after a stale
	// configuration, and then the other is the introspection/reflection results, which will be created each time there is
	// a cache change. Both will be applied only once, the first time the class is referenced after a project has been opened.
	// No need to load at any other time because any changes will simply be a merge of the changes (thru reflection/introspection) into
	// the existing set and then a new change cache will be created containing the entire set of implicit changes, both the previous
	// ones that are still valid, and any new ones.
//	/**
//	 * Pausable Change Recorder.
//	 * 
//	 * @since 1.1.0
//	 */
//	private static class PausableChangeRecorder extends ChangeRecorder {
//		
//		/**
//		 * @param rootObject
//		 * 
//		 * @since 1.1.0
//		 */
//		public PausableChangeRecorder(EObject rootObject) {
//			super(rootObject);
//		}
//		/**
//		 * Pause recording
//		 * 
//		 * 
//		 * @since 1.1.0
//		 */
//		public void pause() {
//			recording = false;
//		}
//		
//		/**
//		 * Resume recording
//		 * 
//		 * 
//		 * @since 1.1.0
//		 */
//		public void resume() {
//			recording = true;
//		}
//	}
	
	public static BeaninfoClassAdapter getBeaninfoClassAdapter(EObject jc) {
		return (BeaninfoClassAdapter) EcoreUtil.getExistingAdapter(jc, IIntrospectionAdapter.ADAPTER_KEY);
	}
	
	/**
	 * Clear out the introspection because introspection is being closed or removed from the project.
	 * Don't want anything hanging around that we had done.
	 */
	public void clearIntrospection() {
		// Clear out the beandecorator if implicitly created.
		Iterator beanItr = getJavaClass().getEAnnotationsInternal().iterator();
		while (beanItr.hasNext()) {
			EAnnotation dec = (EAnnotation) beanItr.next();
			if (dec instanceof BeanDecorator) {
				BeanDecorator decor = (BeanDecorator) dec;
				if (decor.getImplicitDecoratorFlag() == ImplicitItem.IMPLICIT_DECORATOR_LITERAL) {
					beanItr.remove();
					((InternalEObject) decor).eSetProxyURI(BAD_URI); // Mark it as bad proxy so we know it is no longer any use.
				} else {
					BeanInfoDecoratorUtility.clear((BeanDecorator) dec);
				}
				break;
			}
		}
		// Clear out the features that we implicitly created.
		Iterator propItr = getJavaClass().getEStructuralFeaturesInternal().iterator();
		while (propItr.hasNext()) {
			EStructuralFeature prop = (EStructuralFeature) propItr.next();
			Iterator pdItr = prop.getEAnnotations().iterator();
			while (pdItr.hasNext()) {
				EAnnotation dec = (EAnnotation) pdItr.next();
				if (dec instanceof PropertyDecorator) {
					PropertyDecorator pd = (PropertyDecorator) dec;
					if (pd.getImplicitDecoratorFlag() == ImplicitItem.NOT_IMPLICIT_LITERAL)
						BeanInfoDecoratorUtility.clear(pd);
					else {
						pdItr.remove(); // Remove it from the property.
						((InternalEObject) pd).eSetProxyURI(BAD_URI); // Mark it as bad proxy so we know it is no longer any use.
					}
					if (pd.getImplicitDecoratorFlag() == ImplicitItem.IMPLICIT_DECORATOR_AND_FEATURE_LITERAL) {
						propItr.remove(); // Remove the feature itself
						((InternalEObject) prop).eSetProxyURI(BAD_URI); // Mark it as bad proxy so we know it is no longer any use.
					}
					break;
				}
			}
		}
		
		// Clear out the operations that we implicitly created.
		Iterator operItr = getJavaClass().getEOperationsInternal().iterator();
		while (operItr.hasNext()) {
			EOperation oper = (EOperation) operItr.next();
			Iterator mdItr = oper.getEAnnotations().iterator();
			while (mdItr.hasNext()) {
				EAnnotation dec = (EAnnotation) mdItr.next();
				if (dec instanceof MethodDecorator) {
					MethodDecorator md = (MethodDecorator) dec;
					if (md.getImplicitDecoratorFlag() == ImplicitItem.NOT_IMPLICIT_LITERAL)
						BeanInfoDecoratorUtility.clear(md);
					else {
						mdItr.remove(); // Remove it from the operation.
						((InternalEObject) md).eSetProxyURI(BAD_URI); // Mark it as bad proxy so we know it is no longer any use.
					}
					if (md.getImplicitDecoratorFlag() == ImplicitItem.IMPLICIT_DECORATOR_AND_FEATURE_LITERAL) {
						operItr.remove(); // Remove the oepration itself
						((InternalEObject) oper).eSetProxyURI(BAD_URI); // Mark it as bad proxy so we know it is no longer any use.
					}
					break;
				}
			}
			
			// Clear out the events that we implicitly created.
			Iterator evtItr = getJavaClass().getEventsGen().iterator();
			while (evtItr.hasNext()) {
				JavaEvent evt = (JavaEvent) evtItr.next();
				Iterator edItr = evt.getEAnnotations().iterator();
				while (edItr.hasNext()) {
					EAnnotation dec = (EAnnotation) edItr.next();
					if (dec instanceof EventSetDecorator) {
						EventSetDecorator ed = (EventSetDecorator) dec;
						if (ed.getImplicitDecoratorFlag() == ImplicitItem.NOT_IMPLICIT_LITERAL)
							BeanInfoDecoratorUtility.clear(ed);
						else {
							edItr.remove(); // Remove it from the event.
							((InternalEObject) ed).eSetProxyURI(BAD_URI); // Mark it as bad proxy so we know it is no longer any use.
						}
						if (ed.getImplicitDecoratorFlag() == ImplicitItem.IMPLICIT_DECORATOR_AND_FEATURE_LITERAL) {
							evtItr.remove(); // Remove the event itself
							((InternalEObject) evt).eSetProxyURI(BAD_URI); // Mark it as bad proxy so we know it is no longer any use.
						}
						break;
					}
				}
			}				
		}

		synchronized(this) {
			needsIntrospection = true;
		}
	}
	
	private void clearAll() {
		clearIntrospection();	// First get rid of the ones we did so that they are marked as proxies.
		
		// Clear out the annotations.
		getJavaClass().getEAnnotationsInternal().clear();
		// Clear out the attributes.
		getJavaClass().getEStructuralFeaturesInternal().clear();	
		// Clear out the operations.
		getJavaClass().getEOperationsInternal().clear();
		// Clear out the events.
		getJavaClass().getEventsGen().clear();
		
		retrievedExtensionDocument = NEVER_RETRIEVED_EXTENSION_DOCUMENT;	// Since we cleared everything, go back to no doc applied.
	}
	

	/**
	 * @version 	1.0
	 * @author
	 */

	// A URI that will never resolve. Used to mark an object as no longer valid.
	protected static final URI BAD_URI = URI.createURI("baduri"); //$NON-NLS-1$

	protected boolean needsIntrospection = true;
	
	protected BeanInfoCacheController.ClassEntry classEntry;
	
	protected boolean isIntrospecting;

	protected boolean isDoingAllProperties;

	protected boolean isDoingAllOperations;

	protected boolean isDoingAllEvents;

	protected final static int
		NEVER_RETRIEVED_EXTENSION_DOCUMENT = 0,
		RETRIEVED_ROOT_ONLY = 1,
		RETRIEVED_FULL_DOCUMENT = 2;
	protected int retrievedExtensionDocument = NEVER_RETRIEVED_EXTENSION_DOCUMENT;

	protected BeaninfoAdapterFactory adapterFactory;

	private WeakReference staleFactory; // When reference not null, then this factory is a stale factory and 
	// a new one is needed when the factory returned == this one.
	// It is a WeakRef so that if the factory goes away on its own
	// that we don't hold onto it.

	// A temporary hashset of the local properties. Used when creating a new
	// property to use the old one. It is cleared out at the end of attribute introspection.
	// It is only built once during attribute introspection so that we have the snapshot
	// of before the introspection (i.e. the ones that were specifically added by users
	// and not through introspection). The ones that we are adding do not need to be checked
	// against each other because there will not be conflicts.
	//
	// Also at the end, we will go through the properties and see if it exists in the fPropertiesMap and
	// it is not the value Boolean.FALSE in the map, and the entry is implicitly created. This means this
	// was an implicit entry from the previous introspection and was not re-created in this introspection.
	private HashMap propertiesMap;
	private List featuresRealList; // Temp pointer to the real list we are building. It is the true list in java class.
	
	// A temporary hashmap of the local operations. Used when creating a new
	// operation to reuse the old one. It is cleared out at the end of operation introspection.
	// It is only built once during operation introspection so that we have the snapshot
	// of before the introspection.
	private HashMap operationsMap;
	private EList operationsRealList; // Temp pointer to the real list we are building. It is the true list in java class.
	// A set of operations as we create them so that we which ones we added/kept and which are no longer in use and can be removed.	
	// If they aren't in this set at the end, then we know it should be removed if it is one we had created in the past.
	private HashSet newoperations; 

	// A temporary hashset of the local events. Used when creating a new
	// event to use the old one. It is cleared out at the end of event introspection.
	// It is only built once during event introspection so that we have the snapshot
	// of before the introspection (i.e. the ones that were specifically added by users
	// and not through introspection). The ones that we are adding do not need to be checked
	// against each other because there will not be conflicts.
	//
	// Also at the end, we will go through the events and see if it exists in the fEventsMap and
	// it is not the value Boolean.FALSE in the map, and the entry is implicitly created. This means this
	// was an implicit entry from the previous introspection and was not re-created in this introspection.
	private HashMap eventsMap;
	private EList eventsRealList; // Temp pointer to the real list we are building. It is the true list in java class.

	private Boolean defaultBound;
	// Whether this class is default bound or not (i.e. does this class implement add/remove property change listener. If null, then not yet queried.

	public BeaninfoClassAdapter(BeaninfoAdapterFactory factory) {
		super();
		adapterFactory = factory;
	}

	/*
	 * Answer whether this java class is still connected to a live resource. It happens during unloading
	 * that we are no longer connected to a resource (because the javapackage has already been processed and
	 * unloaded) or the resource is in the process of being unloaded, but the unloading process will still 
	 * call accessors on this java class, which will come over here. In those cases we should treat as
	 * introspection completed without doing anything.
	 */
	protected boolean isResourceConnected() {
		Resource res = getJavaClass().eResource();
		return res != null && res.isLoaded();
	}

	protected final ProxyFactoryRegistry getRegistry() {
		ProxyFactoryRegistry factory = adapterFactory.getRegistry();
		if (staleFactory != null && factory == staleFactory.get()) {
			// We need to recycle the factory. The returned factory is the same factory when it went stale.
			factory = adapterFactory.recycleRegistry();
		}
		staleFactory = null; // Whether we recycled or not, it is no longer stale.
		return factory;
	}

	/**
	 * Return whether this adapter has been marked as stale. Needed
	 * by the users so that they can recycle if necessary.
	 */
	public boolean isStale() {
		return staleFactory != null;
	}

	protected BeaninfoAdapterFactory getAdapterFactory() {
		return adapterFactory;
	}

	public boolean isAdapterForType(Object key) {
		return IIntrospectionAdapter.ADAPTER_KEY.equals(key);
	}

	/**
	 * This map is keyed by name. It is a snapshot of the properties at the
	 * time the introspection/reflection of properties was started. It is used
	 * for quick lookup.
	 *
	 * Once a property is used, the entry is replaced with a Boolean.FALSE. This
	 * is so we know which have already been used and at the end, which need
	 * to be deleted since they weren't used (i.e. the ones that aren't FALSE).
	 */
	protected HashMap getPropertiesMap() {
		if (propertiesMap == null) {
			List localFeatures = getJavaClass().getEStructuralFeaturesInternal();
			propertiesMap = new HashMap(localFeatures.size());
			Iterator itr = localFeatures.iterator();
			while (itr.hasNext()) {
				EStructuralFeature feature = (EStructuralFeature) itr.next();
				propertiesMap.put(feature.getName(), feature);
			}
		}
		return propertiesMap;
	}

	/**
	 * Get it once so that we don't need to keep getting it over and over.
	 */
	protected List getFeaturesList() {
		if (featuresRealList == null)
			featuresRealList = getJavaClass().getEStructuralFeaturesInternal();
		return featuresRealList;
	}

	/**
	 * The map is keyed by longName. If a Method is passed in, then the
	 * id of the method is used (this is in reflection), if an IBeanProxy
	 * is passed in, then an id is created and looked up (this is in introspection).
	 * The map is used for a quick lookup of behaviors at the time introspection
	 * of behaviors started.
	 */
	protected HashMap getOperationsMap() {
		if (operationsMap == null) {
			List locals = getJavaClass().getEOperationsInternal();
			int l = locals.size();
			operationsMap = new HashMap(l);
			for (int i = 0; i < l; i++) {
				EOperation op = (EOperation) locals.get(i);
				operationsMap.put(formLongName(op), op);
			}
		}
		return operationsMap;
	}

	/**
	 * Get it once so that we don't need to keep getting it over and over.
	 */
	protected EList getOperationsList() {
		if (operationsRealList == null)
			operationsRealList = getJavaClass().getEOperationsInternal();
		return operationsRealList;
	}

	/**
	 * The map is keyed by name.
	 * The map is used for a quick lookup of events at the time introspection
	 * of events started.
	 *
	 * Once an event is used, the entry is replaced with a Boolean.FALSE. This
	 * is so we know which have already been used and at the end, which need
	 * to be deleted since they weren't used (i.e. the ones that aren't FALSE).
	 */
	protected HashMap getEventsMap() {
		if (eventsMap == null) {
			List locals = getJavaClass().getEventsGen();
			eventsMap = new HashMap(locals.size());
			Iterator itr = locals.iterator();
			while (itr.hasNext()) {
				JavaEvent event = (JavaEvent) itr.next();
				eventsMap.put(event.getName(), event);
			}
		}
		return eventsMap;
	}

	/**
	 * Get it once so that we don't need to keep getting it over and over.
	 */
	protected EList getEventsList() {
		if (eventsRealList == null)
			eventsRealList = getJavaClass().getEventsGen();
		return eventsRealList;
	}

	public void introspectIfNecessary() {
		introspectIfNecessary(false);
	}
	
	protected void introspectIfNecessary(boolean doOperations) {
		boolean doIntrospection = false;
		synchronized (this) {
			doIntrospection = needsIntrospection && !isIntrospecting; 
			if (doIntrospection)
				isIntrospecting = true;
		}
		if (doIntrospection) {
			boolean didIntrospection = false;
			try {				
				introspect(doOperations);
				didIntrospection = true;
			} catch (Throwable e) {
				BeaninfoPlugin.getPlugin().getLogger().log(
					new Status(
						IStatus.WARNING,
						BeaninfoPlugin.getPlugin().getBundle().getSymbolicName(),
						0,
						MessageFormat.format(
							BeanInfoAdapterMessages.getString(BeanInfoAdapterMessages.INTROSPECTFAILED),
							new Object[] { getJavaClass().getJavaName(), ""}), //$NON-NLS-1$
						e));
			} finally {
				synchronized (this) {
					isIntrospecting = false;
					needsIntrospection = !didIntrospection;
				}
			}
		}
	}

	/**
	 * Get the class entry. 
	 * @return
	 * 
	 * @since 1.1.0
	 */
	public BeanInfoCacheController.ClassEntry getClassEntry() {
		return classEntry;
	}
	
	private boolean canUseCache() {
		// We check our level, we assume not stale unless CE says stale.
		synchronized (this) {
			// We may already have a class entry due to a subclass doing a check, so if we do, we'll use it. Else we'll get the latest one.
			if (classEntry == null)
				classEntry = BeanInfoCacheController.INSTANCE.getClassEntry(getJavaClass());
			if (classEntry != null) {
				// We have a cache to check.
				long modStamp = classEntry.getModificationStamp();
				// A sanity check, if this was an old, but now deleted one we want to throw it away and get it again. It may now be valid.
				if (modStamp == BeanInfoCacheController.ClassEntry.DELETED_MODIFICATION_STAMP) {
					classEntry = BeanInfoCacheController.INSTANCE.getClassEntry(getJavaClass());
					if (classEntry != null)
						modStamp = classEntry.getModificationStamp();
				}
				if (modStamp == IResource.NULL_STAMP || modStamp == BeanInfoCacheController.ClassEntry.DELETED_MODIFICATION_STAMP)
					return false;	// We are stale.
			} else
				return false;	// We don't have a cache entry to check against, which means are deleted, or never cached.
		}
		
		// Now try the supers to see if we are out of date to them.
		// Note: Only if this is an interface could there be more than one eSuperType.
		List supers = getJavaClass().getESuperTypes();
		if (!supers.isEmpty()) {
			BeaninfoClassAdapter bca = getBeaninfoClassAdapter((EObject) supers.get(0));
			if (bca.getClassEntry().getModificationStamp() != classEntry.getSuperModificationStamp())
				return false; // Out-of-date wrt/super.
			String[] iNames = classEntry.getInterfaceNames();
			if (iNames != null) {
				if (iNames.length != supers.size() - 1)
					return false; // We have a different number of supers, so stale.
				// Now the interfaces may not be in the same order, but there shouldn't be too many, so we'll use O(n2) lookup. We'll try starting at
				// the same index just in case. That way if they are the same order it will be linear instead. Most likely will be same order.
				long[] iStamp = classEntry.getInterfaceModificationStamps();
				for (int i = 1; i <= iNames.length; i++) {
					JavaClass javaClass = (JavaClass) supers.get(i);
					String intName = (javaClass).getQualifiedNameForReflection();
					// Find it in the names list.
					int stop = i-1;
					int indx = stop;	// Start at the stop, when we hit it again we will be done.
					boolean found = false;
					do {
						if (iNames[indx].equals(intName)) {
							found = true;
							break;
						}
					} while ((++indx)%iNames.length != stop);
					if (!found)
						return false;	// Couldn't find it, so we are stale.
					if (iStamp[indx] != getBeaninfoClassAdapter(javaClass).getClassEntry().getModificationStamp())
						return false;	// We didn't match it, so we are stale.
				}
			}
		}
		return true;	// If we got here everything is ok.
	}

	private boolean canUseOverrideCache() {
		// We check our config stamp.
		// TODO in future can we listen for config changes and mark classes stale if the config changes?
		synchronized (this) {
			// We may already have a class entry due to a subclass doing a check, so if we do, we'll use it. Else we'll get the latest one.
			if (classEntry == null)
				classEntry = BeanInfoCacheController.INSTANCE.getClassEntry(getJavaClass());
			if (classEntry != null) {
				// We have a cache to check.
				// A sanity check, if this was an old, but now deleted one we want to throw it away and get it again. It may now be valid.
				if (classEntry.isDeleted()) {
					classEntry = BeanInfoCacheController.INSTANCE.getClassEntry(getJavaClass());
					if (classEntry != null)
						if (classEntry.isDeleted())
							return false;	// We have been deleted. Probably shouldn't of gotton here in this case.
				}
			} else
				return false;	// We don't have a cache entry to check against, which means are deleted, or never cached.
			return classEntry.getConfigurationModificationStamp() == Platform.getPlatformAdmin().getState(false).getTimeStamp();
		}
		
	}

	/**
	 * Check if the cache for this entry is stale compared to the modification stamp, or if the modification stamp itself is stale, meaning
	 * subclass was stale already.
	 * 
	 * @param requestStamp the timestamp to compare against. 
	 * @return <code>true</code> if we can use the incoming cache stamp.
	 * 
	 * @since 1.1.0
	 */
	protected boolean canUseCache(long requestStamp) {
		long modStamp;
		// Now get the current mod stamp for this class so we can compare it.
		synchronized (this) {
			// We may already have a class entry due to a subclass doing a check, so if we do, we'll use it. Else we'll get the latest one.
			if (classEntry == null)
				classEntry = BeanInfoCacheController.INSTANCE.getClassEntry(getJavaClass());
			if (classEntry != null) {
				// We have a cache to check.
				modStamp = classEntry.getModificationStamp();
				// A sanity check, if this was an old, but now deleted one we want to throw it away and get it again. It may now be valid.
				if (modStamp == BeanInfoCacheController.ClassEntry.DELETED_MODIFICATION_STAMP) {
					classEntry = BeanInfoCacheController.INSTANCE.getClassEntry(getJavaClass());
					if (classEntry != null)
						modStamp = classEntry.getModificationStamp();
				}
				if (modStamp == IResource.NULL_STAMP && modStamp == BeanInfoCacheController.ClassEntry.DELETED_MODIFICATION_STAMP)
					return false;	// Since we are stale, child asking question must also be stale and can't use the cache.
			} else
				return false;	// We don't have a cache entry to check against, so child must be stale too.
		}
		// If the requested stamp is not the same as ours, then it is out of date (it couldn't be newer but it could be older).
		return requestStamp == modStamp;
	}
		
	/*
	 * This should only be called through introspectIfNecessary so that flags are set correctly.
	 */
	private void introspect(boolean doOperations) {
		IBeanProxy beaninfo = null;
		try {
			if (isResourceConnected()) {
				// See if are valid kind of class.
				if (getJavaClass().getKind() == TypeKind.UNDEFINED_LITERAL) {
					// Not valid, don't let any further introspection occur.
					// Mark that we've done all introspections so as not to waste time until we get notified that it has been added
					// back in.
					synchronized(this) {
						if (classEntry != null) {
							classEntry.markDeleted();	// mark it deleted in case still sitting in cache (maybe because it was in an external jar, we can't know if deleted when jar changed).
							classEntry = null;	// Get rid of it since now deleted.
						}
						needsIntrospection = false;
					}
					
					if (retrievedExtensionDocument == RETRIEVED_FULL_DOCUMENT) {
						// We've been defined at one point. Need to clear everything and step back
						// to never retrieved so that we now get the root added in. If we had been
						// previously defined, then we didn't have root. We will have to lose
						// all other updates too. But they can come back when we're defined.
						clearAll();
						retrievedExtensionDocument = NEVER_RETRIEVED_EXTENSION_DOCUMENT;
					}
					if (retrievedExtensionDocument == NEVER_RETRIEVED_EXTENSION_DOCUMENT)
						applyExtensionDocument(true);	// Add in Root stuff so that it will work correctly even though undefined.
				} else {
					// TODO For now cause recycle of vm if any super type is stale so that if registry is stale for the super type it will be
					// recreated. This is needed because reflection requires superProperties, etc. and recreating the registry
					// currently re-marks everyone as stale, including this subclass. This would mean that
					// re-introspection would need to be done, even though we just did it. The stale registry business needs to be re-addressed so that it is
					// a lot smarter. 
					List supers = getJavaClass().getEAllSuperTypes();
					for (int i = 0; i < supers.size(); i++) {
						BeaninfoClassAdapter bca = (BeaninfoClassAdapter) EcoreUtil.getExistingAdapter((EObject) supers.get(i),
								IIntrospectionAdapter.ADAPTER_KEY);
						if (bca != null && bca.isStale())
							bca.getRegistry();
					}
					// Now we need to force introspection, if needed, of all parents because we need them to be up-to-date for the
					// class entry.
					// TODO see if we can come up with a better way that we KNOW the CE is correct, even if any supers are stale.
					supers = getJavaClass().getESuperTypes();
					for (int i = 0; i < supers.size(); i++) {
						BeaninfoClassAdapter bca = (BeaninfoClassAdapter) EcoreUtil.getRegisteredAdapter((EObject) supers.get(i),
								IIntrospectionAdapter.ADAPTER_KEY);
						bca.introspectIfNecessary();
					}

					TimerTests.basicTest.startCumulativeStep(INTROSPECT);
					if (retrievedExtensionDocument == RETRIEVED_ROOT_ONLY) {
						// We need to clear out EVERYTHING because we are coming from an undefined to a defined.
						// Nothing previous is now valid. (Particularly the root stuff).
						clearAll();
					}
					boolean firstTime = false;
					if (retrievedExtensionDocument != RETRIEVED_FULL_DOCUMENT) {
						firstTime = true;	// If we need to apply the extension doc, then this is the first time.
						applyExtensionDocument(false); // Apply the extension doc before we do anything.
					}

					// Now check to see if we can use the cache.
					boolean doIntrospection = true;
					if (firstTime) {
						// Check if we can use the cache. Use Max value so that first level test (ourself) will always pass and go on to the supers.
						if (canUseCache()) {
							TimerTests.basicTest.startCumulativeStep(LOAD_FROM_CACHE);
							// We can use the cache.
							Resource cres = BeanInfoCacheController.INSTANCE.getCache(getJavaClass(), classEntry, true);
							if (cres != null) {
								try {
									// Got a cache to use, now apply it.
									for (Iterator cds = cres.getContents().iterator(); cds.hasNext();) {
										ChangeDescription cacheCD = (ChangeDescription) cds.next();
										cacheCD.apply();
									}
									// We need to walk through and create the appropriate ID's for events/actions/properties because by
									// default from the change descriptions these don't get reflected back. And if some one doesn't
									// use an ID to get them, they won't have an id set.
									doIDs();
									doIntrospection = false;
								} catch (RuntimeException e) {
									BeaninfoPlugin.getPlugin().getLogger().log(e);
								} finally {
									// Remove the cres since it is now invalid. The applies cause them to be invalid.
									cres.getResourceSet().getResources().remove(cres);
									if (doIntrospection) {
										// Apply had failed. We don't know how far it went. We need to wipe out and reget EVERYTHING.
										clearAll();
										applyExtensionDocument(false); // Re-apply the extension doc before we do anything else.
									}
								}
							}
							TimerTests.basicTest.stopCumulativeStep(LOAD_FROM_CACHE);
						}
					}
					
					if (doIntrospection) {
						// Finally we can get to handling ourselves.
						TimerTests.basicTest.startCumulativeStep(REMOTE_INTROSPECT);
						BeanDecorator decor = Utilities.getBeanDecorator(getJavaClass());
						if (decor == null) {
							decor = BeaninfoFactory.eINSTANCE.createBeanDecorator();
							decor.setImplicitDecoratorFlag(ImplicitItem.IMPLICIT_DECORATOR_LITERAL);
							getJavaClass().getEAnnotations().add(decor);
						} else
							BeanInfoDecoratorUtility.clear(decor);	// Clear out previous results.
						
						boolean doReflection = true;
						if (doOperations)
							newoperations = new HashSet(50);
						if (decor.isDoBeaninfo()) {
							int doFlags = 0;
							if (decor == null || decor.isMergeIntrospection())
								doFlags |= IBeanInfoIntrospectionConstants.DO_BEAN_DECOR;
							if (decor == null || decor.isIntrospectEvents())
								doFlags |= IBeanInfoIntrospectionConstants.DO_EVENTS;
							if (decor == null || decor.isIntrospectProperties())
								doFlags |= IBeanInfoIntrospectionConstants.DO_PROPERTIES;
							if (doOperations && (decor == null || decor.isIntrospectMethods()))
								doFlags |= IBeanInfoIntrospectionConstants.DO_METHODS;
							
							if (doFlags != 0) {
								// There was something remote to do.
								IBeanTypeProxy targetType = null;
								ProxyFactoryRegistry registry = getRegistry();
								if (registry != null && registry.isValid())
									targetType = registry.getBeanTypeProxyFactory().getBeanTypeProxy(getJavaClass().getQualifiedNameForReflection());
								if (targetType != null) {
									if (targetType.getInitializationError() == null) {
										// If an exception is thrown, treat this as no proxy, however log it because we
										// shouldn't have exceptions during introspection, but if we do it should be logged
										// so it can be corrected.
										try {
											beaninfo = getProxyConstants().getIntrospectProxy().invoke(null,
													new IBeanProxy[] { targetType, getRegistry().getBeanProxyFactory().createBeanProxyWith(false), getRegistry().getBeanProxyFactory().createBeanProxyWith(doFlags)});
										} catch (ThrowableProxy e) {
											BeaninfoPlugin.getPlugin().getLogger().log(
													new Status(IStatus.WARNING, BeaninfoPlugin.getPlugin().getBundle().getSymbolicName(), 0,
															MessageFormat.format(BeanInfoAdapterMessages
																	.getString(BeanInfoAdapterMessages.INTROSPECTFAILED), new Object[] {
																	getJavaClass().getJavaName(), ""}), //$NON-NLS-1$
																	e));
										}
									} else {
										// The class itself couldn't be initialized. Just log it, but treat as no proxy.
										BeaninfoPlugin.getPlugin().getLogger()
										.log(
												new Status(IStatus.WARNING, BeaninfoPlugin.getPlugin().getBundle().getSymbolicName(), 0,
														MessageFormat.format(BeanInfoAdapterMessages
																.getString(BeanInfoAdapterMessages.INTROSPECTFAILED), new Object[] {
																getJavaClass().getJavaName(), targetType.getInitializationError()}), null));
									}
								} else {
									// The class itself could not be found. Just log it, but treat as no proxy.
									BeaninfoPlugin.getPlugin().getLogger().log(
											new Status(IStatus.INFO, BeaninfoPlugin.getPlugin().getBundle().getSymbolicName(), 0, MessageFormat.format(
													BeanInfoAdapterMessages.getString(BeanInfoAdapterMessages.INTROSPECTFAILED), new Object[] {
															getJavaClass().getJavaName(),
															BeanInfoAdapterMessages.getString("BeaninfoClassAdapter.ClassNotFound")}), //$NON-NLS-1$
															null));
								}
								
								if (beaninfo != null) {
									doReflection = false;	// We have a beaninfo, so we are doing introspection.
									final BeanDecorator bdecor = decor;
									// We have a beaninfo to process.
									BeanInfoDecoratorUtility.introspect(beaninfo, new BeanInfoDecoratorUtility.IntrospectCallBack() {

										/*; (non-Javadoc)
										 * @see org.eclipse.jem.internal.beaninfo.adapters.BeanInfoDecoratorUtility.IntrospectCallBack#process(org.eclipse.jem.internal.beaninfo.common.BeanRecord)
										 */
										public BeanDecorator process(BeanRecord record) {
											return bdecor;
										}

										/* (non-Javadoc)
										 * @see org.eclipse.jem.internal.beaninfo.adapters.BeanInfoDecoratorUtility.IntrospectCallBack#process(org.eclipse.jem.internal.beaninfo.common.PropertyRecord)
										 */
										public PropertyDecorator process(PropertyRecord record) {
											return calculateProperty(record, false);
										}

										/* (non-Javadoc)
										 * @see org.eclipse.jem.internal.beaninfo.adapters.BeanInfoDecoratorUtility.IntrospectCallBack#process(org.eclipse.jem.internal.beaninfo.common.IndexedPropertyRecord)
										 */
										public PropertyDecorator process(IndexedPropertyRecord record) {
											return calculateProperty(record, true);
										}

										/* (non-Javadoc)
										 * @see org.eclipse.jem.internal.beaninfo.adapters.BeanInfoDecoratorUtility.IntrospectCallBack#process(org.eclipse.jem.internal.beaninfo.common.MethodRecord)
										 */
										public MethodDecorator process(MethodRecord record) {
											return calculateOperation(record);
										}

										/* (non-Javadoc)
										 * @see org.eclipse.jem.internal.beaninfo.adapters.BeanInfoDecoratorUtility.IntrospectCallBack#process(org.eclipse.jem.internal.beaninfo.common.EventSetRecord)
										 */
										public EventSetDecorator process(EventSetRecord record) {
											return calculateEvent(record);
										}
									});
								} 
							}
						}
						
						if (doReflection) {
							// Need to do reflection stuff.
							if (decor.isIntrospectProperties())
								reflectProperties();
							if (doOperations && decor.isIntrospectMethods())
								reflectOperations();
							if (decor.isIntrospectEvents())
								reflectEvents();
						}
						ChangeDescription cd = ChangeFactory.eINSTANCE.createChangeDescription();						
						BeanInfoDecoratorUtility.buildChange(cd, decor);
						finalizeProperties(cd);
						if (doOperations)
							finalizeOperations(cd);
						finalizeEvents(cd);

						classEntry = BeanInfoCacheController.INSTANCE.newCache(getJavaClass(), cd, doOperations ? BeanInfoCacheController.REFLECTION_OPERATIONS_CACHE : BeanInfoCacheController.REFLECTION_CACHE);
						TimerTests.basicTest.stopCumulativeStep(REMOTE_INTROSPECT); 
					}
					TimerTests.basicTest.stopCumulativeStep(INTROSPECT);
				}
				getAdapterFactory().registerIntrospection(getJavaClass().getQualifiedNameForReflection(), this);
			}
		} finally {
			if (beaninfo != null) {
				beaninfo.getProxyFactoryRegistry().releaseProxy(beaninfo); // Dispose of the beaninfo since we now have everything.
			}
			eventsMap = null; // Clear out the temp lists.
			eventsRealList = null;
			operationsMap = null; // Clear out the temp lists.
			operationsRealList = null;
			newoperations = null;
			propertiesMap = null; // Get rid of accumulated map.
			featuresRealList = null; // Release the real list.
		}
	}

	private void doIDs() {
		// Do properties.
		if (getJavaClass().eIsSet(EcorePackage.eINSTANCE.getEClass_EStructuralFeatures())) {
			List features = getFeaturesList();
			int len = features.size();
			for (int i = 0; i < len; i++) {
				EStructuralFeature f = (EStructuralFeature) features.get(i);
				PropertyDecorator pd = Utilities.getPropertyDecorator(f);
				if (pd == null || !pd.isMergeIntrospection())
					continue; // Not a property for us to give an ID to.
				setPropertyID(f.getName(), f);
			}
		}
		
		// Do events.
		if (getJavaClass().eIsSet(JavaRefPackage.eINSTANCE.getJavaClass_Events())) {
			List events = getEventsList();
			int len = events.size();
			for (int i = 0; i < len; i++) {
				BeanEvent e = (BeanEvent) events.get(i);
				EventSetDecorator ed = Utilities.getEventSetDecorator(e);
				if (ed == null || !ed.isMergeIntrospection())
					continue; // Not an event for us to give an ID to.
				setEventID(e.getName(), e);
			}
		}

		// Do Operations.
		if (getJavaClass().eIsSet(EcorePackage.eINSTANCE.getEClass_EOperations())) {
			List ops = getOperationsList();
			int len = ops.size();
			for (int i = 0; i < len; i++) {
				EOperation o = (EOperation) ops.get(i);
				MethodDecorator md = Utilities.getMethodDecorator(o);
				if (md == null || !md.isMergeIntrospection())
					continue; // Not an event for us to give an ID to.
				setMethodID(o.getName(), o);
			}
		}
	}

	private static final String ROOT_OVERRIDE = BeaninfoPlugin.ROOT+BeaninfoPlugin.OVERRIDE_EXTENSION;	 //$NON-NLS-1$
	
	protected void applyExtensionDocument(boolean rootOnly) {
		try {
			TimerTests.basicTest.startCumulativeStep(APPLY_EXTENSIONS);
			boolean canUseCache = !rootOnly && canUseOverrideCache();
			boolean alreadyRetrievedRoot = retrievedExtensionDocument == RETRIEVED_ROOT_ONLY;
			retrievedExtensionDocument = rootOnly ? RETRIEVED_ROOT_ONLY : RETRIEVED_FULL_DOCUMENT;
			JavaClass jc = getJavaClass();
			Resource mergeIntoResource = jc.eResource();
			ResourceSet rset = mergeIntoResource.getResourceSet();
			String className = jc.getName();
			if (canUseCache) {
				// We can use the cache, see if we actually have one.
				if (getClassEntry().overrideCacheExists()) {
					// Get the cache and apply it before anything else.
					Resource cacheRes = BeanInfoCacheController.INSTANCE.getCache(jc, getClassEntry(), false);
					if (cacheRes != null) {
						try {
							EventUtil util = EventFactory.eINSTANCE.createEventUtil(jc, rset);
							util.doForwardEvents(cacheRes.getContents());
						} catch (WrappedException e) {
							BeaninfoPlugin.getPlugin().getLogger().log(
									new Status(IStatus.WARNING, BeaninfoPlugin.PI_BEANINFO_PLUGINID, 0,
											"Error processing file\"" + cacheRes.getURI() + "\"", e.exception())); //$NON-NLS-1$ //$NON-NLS-2$						
						} finally {
							cacheRes.getResourceSet().getResources().remove(cacheRes); // We don't need it around once we do the merge. Normal merge would of gotton rid of it, but in case of error we do it here.
						}
					} else
						canUseCache = false; // Need to rebuild the cache.
				}
			}
			List overrideCache = null;
			if (!alreadyRetrievedRoot && (rootOnly || jc.getSupertype() == null)) {
				// It is a root class. Need to merge in root stuff.
				if (!canUseCache) {
					overrideCache = createOverrideCache(overrideCache, getAdapterFactory().getProject(), BeaninfoPlugin.ROOT, ROOT_OVERRIDE, rset, jc);
				}
				applyExtensionDocTo(rset, jc, ROOT_OVERRIDE, BeaninfoPlugin.ROOT, BeaninfoPlugin.ROOT);
				if (rootOnly)
					return;
			}

			String baseOverridefile = className + BeaninfoPlugin.OVERRIDE_EXTENSION; // getName() returns inner classes with "$" notation, which is good. //$NON-NLS-1$
			String packageName = jc.getJavaPackage().getPackageName();
			if (!canUseCache) {
				overrideCache = createOverrideCache(overrideCache, getAdapterFactory().getProject(), packageName, baseOverridefile, rset, jc);
			}
			applyExtensionDocTo(rset, jc, baseOverridefile, packageName, className);
			
			if (!canUseCache) {
				// We have an override cache to store. If the cache is null, this will flag that there is no override cache for the current configuration. That way we won't bother trying again until config changes.
				BeanInfoCacheController.INSTANCE.newCache(jc, overrideCache, BeanInfoCacheController.OVERRIDES_CACHE);
			}
			
		} finally {
			TimerTests.basicTest.stopCumulativeStep(APPLY_EXTENSIONS);	
		}
	}
	
	/*
	 * Build up the fixed overrides into the cache, and apply as we gather them.
	 * Return the cache or null if the cache is empty at the end.
	 */
	private List createOverrideCache(List cache, IProject project, String packageName, String overrideFile, ResourceSet rset, JavaClass mergeIntoJavaClass) {
		// Now get the overrides paths
		String[] paths = BeaninfoPlugin.getPlugin().getOverridePaths(project, packageName);
		if (paths.length == 0)
			return cache;
		
		// Now apply the overrides.
		if (cache == null)
			cache = new ArrayList();
		BeaninfoPlugin.IOverrideRunnable runnable = new ExtensionDocApplies(overrideFile, rset, mergeIntoJavaClass, cache);
		for (int i = 0; i < paths.length; i++) {
			runnable.run(paths[i]);
		}
		return !cache.isEmpty() ? cache : null;
	}
	
	private class ExtensionDocApplies implements BeaninfoPlugin.IOverrideRunnable {
		
		private final String overrideFile;
		private final ResourceSet rset;
		private final JavaClass mergeIntoJavaClass;
		private final List overridesCache;

		public ExtensionDocApplies(String overrideFile, ResourceSet rset, JavaClass mergeIntoJavaClass, List overridesCache) {
			this.overrideFile = overrideFile;
			this.rset = rset;
			this.mergeIntoJavaClass = mergeIntoJavaClass;
			this.overridesCache = overridesCache;
		}
		
		/* (non-Javadoc)
		 * @see org.eclipse.jem.internal.beaninfo.core.BeaninfoPlugin.IOverrideRunnable#run(java.lang.String)
		 */
		public void run(String overridePath) {
			Resource overrideRes = null;
			URI uri = URI.createURI(overridePath+overrideFile);
			try {
				overrideRes = rset.getResource(uri, true);
				run(overrideRes);
			} catch (WrappedException e) {
				// FileNotFoundException is ok
				if (!(e.exception() instanceof FileNotFoundException)) {
					if (e.exception() instanceof CoreException
						&& ((CoreException) e.exception()).getStatus().getCode() == IResourceStatus.RESOURCE_NOT_FOUND) {
						// This is ok. Means uri_mapping not set so couldn't find in Workspace, also ok.
					} else {
						BeaninfoPlugin.getPlugin().getLogger().log(new Status(IStatus.WARNING, BeaninfoPlugin.PI_BEANINFO_PLUGINID, 0, "Error loading file\"" + overridePath + "\"", e.exception())); //$NON-NLS-1$ //$NON-NLS-2$						
					}
				}
				// In case it happened after creating resource but during load. Need to get rid of it in the finally.	
				overrideRes = rset.getResource(uri, false);				
			} catch (Exception e) {
				// Couldn't load it for some reason.
				BeaninfoPlugin.getPlugin().getLogger().log(new Status(IStatus.WARNING, BeaninfoPlugin.PI_BEANINFO_PLUGINID, 0, "Error loading file\"" + overridePath + "\"", e)); //$NON-NLS-1$ //$NON-NLS-2$
				overrideRes = rset.getResource(uri, false); // In case it happened after creating resource but during load so that we can get rid of it.
			} finally {
				if (overrideRes != null)
					rset.getResources().remove(overrideRes); // We don't need it around once we do the merge. Normal merge would of gotton rid of it, but in case of error we do it here.
			}
		}
		
		/* (non-Javadoc)
		 * @see org.eclipse.jem.internal.beaninfo.core.BeaninfoPlugin.IOverrideRunnable#run(org.eclipse.emf.ecore.resource.Resource)
		 */
		public void run(Resource overrideRes) {
			try {
				if (overridesCache != null)
					overridesCache.addAll(EcoreUtil.copyAll(overrideRes.getContents()));	// Make a copy for the override cache to be used next time needed.
				EventUtil util = EventFactory.eINSTANCE.createEventUtil(mergeIntoJavaClass, rset);
				util.doForwardEvents(overrideRes.getContents());
			} catch (WrappedException e) {
				BeaninfoPlugin.getPlugin().getLogger().log(new Status(IStatus.WARNING, BeaninfoPlugin.PI_BEANINFO_PLUGINID, 0, "Error processing file\"" + overrideRes.getURI() + "\"", e.exception())); //$NON-NLS-1$ //$NON-NLS-2$						
			}
		}
	}
	protected void applyExtensionDocTo(ResourceSet rset, JavaClass mergeIntoJavaClass, String overrideFile, String packageName, String className) {
		BeaninfoPlugin.getPlugin().applyOverrides(getAdapterFactory().getProject(), packageName, className, mergeIntoJavaClass, rset, 
			new ExtensionDocApplies(overrideFile, rset, mergeIntoJavaClass, null));
	}

	/**
	 * Return the target as a JavaClass 
	 */
	protected JavaClassImpl getJavaClass() {
		return (JavaClassImpl) getTarget();
	}

	/**
	 * Answer the beaninfo constants record
	 */
	protected BeaninfoProxyConstants getProxyConstants() {
		return BeaninfoProxyConstants.getConstants(getRegistry());
	}

	/**
	 * @see org.eclipse.jem.java.beaninfo.IIntrospectionAdapter#getEStructuralFeatures()
	 */
	public EList getEStructuralFeatures() {
		introspectIfNecessary();
		return getJavaClass().getEStructuralFeaturesInternal();
	}
	
	/**
	 * @see org.eclipse.jem.java.beaninfo.IIntrospectionAdapter#getAllProperties()
	 */
	public EList getAllProperties() {
		return allProperties();
	}	
	
	/**
	 * @see org.eclipse.jem.java.beaninfo.IIntrospectionAdapter#getEOperations()
	 */
	public EList getEOperations() {
		if (getClassEntry() != null && getClassEntry().isOperationsStored())
			introspectIfNecessary();	// Already stored, just do if necessary.
		else {
			synchronized (this) {
				needsIntrospection = true;	// Force reintrospection because we either aren't storing operations, or have never loaded.
			}
			introspectIfNecessary(true);	// But force the operations now.
		}
		return getJavaClass().getEOperationsInternal();
	}
	
	/**
	 * @see org.eclipse.jem.java.beaninfo.IIntrospectionAdapter#getEAllOperations()
	 */
	public BasicEList getEAllOperations() {
		return allOperations();
	}
	
	/**
	 * @see org.eclipse.jem.java.beaninfo.IIntrospectionAdapter#getEvents()
	 */
	public EList getEvents() {
		introspectIfNecessary();
		return getJavaClass().getEventsGen();
	}
	
	/**
	 * @see org.eclipse.jem.java.beaninfo.IIntrospectionAdapter#getAllEvents()
	 */
	public EList getAllEvents() {
		return allEvents();
	}					

	private void finalizeProperties(ChangeDescription cd) {
		// Now go through the list and remove those that should be removed, and set the etype for those that don't have it set.
		Map oldLocals = getPropertiesMap();
		Iterator itr = getFeaturesList().iterator();
		while (itr.hasNext()) {
			EStructuralFeature a = (EStructuralFeature) itr.next();
			PropertyDecorator p = Utilities.getPropertyDecorator(a);
			Object aOld = oldLocals.get(a.getName());
			if (aOld != null && aOld != Boolean.FALSE) {
				// A candidate for removal. It was in the old list and it was not processed.
				if (p != null) {
					ImplicitItem implicit = p.getImplicitDecoratorFlag();
					if (implicit != ImplicitItem.NOT_IMPLICIT_LITERAL) {
						p.setEModelElement(null); // Remove from the feature;
						((InternalEObject) p).eSetProxyURI(BAD_URI);
						// Mark it as bad proxy so we know it is no longer any use.
						p = null;
						if (implicit == ImplicitItem.IMPLICIT_DECORATOR_AND_FEATURE_LITERAL) {
							itr.remove(); // Remove it, this was implicitly created and not processed this time.
							((InternalEObject) a).eSetProxyURI(BAD_URI);	// Mark it as bad proxy so we know it is no longer any use.
							continue;
						}
						// Need to go on because we need to check the eType to make sure it is set. At this point we have no decorator but we still have a feature.
					}
				}
			}
			
			// [79083] Also check for eType not set, and if it is, set it to EObject type. That way it will be valid, but not valid as 
			// a bean setting.
			if (a.getEType() == null) {
				// Set it to EObject type. If it becomes valid later (through the class being changed), then the introspect/reflect
				// will set it to the correct type.
				a.setEType(EcorePackage.eINSTANCE.getEObject());
				Logger logger = BeaninfoPlugin.getPlugin().getLogger();
				if (logger.isLoggingLevel(Level.WARNING))
					logger.logWarning("Feature \""+getJavaClass().getQualifiedName()+"->"+a.getName()+"\" did not have a type set. Typically due to override file creating feature but property not found on introspection/reflection."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			}
			
			if (p != null && cd != null) {
				// Now create the appropriate cache entry for this property.
				BeanInfoDecoratorUtility.buildChange(cd, p);
			}
		}
	}

	/**
	 * merge all  the Properties (i.e. supertypes) (properties)
	 */
	protected EList allProperties() {
		
		EList jcAllProperties = getJavaClass().getAllPropertiesGen();
		BeaninfoSuperAdapter superAdapter =
			(BeaninfoSuperAdapter) EcoreUtil.getRegisteredAdapter(getJavaClass(), BeaninfoSuperAdapter.class);
		if (jcAllProperties != null) {
			// See if new one required.
			if (superAdapter == null || !superAdapter.isAllPropertiesCollectionModified())
				return jcAllProperties;
			// Can't get superadapter, so must not be attached to a resource, so return current list. Or no change required.       		
		}
		
		UniqueEList.FastCompare allProperties = new UniqueEList.FastCompare() {
			protected Object[] newData(int capacity) {
				return new EStructuralFeature[capacity];
			}
		};
		boolean doAllProperties = false;
		synchronized(this) {
			// If we are introspecting, don't do all properties because it is an invalid list. Just return empty without reseting the all modified flag.
			doAllProperties = !isDoingAllProperties && !isIntrospecting && isResourceConnected();
			if (doAllProperties)
				isDoingAllProperties = true;
		}
		if (doAllProperties) {
			try {
				EList localProperties = getJavaClass().getProperties();
				// Kludge: BeanInfo spec doesn't address Interfaces, but some people want to use them.
				// Interfaces can have multiple extends, while the Introspector ignores these for reflection,
				// the truth is most people want these. So we will add them in. But since there could be more than one it
				// gets confusing. We need to look for dups from the super types and still keep order.
				//
				// Supertypes will never be more than one entry for classes, it is possible to be 0, 1, 2 or more for interfaces.
				List superTypes = getJavaClass().getESuperTypes();
				if (!superTypes.isEmpty()) {
					// Now we need to merge in the supers.
					BeanDecorator bd = Utilities.getBeanDecorator(getJavaClass());
					// If there is only one supertype, we can add to the actual events, else we will use the linked hashset so that
					// we don't add possible duplicates (e.g. IA extends IB,IC and IB extends IC. In this case there would be dups
					// because IB would contribute IC's too).
					Collection workingAllProperties = superTypes.size() == 1 ? (Collection) allProperties : new LinkedHashSet(); 
					// We will now merge as directed.
					boolean mergeAll = bd == null || bd.isMergeSuperProperties();
					if (!mergeAll) {
						// we don't to want to merge super properties, but we still need super non-properties or explict ones.
						int lenST = superTypes.size();
						for (int i=0; i<lenST; i++) {
							List supers = ((JavaClass) superTypes.get(i)).getAllProperties();
							int len = supers.size();
							for (int i1 = 0; i1 < len; i1++) {
								EStructuralFeature p = (EStructuralFeature) supers.get(i1);
								PropertyDecorator pd = Utilities.getPropertyDecorator(p);
								if ( pd == null || (pd.getImplicitDecoratorFlag() == ImplicitItem.NOT_IMPLICIT_LITERAL && !pd.isMergeIntrospection()))
									workingAllProperties.add(p);
							}
						}
					} else {
						// We want to merge all.					
						// BeanInfo could of given us the not merge list. If the list is empty, then we accept all.
						if (bd != null && bd.eIsSet(BeaninfoPackage.eINSTANCE.getBeanDecorator_NotInheritedPropertyNames())) {
							// We were given a list of names.
							// Get the names into a set to create a quick lookup.
							HashSet superSet = new HashSet(bd.getNotInheritedPropertyNames());
							
							// Now walk and add in non-bean properties (and bean properties that were explicitly added and not mergeable (i.e. didn't come thru beaninfo)) 
							// and add those not specifically called out by BeanInfo in the not inherited list.
							int lenST = superTypes.size();
							for (int i=0; i<lenST; i++) {
								List supers = ((JavaClass) superTypes.get(i)).getAllProperties();
								int len = supers.size();
								for (int i1 = 0; i1 < len; i1++) {
									EStructuralFeature p = (EStructuralFeature) supers.get(i1);
									PropertyDecorator pd = Utilities.getPropertyDecorator(p);
									if (pd == null || (pd.getImplicitDecoratorFlag() == ImplicitItem.NOT_IMPLICIT_LITERAL && !pd.isMergeIntrospection()) || !superSet.contains(pd.getName()))
										workingAllProperties.add(p);
								}
							}
						} else {
							// BeanInfo (or reflection always does this) called out that all super properties are good
							int lenST = superTypes.size();
							for (int i=0; i<lenST; i++) {
								workingAllProperties.addAll(((JavaClass) superTypes.get(i)).getAllProperties());
							}
						}
					}
					if (workingAllProperties != allProperties)
						allProperties.addAll(workingAllProperties);	// Now copy over the ordered super properties.
				}
				allProperties.addAll(localProperties);				
				superAdapter.setAllPropertiesCollectionModified(false); // Now built, so reset to not changed.
			} finally {
				synchronized(this) {
					isDoingAllProperties = false;
				}
			}
		}

		if (!allProperties.isEmpty()) {
			allProperties.shrink();
			return new EcoreEList.UnmodifiableEList.FastCompare(
				getJavaClass(),
				null,
				allProperties.size(),
				allProperties.data());
		} else
			return ECollections.EMPTY_ELIST;
	}

	/*
	 * Fill in the property using the prop record. If this one that should have merging done, then
	 * return the PropertyDecorator so that it can have the PropertyRecord merged into it. Else
	 * return null if no merging.
	 */
	protected PropertyDecorator calculateProperty(PropertyRecord pr, boolean indexed) {
		// If this is an indexed property, then a few fields will not be set in here, but
		// will instead be set by the calculateIndexedProperty, which will be called.
		boolean changeable = pr.writeMethod != null || (pr.field != null && !pr.field.readOnly);
		JavaHelpers type = pr.propertyTypeName != null ? Utilities.getJavaType(MapJNITypes.getFormalTypeName(pr.propertyTypeName), getJavaClass().eResource().getResourceSet()) : null;

		if (indexed) {
			// If no array write method found, then see if there is an indexed write method. If there is, then it is changable.
			if (!changeable)
				changeable = ((IndexedPropertyRecord) pr).indexedWriteMethod != null;
			if (type == null) {
				// If no array type from above, create one from the indexed type proxy. Add '[]' to turn it into an array.
				type = Utilities.getJavaType(MapJNITypes.getFormalTypeName(((IndexedPropertyRecord) pr).indexedPropertyTypeName)+"[]", getJavaClass().eResource().getResourceSet()); //$NON-NLS-1$
			}
		}

		if (type != null)
			return createProperty(pr.name, indexed, changeable, type); // A valid property descriptor.
		else
			return null;
	}

	/**
	 * Fill in the property and its decorator using the passed in information.
	 */
	protected PropertyDecorator createProperty(String name, boolean indexed, boolean changeable, EClassifier type) {
		// First find if there is already a property of this name, and if there is, is the PropertyDecorator
		// marked to not allow merging in of introspection results.		
		HashMap existingLocals = getPropertiesMap();
		EStructuralFeature prop = null;
		PropertyDecorator pd = null;
		Object p = existingLocals.get(name);
		if (Boolean.FALSE == p)
			return null; // We've already processed this name, can't process it again.
		if (p != null) {
			// We've found one of the same name. Whether we modify it or use it as is, we put in a
			// special dummy in its place. That marks that we've already processed it and accepted it.
			existingLocals.put(name, Boolean.FALSE);

			// If the decorator for this entry says not to merge then return.
			// If there is no PropertyDecorator, then we will merge. If they
			// didn't want to merge then should of created of property decorator and said no merge.
			pd = Utilities.getPropertyDecorator((EStructuralFeature) p);
			if (pd != null && !pd.isMergeIntrospection())
				return null;
			prop = (EStructuralFeature) p;
		}

		// Need to test if this is an implicit decorator and it is not of the 
		// same type (i.e. is indexed now but wasn't or visa-versa, then we need
		// to get rid of the decorator and recreate it. If it is not implicit, then
		// we have to use it as is because the user specified, so it won't become
		// an indexed if the user did not created it as an index, and visa-versa.
		// Also if it is implicit, then we need to unset certain features that may of
		// been set by a previous reflection which has now become introspected.
		// When reflected we set the actual fields instead of the letting proxy determine them.
		if (pd != null) {
			if (pd.getImplicitDecoratorFlag() == ImplicitItem.NOT_IMPLICIT_LITERAL) {
				// We can't change the type for explicit.
				indexed = pd instanceof IndexedPropertyDecorator;
			} else {
				if ((indexed && !(pd instanceof IndexedPropertyDecorator)) || (!indexed && pd instanceof IndexedPropertyDecorator)) {
					// It is implicit and of a different type, so just get rid of it and let it be recreated correctly.
					prop.getEAnnotations().remove(pd);
					pd = null;
				}
			}
			if (pd != null)
				if (indexed)
					BeanInfoDecoratorUtility.clear((IndexedPropertyDecorator) pd);
				else
					BeanInfoDecoratorUtility.clear(pd);
		}

		ImplicitItem implicit = pd == null ? ImplicitItem.IMPLICIT_DECORATOR_LITERAL : pd.getImplicitDecoratorFlag();
		if (prop == null) {
			// We will create a new property.
			// We can't have an implicit feature, but an explicit decorator.
			getFeaturesList().add(prop = EcoreFactory.eINSTANCE.createEReference());
			implicit = ImplicitItem.IMPLICIT_DECORATOR_AND_FEATURE_LITERAL;
		}

		setPropertyID(name, prop);
		prop.setName(name);
		prop.setTransient(false);
		prop.setVolatile(false);
		prop.setChangeable(changeable);

		// Containment and Unsettable is tricky for EReferences. There is no way to know whether it has been explicitly set to false, or it defaulted to
		// false because ECore has not made containment/unsettable an unsettable feature. So we need to instead use the algorithm of if we here 
		// created the feature, then we will by default set it to containment/unsettable. If it was created through diff merge, then
		// we will leave it alone. It is the responsibility of the merge file writer to set containment/unsettable correctly.
		if (implicit == ImplicitItem.IMPLICIT_DECORATOR_AND_FEATURE_LITERAL) {
			prop.setUnsettable(true);
		}
		prop.setEType(type);
		if (!indexed) {
			prop.setLowerBound(0);
			prop.setUpperBound(1);
		} else {
			prop.setLowerBound(0);
			prop.setUpperBound(-1);
			prop.setUnique(true);
		}

		// Now create/fill in the property descriptor for it.
		// If there already is one then we
		// will use it. This allows merging with beanfinfo.		
		if (pd == null) {
			pd =
				(!indexed)
					? BeaninfoFactory.eINSTANCE.createPropertyDecorator()
					: BeaninfoFactory.eINSTANCE.createIndexedPropertyDecorator();
			pd.setImplicitDecoratorFlag(implicit);
			prop.getEAnnotations().add(pd);
		}
		return pd;
	}

	/**
	 * @param name
	 * @param prop
	 * 
	 * @since 1.1.0
	 */
	private void setPropertyID(String name, EStructuralFeature prop) {
		// Now fill it in. Normal id for an attribute is "classname.attributename" but we can't use that
		// for us because that format is used by Java Core for a field and there would be confusion.
		// So we will use '/' instead.
		((XMIResource) prop.eResource()).setID(prop, getJavaClass().getName() + BeaninfoJavaReflectionKeyExtension.FEATURE + name);
	}

	/*
	 * Reflect the properties. This requires going through local methods and matching them up to
	 * see if they are properties.
	 */
	private void reflectProperties() {
		// If we are set to mergeSuperTypeProperties, then we need to get the super properties.
		// This is so that duplicate any from super that we find here. When reflecting we don't
		// allow discovered duplicates unless they are different types.
		//
		// Kludge: BeanInfo spec doesn't address Interfaces, but some people want to use them.
		// Interfaces can have multiple extends, while the Introspector ignores these for reflection,
		// the truth is most people want these. So we will add them in. But since there could be more than one it
		// gets confusing. We need to look for dups from the super types.
		//
		// Supertypes will never be more than one entry for classes, it is possible to be 0, 1, 2 or more for interfaces.
		TimerTests.basicTest.startCumulativeStep(REFLECT_PROPERTIES);		
		Set supers = new HashSet(50);
		BeanDecorator bd = Utilities.getBeanDecorator(getJavaClass());
		if (bd == null || bd.isMergeSuperProperties()) {
			List superTypes = getJavaClass().getESuperTypes();
			if (!superTypes.isEmpty()) {
				int lenST = superTypes.size();
				for (int i=0; i<lenST; i++) {
					List superAll = ((JavaClass) superTypes.get(i)).getAllProperties();
					int len = superAll.size();
					for (int i1=0; i1<len; i1++) {
						EStructuralFeature sf = (EStructuralFeature) superAll.get(i1);
						supers.add(sf.getName());
					}
				}
			}
		}

		// If any of the classes in the hierarchy are bound, then all reflected properties are considered bound.
		boolean isBound = isDefaultBound();
		if (!isBound) {
			List superTypes = getJavaClass().getEAllSuperTypes();
			// Start from end because that will be first class above the this one.
			for (int i=superTypes.size()-1; !isBound && i>=0; i--) {
				JavaClass spr = (JavaClass) superTypes.get(i);
				BeaninfoClassAdapter bi = (BeaninfoClassAdapter) EcoreUtil.getExistingAdapter(spr, IIntrospectionAdapter.ADAPTER_KEY);
				// They should all be reflected, but be on safe side, check if null.
				if (bi != null)
					isBound = bi.isDefaultBound();
			}
		}

		HashMap props = new HashMap();

		Iterator itr = getJavaClass().getPublicMethods().iterator();
		while (itr.hasNext()) {
			Method mthd = (Method) itr.next();
			if (mthd.isStatic() || mthd.isConstructor())
				continue; // Statics/constructors don't participate as properties
			if (mthd.getName().startsWith("get")) { //$NON-NLS-1$
				String name = java.beans.Introspector.decapitalize(mthd.getName().substring(3));
				if (name.length() == 0 || supers.contains(name))
					continue;	// Had get(...) and not getXXX(...) so not a getter. Or this is the same name as a super, either way ignore it.
				PropertyInfo propInfo = (PropertyInfo) props.get(name);
				if (propInfo == null) {
					propInfo = new PropertyInfo();
					if (propInfo.setGetter(mthd, false))
						props.put(name, propInfo);
				} else
					propInfo.setGetter(mthd, false);
			} else if (mthd.getName().startsWith("is")) { //$NON-NLS-1$
				String name = java.beans.Introspector.decapitalize(mthd.getName().substring(2));
				if (name.length() == 0 || supers.contains(name))
					continue;	// Had is(...) and not isXXX(...) so not a getter. Or this is the same name as a super, either way ignore it.
				PropertyInfo propInfo = (PropertyInfo) props.get(name);
				if (propInfo == null) {
					propInfo = new PropertyInfo();
					if (propInfo.setGetter(mthd, true))
						props.put(name, propInfo);
				} else
					propInfo.setGetter(mthd, true);
			} else if (mthd.getName().startsWith("set")) { //$NON-NLS-1$
				String name = java.beans.Introspector.decapitalize(mthd.getName().substring(3));
				if (name.length() == 0 || supers.contains(name))
					continue;	// Had set(...) and not setXXX(...) so not a setter. Or this is the same name as a super, either way ignore it.				
				PropertyInfo propInfo = (PropertyInfo) props.get(name);
				if (propInfo == null) {
					propInfo = new PropertyInfo();
					if (propInfo.setSetter(mthd))
						props.put(name, propInfo);
				} else
					propInfo.setSetter(mthd);
			}
		}

		// Now go through the hash map and create the properties.
		itr = props.entrySet().iterator();
		while (itr.hasNext()) {
			Map.Entry entry = (Map.Entry) itr.next();
			((PropertyInfo) entry.getValue()).createProperty((String) entry.getKey(), isBound);
		}
		TimerTests.basicTest.stopCumulativeStep(REFLECT_PROPERTIES);		
	}

	private class PropertyInfo {
		
		public EClassifier type, indexedType;
		public boolean constrained;
		public Method getter, setter, indexedGetter, indexedSetter;

		public boolean setGetter(Method get, boolean mustBeBoolean) {
			List parms = get.getParameters();
			if (parms.size() > 1)
				return false; // Invalid - improper number of parms.
			boolean indexed = parms.size() == 1;
			if (indexed && !((JavaParameter) parms.get(0)).getEType().getName().equals("int")) //$NON-NLS-1$
				return false; // Invalid - a parm that is not an int is invalid for indexed.
			EClassifier retType = get.getReturnType();
			if (retType == null || retType.getName().equals("void")) //$NON-NLS-1$
				return false; // Invalid - must have a return type
			if (mustBeBoolean && !retType.getName().equals("boolean")) //$NON-NLS-1$
				return false; // Invalid - it must be a boolean.
			if (indexed) {
				if (indexedType != null) {
					if (indexedType != retType)
						return false; // Invalid - type is different from previous info.
				}
				if (type != null && !(((JavaHelpers) type).isArray() && ((ArrayType) type).getComponentType() == retType))
					return false; // Invalid - indexed type doesn't match component type of base type.
			} else {
				if (type != null) {
					if (type != retType)
						return false; // Invalid - type is different from previous info.
				}
				if (indexedType != null && !(((JavaHelpers) retType).isArray() && ((ArrayType) retType).getComponentType() == indexedType))
					if (type == null) {
						// We had a potential indexed and had not yet found the regular type. We've now found
						// the regular type, and it is not indexed. So it takes priority and will wipe out
						// the indexed type.
						indexedGetter = null;
						indexedSetter = null;
						indexedType = null;
					} else
						return false; // Invalid - indexed type doesn't match component type of base type we already have
			}

			if (indexed) {
				if (indexedGetter != null)
					return false; // Already have an indexed getter.
				indexedGetter = get;
				indexedType = retType;
			} else {
				if (getter != null)
					return false; // Already have a getter
				getter = get;
				type = retType;
			}
			return true;
		}

		public boolean setSetter(Method set) {
			List parms = set.getParameters();
			if (parms.size() > 2 || parms.size() < 1)
				return false; // Invalid - improper number of parms.
			boolean indexed = parms.size() == 2;
			if (indexed && !((JavaParameter) parms.get(0)).getEType().getName().equals("int")) //$NON-NLS-1$
				return false; // Invalid - a parm that is not an int is invalid for indexed.
			EClassifier retType = set.getReturnType();
			if (retType != null && !retType.getName().equals("void")) //$NON-NLS-1$
				return false; // Invalid - must not have a return type
			EClassifier propType = null;
			if (indexed) {
				propType = ((JavaParameter) parms.get(1)).getEType();
				if (indexedType != null) {
					if (indexedType != propType)
						return false; // Invalid - type is different from previous info.
				}
				if (type != null && !(((JavaHelpers) type).isArray() && ((ArrayType) type).getComponentType() == propType))
					return false; // Invalid - indexed type doesn't match component type of base type, or base type not an array
			} else {
				propType = ((JavaParameter) parms.get(0)).getEType();
				if (type != null) {
					if (type != propType)
						return false; // Invalid - type is different from previous info.
				}
				if (indexedType != null
					&& !(((JavaHelpers) propType).isArray() && ((ArrayType) propType).getComponentType() == indexedType))
					if (type == null) {
						// We had a potential indexed and had not yet found the regular type. We've now found
						// the regular type, and it is not indexed of the correct type. So it takes priority and will wipe out
						// the indexed type.
						indexedGetter = null;
						indexedSetter = null;
						indexedType = null;
					} else
						return false; // Invalid - indexed type doesn't match component type of base type from this setter.
			}

			if (indexed) {
				if (indexedSetter != null)
					return false; // Already have an indexed getter.
				indexedSetter = set;
				indexedType = propType;
			} else {
				if (setter != null)
					return false; // Already have a getter
				setter = set;
				type = propType;
			}

			if (set.getJavaExceptions().contains(Utilities.getJavaClass("java.beans.PropertyVetoException", getJavaClass().eResource().getResourceSet()))) //$NON-NLS-1$
				constrained = true;
			return true;
		}

		public void createProperty(String name, boolean isBound) {
			boolean indexed = indexedType != null;
			if (indexed && type == null)
				return; // A potential indexed, but never found the getter/setter of the regular type.

			PropertyDecorator prop =
				BeaninfoClassAdapter.this.createProperty(
					name,
					indexed,
					(!indexed) ? (setter != null) : (setter != null || indexedSetter != null),
					type);
			if (prop == null)
				return; // Reflection not wanted.

			indexed = prop instanceof IndexedPropertyDecorator; // It could of been forced back to not indexed if explicitly set.

			// At this point in time all implicit settings have been cleared. This is done back in createProperty() method above.
			// So now apply reflected settings on the property decorator. 
			BeanInfoDecoratorUtility.setProperties(prop, isBound, constrained, getter, setter);
			if (indexed)
				BeanInfoDecoratorUtility.setProperties((IndexedPropertyDecorator) prop, indexedGetter, indexedSetter);

		}
	};

	/*
	 * Should only be called from introspect so that flags are correct.
	 */
	private void finalizeOperations(ChangeDescription cd) {
		// Now go through the list and remove those that should be removed.
		Iterator itr = getOperationsList().iterator();
		while (itr.hasNext()) {
			EOperation a = (EOperation) itr.next();
			MethodDecorator m = Utilities.getMethodDecorator(a);
			if (!newoperations.contains(a)) {
				// A candidate for removal. It is in the list but we didn't add it. Check to see if it one we had created in the past.
				// If no methoddecorator, then keep it, not one ours.
				if (m != null) {
					ImplicitItem implicit = m.getImplicitDecoratorFlag();
					if (implicit != ImplicitItem.NOT_IMPLICIT_LITERAL) {
						m.setEModelElement(null); // Remove it because it was implicit.
						 ((InternalEObject) m).eSetProxyURI(BAD_URI);
						if (implicit == ImplicitItem.IMPLICIT_DECORATOR_AND_FEATURE_LITERAL) {
							itr.remove(); // The operation was implicit too.
							 ((InternalEObject) a).eSetProxyURI(BAD_URI);
						}
						continue;	// At this point we no longer have a method decorator, so go to next.
					}
				}
			}
			
			if (m != null && cd != null) {
				// Now create the appropriate cache entry for this method.
				BeanInfoDecoratorUtility.buildChange(cd, m);
			}
		}
	}

	/**
	 * Fill in the behavior and its decorator using the mthdDesc.
	 */
	protected MethodDecorator calculateOperation(MethodRecord record) {
		return createOperation(record.name, formLongName(record), null, record);
	}

	/**
	 * Fill in the behavior and its decorator using the passed in information.
	 */
	protected MethodDecorator createOperation(String name, String longName, Method method, MethodRecord record) {
		// First find if there is already a behavior of this name and method signature , and if there is, is the MethodDecorator
		// marked to not allow merging in of introspection results.
		HashMap existingLocals = getOperationsMap();
		EOperation oper = null;
		MethodDecorator md = null;
		Object b = null;
		if (name != null)
			b = existingLocals.get(longName);
		else
			b = existingLocals.get(longName);
			
		if (b != null) {
			// If the decorator for this entry says not to merge then return.
			// If there is no decorator, then we will merge. If they didn't want to
			// merge, then they should of created a decorator with no merge on it.
			md = Utilities.getMethodDecorator((EOperation) b);
			if (md != null && !md.isMergeIntrospection())
				return null;
			oper = (EOperation) b;
		}

		// Need to find the method and method id.
		if (method == null) {
			// No method sent, create a proxy to it from the record.
			method = BeanInfoDecoratorUtility.createJavaMethodProxy(record.methodForDescriptor);
		}

		ImplicitItem implicit = md == null ? ImplicitItem.IMPLICIT_DECORATOR_LITERAL : ImplicitItem.NOT_IMPLICIT_LITERAL;
		if (oper == null) {
			// We will create a new MethodProxy.
			oper = BeaninfoFactory.eINSTANCE.createMethodProxy();
			getOperationsList().add(oper);
			implicit = ImplicitItem.IMPLICIT_DECORATOR_AND_FEATURE_LITERAL; 
		}		
		if (name == null)
			name = method.getName();		

		// Now fill it in.
		if (oper instanceof MethodProxy)
			 ((MethodProxy) oper).setMethod(method);
		setMethodID(name, oper);
		oper.setName(name);
		newoperations.add(oper);

		// Now create/fill in the method decorator for it.
		// If there already is one then we
		// will use it. This allows merging with beaninfo.		
		if (md == null) {
			md = BeaninfoFactory.eINSTANCE.createMethodDecorator();
			md.setImplicitDecoratorFlag(implicit);
			oper.getEAnnotations().add(md);
		} else
			BeanInfoDecoratorUtility.clear(md);
		return md;
	}

	/**
	 * @param name
	 * @param oper
	 * 
	 * @since 1.1.0
	 */
	private void setMethodID(String name, EOperation oper) {
		((XMIResource) oper.eResource()).setID(oper, getJavaClass().getName() + BeaninfoJavaReflectionKeyExtension.BEHAVIOR + name);
	}

	private void reflectOperations() {
		// If we are set to mergeSuperTypeBehaviors, then we need to get the super behaviors.
		// This is so that duplicate any from super that we find here. When reflecting we don't
		// allow discovered duplicates unless they are different signatures. So all super operations
		// will be allowed and we will not override them.
		//
		// Kludge: BeanInfo spec doesn't address Interfaces, but some people want to use them.
		// Interfaces can have multiple extends, while the Introspector ignores these for reflection,
		// the truth is most people want these. So we will add them in. But since there could be more than one it
		// gets confusing. We need to look for dups from the super types.
		//
		// Supertypes will never be more than one entry for classes, it is possible to be 0, 1, 2 or more for interfaces.
		Set supers = new HashSet(50);
		BeanDecorator bd = Utilities.getBeanDecorator(getJavaClass());
		if (bd == null || bd.isMergeSuperMethods()) {
			List superTypes = getJavaClass().getESuperTypes();
			if (!superTypes.isEmpty()) {
				int lenST = superTypes.size();
				for (int i=0; i<lenST; i++) {
					List superAll = ((JavaClass) superTypes.get(i)).getEAllOperations();
					int len = superAll.size();
					for (int i1=0; i1<len; i1++) {
						EOperation op = (EOperation) superAll.get(i1);
						supers.add(formLongName(op));
					}
				}
			}
		}

		Iterator itr = getJavaClass().getPublicMethods().iterator();
		while (itr.hasNext()) {
			Method mthd = (Method) itr.next();
			if (mthd.isStatic() || mthd.isConstructor())
				continue; // Statics/constructors don't participate as behaviors	
			String longName = formLongName(mthd);
			// Add if super not already contain it.
			if (!supers.contains(longName))
				createOperation(null, longName, mthd, null);	// Don't pass a name, try to create it by name, only use ID if there is more than one of the same name.
		}
	}

	/*
	 * merge all  the Behaviors(i.e. supertypes)
	 */
	protected BasicEList allOperations() {
		BasicEList jcAllOperations = (BasicEList) getJavaClass().primGetEAllOperations();
		BeaninfoSuperAdapter superAdapter =
			(BeaninfoSuperAdapter) EcoreUtil.getRegisteredAdapter(getJavaClass(), BeaninfoSuperAdapter.class);
		if (jcAllOperations != null) {
			// See if new one required.
			if (superAdapter == null || !superAdapter.isAllOperationsCollectionModified())
				return jcAllOperations;
			// Can't get superadapter, so must not be attached to a resource, so return current list. Or no change required.       		
		}

		UniqueEList.FastCompare allOperations = new UniqueEList.FastCompare() {
			protected Object[] newData(int capacity) {
				return new EOperation[capacity];
			}
		};
		boolean doAllOperations = false;
		synchronized(this) {
			// If we are introspecting, don't do all operatoins because it is an invalid list. Just return empty without reseting the all modified flag.
			doAllOperations = !isDoingAllOperations && !isIntrospecting && isResourceConnected();
			if (doAllOperations)
				isDoingAllOperations = true;
		}

		if (doAllOperations) {
			try {
				EList localOperations = getJavaClass().getEOperations();
				// Kludge: BeanInfo spec doesn't address Interfaces, but some people want to use them.
				// Interfaces can have multiple extends, while the Introspector ignores these for reflection,
				// the truth is most people want these. So we will add them in. But since there could be more than one it
				// gets confusing. We need to look for dups from the super types and still keep order.
				//
				// Supertypes will never be more than one entry for classes, it is possible to be 0, 1, 2 or more for interfaces.
				List superTypes = getJavaClass().getESuperTypes();
				if (!superTypes.isEmpty()) {
					// Now we need to merge in the supers.
					BeanDecorator bd = Utilities.getBeanDecorator(getJavaClass());
					// If there is only one supertype, we can add to the actual events, else we will use the linked hashset so that
					// we don't add possible duplicates (e.g. IA extends IB,IC and IB extends IC. In this case there would be dups
					// because IB would contribute IC's too).
					Collection workingAllOperations = superTypes.size() == 1 ? (Collection) allOperations : new LinkedHashSet(); 
					// We will now merge as directed.
					boolean mergeAll = bd == null || bd.isMergeSuperMethods();
					if (!mergeAll) {
						// we don't to want to merge super operations, but we still need super non-operations.
						int lenST = superTypes.size();
						for (int i=0; i<lenST; i++) {
							List supers = ((JavaClass) superTypes.get(i)).getEAllOperations();
							int len = supers.size();
							for (int i1 = 0; i1 < len; i1++) {
								EOperation o = (EOperation) supers.get(i1);
								MethodDecorator md = Utilities.getMethodDecorator(o);
								if (md == null || (md.getImplicitDecoratorFlag() == ImplicitItem.NOT_IMPLICIT_LITERAL && !md.isMergeIntrospection()))
									workingAllOperations.add(o);
							}
						}
					} else {
						// We want to merge all.
						// BeanInfo could of given us the don't merge list. If the list is empty, then we accept all.
						if (bd != null && bd.eIsSet(BeaninfoPackage.eINSTANCE.getBeanDecorator_NotInheritedMethodNames())) {
							// We were given a list of names.
							// Get the names into a set to create a quick lookup.
							HashSet superSet = new HashSet(bd.getNotInheritedMethodNames());
							
							// Now walk and add in non-bean operations (and bean operations that were explicitly added and not mergeable (i.e. didn't come thru beaninfo)) 
							// and add those not specifically called out by BeanInfo not merge list.
							int lenST = superTypes.size();
							for (int i=0; i<lenST; i++) {
								List supers = ((JavaClass) superTypes.get(i)).getEAllOperations();
								int len = supers.size();
								for (int i1 = 0; i1 < len; i1++) {
									EOperation o = (EOperation) supers.get(i1);
									MethodDecorator md = Utilities.getMethodDecorator(o);
									if (md == null || (md.getImplicitDecoratorFlag() == ImplicitItem.NOT_IMPLICIT_LITERAL && !md.isMergeIntrospection()))
										workingAllOperations.add(o);
									else {
										String longName = formLongName(o);
										if (longName == null || !superSet.contains(longName))
											workingAllOperations.add(o);
									}
								}
							}
						} else {
							int lenST = superTypes.size();
							for (int i=0; i<lenST; i++) {
								workingAllOperations.addAll(((JavaClass) superTypes.get(i)).getEAllOperations());
							}
						}
					}
					if (workingAllOperations != allOperations)
						allOperations.addAll(workingAllOperations);	// Now copy over the ordered super operations.					
				}
				allOperations.addAll(localOperations);				
				ESuperAdapter sa = getJavaClass().getESuperAdapter();
				sa.setAllOperationsCollectionModified(false); // Now built, so reset to not changed.
			} finally {
				synchronized(this) {
					isDoingAllProperties = false;
				}
			}
		}

		allOperations.shrink();
		return new EcoreEList.UnmodifiableEList.FastCompare(
			getJavaClass(),
			EcorePackage.eINSTANCE.getEClass_EAllOperations(),
			allOperations.size(),
			allOperations.data());

	}

	/*
	 * Should only be called from introspect so that flags are correct.
	 */
	private void finalizeEvents(ChangeDescription cd) {
		// Now go through the list and remove those that should be removed.
		Map oldLocals = getEventsMap();
		Iterator itr = getEventsList().iterator();
		while (itr.hasNext()) {
			JavaEvent a = (JavaEvent) itr.next();
			EventSetDecorator e = Utilities.getEventSetDecorator(a);
			Object aOld = oldLocals.get(a.getName());
			if (aOld != null && aOld != Boolean.FALSE) {
				// A candidate for removal. It was in the old list and it was not processed.
				if (e != null) {
					ImplicitItem implicit = e.getImplicitDecoratorFlag();
					if (implicit != ImplicitItem.NOT_IMPLICIT_LITERAL) {
						e.setEModelElement(null); // Remove it because it was implicit.
						((InternalEObject) e).eSetProxyURI(BAD_URI);
						if (implicit == ImplicitItem.IMPLICIT_DECORATOR_AND_FEATURE_LITERAL) {
							itr.remove(); // The feature was implicit too.
							((InternalEObject) a).eSetProxyURI(BAD_URI);
						}
						continue;	// At this point we don't have a decorator any more, so don't bother going on.
					}
				}
			}
			
			if (e != null && cd != null) {
				// Now create the appropriate cache entry for this event.
				BeanInfoDecoratorUtility.buildChange(cd, e);
			}
		}
	}

	/**
	 * Fill in the event and its decorator using the eventDesc.
	 */
	protected EventSetDecorator calculateEvent(EventSetRecord record) {
		return createEvent(record.name);
	}

	/**
	 * Fill in the event and its decorator using the passed in information.
	 */
	protected EventSetDecorator createEvent(String name) {
		// First find if there is already an event of this name, and if there is, is the EventSetDecorator
		// marked to not allow merging in of introspection results.
		HashMap existingLocals = getEventsMap();
		JavaEvent event = null;
		EventSetDecorator ed = null;
		Object b = existingLocals.get(name);
		if (Boolean.FALSE == b)
			return null; // We've already processed this event, can't process it again.			
		if (b != null) {
			// We've found one of the same event. Whether we modify it or use it as is, we put in a
			// special dummy in its place. That marks that we've already processed it and accepted it.
			existingLocals.put(name, Boolean.FALSE);

			// If the decorator for this entry says not to merge then return.
			// If there is no decorator, then we will merge. If they didn't want to
			// merge, then they should of created a decorator with no merge on it.
			ed = Utilities.getEventSetDecorator((JavaEvent) b);
			if (ed != null && !ed.isMergeIntrospection())
				return null;
			event = (JavaEvent) b;
		}
		
		ImplicitItem implicit = ed == null ? ImplicitItem.IMPLICIT_DECORATOR_LITERAL : ImplicitItem.NOT_IMPLICIT_LITERAL;
		if (event == null) {
			// We will create a new Event.
			event = BeaninfoFactory.eINSTANCE.createBeanEvent();
			getEventsList().add(event);
			implicit = ImplicitItem.IMPLICIT_DECORATOR_AND_FEATURE_LITERAL; // Can't have an implicit feature but explicit decorator.
		}

		setEventID(name, event);
		event.setName(name);

		// Now create in the event decorator for it.
		// If there already is one then we
		// will use it. This allows merging with beaninfo.		
		if (ed == null) {
			ed = BeaninfoFactory.eINSTANCE.createEventSetDecorator();
			ed.setImplicitDecoratorFlag(implicit);
			event.getEAnnotations().add(ed);
		} else
			BeanInfoDecoratorUtility.clear(ed);
		return ed;
	}

	/**
	 * @param name
	 * @param event
	 * 
	 * @since 1.1.0
	 */
	private void setEventID(String name, JavaEvent event) {
		// Now fill it in.
		((XMIResource) event.eResource()).setID(event, getJavaClass().getName() + BeaninfoJavaReflectionKeyExtension.EVENT + name);
	}

	/**
	 * Reflect the events. This requires going through local public methods and creating an 
	 * event for the discovered events.
	 */
	protected void reflectEvents() {
		// If we are set to mergeSuperTypeEvents, then we need to get the super events.
		// This is so that duplicate any from super that we find here. When reflecting we don't
		// allow discovered duplicates.
		//
		// Kludge: BeanInfo spec doesn't address Interfaces, but some people want to use them.
		// Interfaces can have multiple extends, while the Introspector ignores these for reflection,
		// the truth is most people want these. So we will add them in. But since there could be more than one it
		// gets confusing. We need to look for dups from the super types.
		//
		// Supertypes will never be more than one entry for classes, it is possible to be 0, 1, 2 or more for interfaces.
		Set supers = new HashSet(50);
		BeanDecorator bd = Utilities.getBeanDecorator(getJavaClass());
		if (bd == null || bd.isMergeSuperEvents()) {
			List superTypes = getJavaClass().getESuperTypes();
			if (!superTypes.isEmpty()) {
				int lenST = superTypes.size();
				for (int i=0; i<lenST; i++) {
					List superAll = ((JavaClass) superTypes.get(i)).getAllEvents();
					int len = superAll.size();
					for (int i1=0; i1<len; i1++) {
						JavaEvent se = (JavaEvent) superAll.get(i1);
						supers.add(se.getName());
					}
				}
			}
		}

		HashMap events = new HashMap();
		eventListenerClass = (JavaClass) JavaRefFactory.eINSTANCE.reflectType("java.util.EventListener", getJavaClass()); // Initialize, needed for building eventinfos. //$NON-NLS-1$
		tooManyExceptionClass = (JavaClass) JavaRefFactory.eINSTANCE.reflectType("java.util.TooManyListenersException", getJavaClass()); // Initialize, needed for building eventinfos. //$NON-NLS-1$
		Iterator itr = getJavaClass().getPublicMethods().iterator();
		while (itr.hasNext()) {
			Method mthd = (Method) itr.next();
			if (mthd.isStatic() || mthd.isConstructor())
				continue; // Statics/constructors don't participate in events.
			String key = validEventAdder(mthd);
			if (key != null) {
				EventInfo eventInfo = (EventInfo) events.get(key);
				if (eventInfo == null) {
					eventInfo = new EventInfo();
					eventInfo.setAdder(mthd);
					events.put(key, eventInfo);
				} else
					eventInfo.setAdder(mthd);
			} else {
				key = validEventRemove(mthd);
				if (key != null) {
					EventInfo eventInfo = (EventInfo) events.get(key);
					if (eventInfo == null) {
						eventInfo = new EventInfo();
						eventInfo.setRemover(mthd);
						events.put(key, eventInfo);
					} else
						eventInfo.setRemover(mthd);
				}
			}
		}

		eventListenerClass = null; // No longer need it.

		// Now actually create the events.
		HashSet eventNames = new HashSet(events.size()); // Set of found event names, to prevent duplicates
		Iterator evtItr = events.entrySet().iterator();
		while (evtItr.hasNext()) {
			Map.Entry eventMap = (Map.Entry) evtItr.next();
			EventInfo ei = (EventInfo) eventMap.getValue();
			if (ei.isValidInfo()) {
				String eventName = getEventName((String) eventMap.getKey());
				if (eventNames.contains(eventName))
					continue;	// Aleady created it. (Note: Introspector actually takes last one over previous dups, but the order is totally undefined, so choosing first is just as good or bad.

				if (supers.contains(eventName))
					continue; // Don't override a super event.

				if (ei.createEvent(eventName))
					eventNames.add(eventName); // It was validly created.
			}
		}

		tooManyExceptionClass = null; // No longer need it.
	}

	/**
	 * merge all the Events (i.e. supertypes)
	 */
	protected EList allEvents() {

		EList jcAllEvents = getJavaClass().getAllEventsGen();
		BeaninfoSuperAdapter superAdapter =
			(BeaninfoSuperAdapter) EcoreUtil.getRegisteredAdapter(getJavaClass(), BeaninfoSuperAdapter.class);
		if (jcAllEvents != null) {
			// See if new one required.
			if (superAdapter == null || !superAdapter.isAllEventsCollectionModified())
				return jcAllEvents;
			// Can't get superadapter, so must not be attached to a resource, so return current list. Or no change required.       		
		}

		UniqueEList.FastCompare allEvents = new UniqueEList.FastCompare() {
			protected Object[] newData(int capacity) {
				return new JavaEvent[capacity];
			}
		};
		
		boolean doAllEvents = false;
		synchronized(this) {
			// If we are introspecting, don't do all properties because it is an invalid list. Just return empty without reseting the all modified flag.
			doAllEvents = !isDoingAllEvents && !isIntrospecting && isResourceConnected();
			if (doAllEvents)
				isDoingAllEvents = true;
		}

		if (doAllEvents) {
			try {
				EList localEvents = getJavaClass().getEvents();
				// Kludge: BeanInfo spec doesn't address Interfaces, but some people want to use them.
				// Interfaces can have multiple extends, while the Introspector ignores these for reflection,
				// the truth is most people want these. So we will add them in. But since there could be more than one it
				// gets confusing. We need to look for dups from the super types and still keep order.
				//
				// Supertypes will never be more than one entry for classes, it is possible to be 0, 1, 2 or more for interfaces.
				List superTypes = getJavaClass().getESuperTypes();
				if (!superTypes.isEmpty()) {
					// Now we need to merge in the supers.
					BeanDecorator bd = Utilities.getBeanDecorator(getJavaClass());
					// If there is only one supertype, we can add to the actual events, else we will use the linked hashset so that
					// we don't add possible duplicates (e.g. IA extends IB,IC and IB extends IC. In this case there would be dups
					// because IB would contribute IC's too).
					Collection workingAllEvents = superTypes.size() == 1 ? (Collection) allEvents : new LinkedHashSet(); 
					// We will now merge as directed.
					boolean mergeAll = bd == null || bd.isMergeSuperEvents();
					if (!mergeAll) {
						// we don't to want to merge super events, but we still need super non-events or explicit ones.
						int lenST = superTypes.size();
						for (int i=0; i<lenST; i++) {
							List supers = ((JavaClass) superTypes.get(i)).getAllEvents();
							int len = supers.size();
							for (int i1 = 0; i1 < len; i1++) {
								JavaEvent e = (JavaEvent) supers.get(i1);
								EventSetDecorator ed = Utilities.getEventSetDecorator(e);
								if (ed == null || (ed.getImplicitDecoratorFlag() == ImplicitItem.NOT_IMPLICIT_LITERAL && !ed.isMergeIntrospection()))
									workingAllEvents.add(e);
							}
						}
					} else {
						// We want to merge all.					
						// BeanInfo has given us the not merge list. If the list is empty, then we accept all.
						if (bd != null && bd.eIsSet(BeaninfoPackage.eINSTANCE.getBeanDecorator_NotInheritedEventNames())) {
							// We were given a list of names.
							// Get the names into a set to create a quick lookup.
							HashSet superSet = new HashSet(bd.getNotInheritedEventNames());
							
							// Now walk and add in non-bean events (and bean events that were explicitly added and not mergeable (i.e. didn't come thru beaninfo)) 
							// and add those not specifically called out by BeanInfo.
							int lenST = superTypes.size();
							for (int i=0; i<lenST; i++) {
								List supers = ((JavaClass) superTypes.get(i)).getAllEvents();
								int len = supers.size();
								for (int i1 = 0; i1 < len; i1++) {
									JavaEvent e = (JavaEvent) supers.get(i1);
									EventSetDecorator ed = Utilities.getEventSetDecorator(e);
									if (ed == null || (ed.getImplicitDecoratorFlag() == ImplicitItem.NOT_IMPLICIT_LITERAL && !ed.isMergeIntrospection()) || !superSet.contains(ed.getName()))
										workingAllEvents.add(e);
								}
							}
						} else {
							// BeanInfo called out that all super events should be added, or no beaninfo.
							int lenST = superTypes.size();
							for (int i=0; i<lenST; i++) {
								workingAllEvents.addAll(((JavaClass) superTypes.get(i)).getAllEvents());
							}
						}
					}
					if (workingAllEvents != allEvents)
						allEvents.addAll(workingAllEvents);	// Now copy over the ordered super events.
				}
				allEvents.addAll(localEvents);				
				superAdapter.setAllEventsCollectionModified(false); // Now built, so reset to not changed.
			} finally {
				synchronized (this) {
					isDoingAllEvents = false;
				}
			}
		}

		if (allEvents.isEmpty())
			return ECollections.EMPTY_ELIST;
		else {
			allEvents.shrink();
			return new EcoreEList.UnmodifiableEList.FastCompare(
				getJavaClass(),
				JavaRefPackage.eINSTANCE.getJavaClass_AllEvents(),
				allEvents.size(),
				allEvents.data());
		}

	}

	private JavaClass eventListenerClass, // Event Listener class. Needed for validation.
	tooManyExceptionClass; // Too many listeners exception.

	/*
	 * Pass in the key, it will be used to form the name.
	 */
	protected String getEventName(String key) {
		return key.substring(0, key.indexOf(':'));
	}

	/*	
	 * Answers event key if valid, null if not valid.
	 */
	protected String validEventAdder(Method method) {
		String name = method.getName();
		if (!name.startsWith("add") || !name.endsWith("Listener")) //$NON-NLS-1$ //$NON-NLS-2$
			return null; // Not valid format for an add listener name.

		List parms = method.getParameters();
		if (parms.size() != 1)
			return null; // Invalid - improper number of parms.

		EClassifier returnType = method.getReturnType();
		if (returnType == null || !returnType.getName().equals("void")) //$NON-NLS-1$
			return null; // Invalid - must be void return type.

		EClassifier parmType = ((JavaParameter) parms.get(0)).getEType();
		if (!BeaninfoClassAdapter.this.eventListenerClass.isAssignableFrom(parmType))
			return null; // Parm must be inherit from EventListener

		// This is a unique containing event name and listener type
		// This is so we can have a unique key for two events with the same
		// name but different listener type. (This matches Introspector so that we aren't
		// coming up with different results.
		return java.beans.Introspector.decapitalize(name.substring(3, name.length() - 8))
			+ ':'
			+ ((JavaHelpers) parmType).getQualifiedName();
	}

	/*
	 * Answers event key if valid, null if not valid.
	 */
	protected String validEventRemove(Method method) {
		String name = method.getName();
		if (!name.startsWith("remove") || !name.endsWith("Listener")) //$NON-NLS-1$ //$NON-NLS-2$
			return null; // Not valid format for a remove listener name.

		List parms = method.getParameters();
		if (parms.size() != 1)
			return null; // Invalid - improper number of parms.

		EClassifier returnType = method.getReturnType();
		if (returnType == null || !returnType.getName().equals("void")) //$NON-NLS-1$
			return null; // Invalid - must be void return type.

		EClassifier parmType = ((JavaParameter) parms.get(0)).getEType();
		if (!BeaninfoClassAdapter.this.eventListenerClass.isAssignableFrom(parmType))
			return null; // Parm must be inherit from EventListener

		// This is a unique containing event name and listener type
		// This is so we can have a unique key for two events with the same
		// name but different listener type. (This matches Introspector so that we aren't
		// coming up with different results).
		return java.beans.Introspector.decapitalize(name.substring(6, name.length() - 8))
			+ ':'
			+ ((JavaHelpers) parmType).getQualifiedName();
	}

	public boolean isDefaultBound() {
		if (defaultBound == null) {
			// Haven't yet decided on it.
			Iterator methods = getJavaClass().getPublicMethods().iterator();
			boolean foundAdd = false, foundRemove = false;
			while (methods.hasNext() && (!foundAdd || !foundRemove)) {
				Method method = (Method) methods.next();
				if ("addPropertyChangeListener".equals(method.getName())) { //$NON-NLS-1$
					List parms = method.getParameters();
					if (parms.size() == 1) {
						JavaParameter parm = (JavaParameter) parms.get(0);
						if ("java.beans.PropertyChangeListener".equals(((JavaHelpers) parm.getEType()).getQualifiedName())) { //$NON-NLS-1$
							foundAdd = true;
							continue;
						}
					}
				} else if ("removePropertyChangeListener".equals(method.getName())) { //$NON-NLS-1$
					List parms = method.getParameters();
					if (parms.size() == 1) {
						JavaParameter parm = (JavaParameter) parms.get(0);
						if ("java.beans.PropertyChangeListener".equals(((JavaHelpers) parm.getEType()).getQualifiedName())) { //$NON-NLS-1$
							foundRemove = true;
							continue;
						}
					}
				}
			}

			defaultBound = (foundAdd && foundRemove) ? Boolean.TRUE : Boolean.FALSE;
		}
		return defaultBound.booleanValue();
	}

	private class EventInfo {
		
		public Method addListenerMethod;
		public Method removeListenerMethod;

		public void setAdder(Method addMethod) {
			addListenerMethod = addMethod;
		}

		public void setRemover(Method removeMethod) {
			removeListenerMethod = removeMethod;
		}

		// Answer whether this is a valid event info.
		public boolean isValidInfo() {
			return (addListenerMethod != null && removeListenerMethod != null);
		}

		public boolean createEvent(String name) {
			EventSetDecorator ed = BeaninfoClassAdapter.this.createEvent(name);
			if (ed == null)
				return false; // Reflection not wanted.


			// See if unicast.
			boolean unicast = false;
			List exceptions = addListenerMethod.getJavaExceptions();
			int len = exceptions.size();
			for(int i=0; i<len; i++) {
				if (exceptions.get(i) == BeaninfoClassAdapter.this.tooManyExceptionClass) {
					unicast = true;
					break;
				}
			}
			// We'll let listener methods get retrieved dynamically when needed.
			BeanInfoDecoratorUtility.setProperties(ed, addListenerMethod, removeListenerMethod, unicast, (JavaClass) ((JavaParameter) addListenerMethod.getParameters().get(0)).getEType());
			return true;
		}

	}

	/**
	 * Mark this factory as the stale factory.
	 */
	public void markStaleFactory(ProxyFactoryRegistry stale) {
		if (staleFactory == null) {
			// It's not stale so make it stale.
			// So that next access will re-introspect
			defaultBound = null; // So query on next request.
			staleFactory = new WeakReference(stale);

			// Need to mark the esuperadapter that things have changed so that any 
			// subtype will know to reuse the parent for anything that requires knowing parent info.
			Adapter a = EcoreUtil.getExistingAdapter(getTarget(), ESuperAdapter.class);
			// Simulate that this objects super has changed. This will make all subclasses
			// think about the super has changed and next retrieving anything that involves the
			// super will cause a rebuild to occur.
			Notification note =
				new ENotificationImpl((InternalEObject) getTarget(), Notification.SET, EcorePackage.ECLASS__ESUPER_TYPES, null, null);
			if (a != null)
				a.notifyChanged(note);
			// Do the same with BeaninfoSuperAdapter so that events also will be rebuilt.
			a = EcoreUtil.getExistingAdapter(getTarget(), BeaninfoSuperAdapter.ADAPTER_KEY);
			if (a != null)
				a.notifyChanged(note);
			synchronized (this) {
				needsIntrospection = true;
			}
		}
	}

	/**
	 * Form a longname for the addkey function.
	 */
	private String formLongName(EOperation feature) {
		Method mthd = null;
		if (feature instanceof Method)
			mthd = (Method) feature;
		else if (feature instanceof MethodProxy)
			mthd = ((MethodProxy) feature).getMethod();
		else
			return null; // Don't know what it is.

		StringBuffer longName = new StringBuffer(100);
		longName.append(feature.getName()); // Feature Name
		longName.append(':');
		longName.append(mthd.getName()); // Method Name
		longName.append('(');
		List p = mthd.getParameters();
		for (int i = 0; i < p.size(); i++) {
			JavaParameter parm = (JavaParameter) p.get(i);
			if (i>0)
				longName.append(',');
			longName.append(parm.getJavaType().getQualifiedName());
		}

		return longName.toString();
	}
	
	/*
	 * More than one operation can have the same name. To identify them uniquely, the long name is created,
	 * which is formed from the name and the method signature.
	 */
	private String formLongName(MethodRecord record) {
		StringBuffer longName = new StringBuffer(100);
		longName.append(record.name); // Feature Name
		longName.append(':');
		longName.append(record.methodForDescriptor.methodName); // Method Name
		longName.append('(');
		String[] p = record.methodForDescriptor.parameterTypeNames;
		if (p != null)
			for (int i = 0; i < p.length; i++) {
				if (i>0)
					longName.append(',');
				longName.append(MapJNITypes.getFormalTypeName(p[i]));
			}

		return longName.toString();
	}
	/**
	 * @see org.eclipse.emf.common.notify.Adapter#notifyChanged(Notification)
	 */
	public void notifyChanged(Notification msg) {
		// In case of removing adapter, make sure we are first removed from the factory so it doesn't know about us anymore.
		if (msg.getEventType() == Notification.REMOVING_ADAPTER)
			getAdapterFactory().removeAdapter(this);
	}

	/**
	 * @see java.lang.Object#toString()
	 */
	public String toString() {
		return super.toString() + '(' + (getJavaClass() != null ? getJavaClass().getQualifiedName() : "?") + ')'; //$NON-NLS-1$
	}


}
