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


 */

import java.io.FileNotFoundException;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.text.MessageFormat;
import java.util.*;
import java.util.logging.Level;
import java.util.regex.Pattern;

import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.emf.common.notify.*;
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.*;
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.*;
import org.eclipse.emf.ecore.xmi.PackageNotFoundException;
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.beaninfo.core.BeanInfoCacheController.ClassEntry;
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.internal.impl.JavaClassImpl;
import org.eclipse.jem.util.TimerTests;
import org.eclipse.jem.util.logger.proxy.Logger;

/**
 * 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$
	
	
	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,
		CLEAR_EXTENSIONS = 3;
	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 (Exception e) {
				BeaninfoPlugin.getPlugin().getLogger().log(
					new Status(
						IStatus.WARNING,
						BeaninfoPlugin.getPlugin().getBundle().getSymbolicName(),
						0,
						MessageFormat.format(
							BeanInfoAdapterMessages.INTROSPECT_FAILED_EXC_, 
							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));
			ClassEntry superCE = bca.getClassEntry();
			// If super is defined and out of date don't use cache. If super is undefined and super modification stamp is not super_undefined,
			// then that means it was defined at time of cache and now not defined, so don't use cache.
			if (superCE != null) {
				if (superCE.getModificationStamp() != classEntry.getSuperModificationStamp())
					return false; // Out-of-date wrt/super.
			} else if (classEntry.getSuperModificationStamp() != ClassEntry.SUPER_UNDEFINED_MODIFICATION_STAMP)
				return false;	// was previously defined, and now undefined, so out of date.
			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.]
					
					superCE = getBeaninfoClassAdapter(javaClass).getClassEntry();
					if (superCE != null) {
						if (superCE.getModificationStamp() != iStamp[indx])
							return false; // Out-of-date wrt/interface.
					} else if (iStamp[indx] != ClassEntry.SUPER_UNDEFINED_MODIFICATION_STAMP)
						return false;	// was previously defined, and now undefined, so out of date.
				}
			}
		}
		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 || retrievedExtensionDocument == CLEAR_EXTENSIONS) {
						// 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.
						// Or we've been asked to clear all.
						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 || retrievedExtensionDocument == CLEAR_EXTENSIONS) {
						// 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).
						// Or we had a Clean requested and need to clear the extensions too.
						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(
										MessageFormat.format(
												BeanInfoAdapterMessages.INTROSPECT_FAILED_EXC_, 
												new Object[] { getJavaClass().getJavaName(), ""}), //$NON-NLS-1$
										Level.WARNING);
									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 {
											BeaninfoProxyConstants proxyConstants = getProxyConstants();
											if (proxyConstants != null) {
												beaninfo = proxyConstants.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.INTROSPECT_FAILED_EXC_, new Object[] { //$NON-NLS-1$
																	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.INTROSPECT_FAILED_EXC_, new Object[] { //$NON-NLS-1$
																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.INTROSPECT_FAILED_EXC_, new Object[] { 
															getJavaClass().getJavaName(),
															BeanInfoAdapterMessages.BeaninfoClassAdapter_ClassNotFound}), 
															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 {
							new ExtensionDocApplies(null, rset, jc, null).run(cacheRes);
						} 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 static final URI ROOT_URI = URI.createGenericURI(BeaninfoPlugin.ROOT_SCHEMA, BeaninfoPlugin.ROOT_OPAQUE, null);
	private static final String ROOT_FRAGMENT = "//@root"; //$NON-NLS-1$
	private static final Pattern FRAGMENT_SPLITTER = Pattern.compile("/"); //$NON-NLS-1$
	
	// TODO This is to make event util optional. This should be removed entirely with 1.3 when event util goes away.
	private static boolean RETRIEVED_EVENT_METHODS;
	private static Object EVENT_FACTORY_INSTANCE;
	private static java.lang.reflect.Method CREATE_EVENT_UTIL_METHOD;
	private static java.lang.reflect.Method DO_FORWARD_EVENTS_METHOD;
	
	private static boolean isEventUtilLoaded() {
		if (!RETRIEVED_EVENT_METHODS) {
			try {
				Class eventFactoryClass = Class.forName("com.ibm.etools.emf.event.EventFactory");
				Field eventFactoryField = eventFactoryClass.getField("eINSTANCE");
				Object eventFactoryInstance = eventFactoryField.get(null);
				java.lang.reflect.Method createEventMethod = eventFactoryClass.getMethod("createEventUtil", new Class[] {Notifier.class, ResourceSet.class});
				Class eventUtilClass = createEventMethod.getReturnType();
				java.lang.reflect.Method doForwardEventsMethod = eventUtilClass.getMethod("doForwardEvents", new Class[] {List.class});
				EVENT_FACTORY_INSTANCE = eventFactoryInstance;
				CREATE_EVENT_UTIL_METHOD = createEventMethod;
				DO_FORWARD_EVENTS_METHOD = doForwardEventsMethod;
			} catch (ClassNotFoundException e) {
			} catch (SecurityException e) {
			} catch (NoSuchFieldException e) {
			} catch (IllegalArgumentException e) {
			} catch (IllegalAccessException e) {
			} catch (NoSuchMethodException e) {
			}
			RETRIEVED_EVENT_METHODS = true;
		} 
		return EVENT_FACTORY_INSTANCE != 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 if (e.exception() instanceof PackageNotFoundException && ((PackageNotFoundException) e.exception()).getMessage().indexOf("event.xmi") != -1) {
						if (!RETRIEVED_EVENT_METHODS) {
							BeaninfoPlugin.getPlugin().getLogger().log(new Status(IStatus.WARNING, BeaninfoPlugin.PI_BEANINFO_PLUGINID, 0, "An old style override file using the com.ibm.event format was found, but com.ibm.event was not installed. The first such file is "+uri, null)); //$NON-NLS-1$
							RETRIEVED_EVENT_METHODS = true;	// Mark we've retrieved. This is ok because if event is missing here, it will be missing for retrieve too.
						}
					} else {
						BeaninfoPlugin.getPlugin().getLogger().log(new Status(IStatus.WARNING, BeaninfoPlugin.PI_BEANINFO_PLUGINID, 0, "Error loading file\"" + uri + "\"", 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\"" + uri + "\"", 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 {
				EList contents = overrideRes.getContents();
				if (overridesCache != null) {
					// TODO Until https://bugs.eclipse.org/bugs/show_bug.cgi?id=109169 is fixed, we need our own Copier.
					EcoreUtil.Copier copier = new EcoreUtil.Copier() {

						private static final long serialVersionUID = 1L;

						protected void copyReference(EReference eReference, EObject eObject, EObject copyEObject) {
							if (eObject.eIsSet(eReference)) {
								if (eReference.isMany()) {
									List source = (List) eObject.eGet(eReference);
									InternalEList target = (InternalEList) copyEObject.eGet(getTarget(eReference));
									if (source.isEmpty()) {
										target.clear();
									} else {
										boolean isBidirectional = eReference.getEOpposite() != null;
										int index = 0;
										for (Iterator k = ((EcoreEList) source).basicIterator(); k.hasNext();) {
											Object referencedEObject = k.next();
											Object copyReferencedEObject = get(referencedEObject);
											if (copyReferencedEObject == null) {
												if (!isBidirectional) {
													target.addUnique(index, referencedEObject);
													++index;
												}
											} else {
												if (isBidirectional) {
													int position = target.indexOf(copyReferencedEObject);
													if (position == -1) {
														target.addUnique(index, copyReferencedEObject);
													} else if (index != position) {
														target.move(index, copyReferencedEObject);
													}
												} else {
													target.addUnique(index, copyReferencedEObject);
												}
												++index;
											}
										}
									}
								} else {
									Object referencedEObject = eObject.eGet(eReference, false);
									if (referencedEObject == null) {
										copyEObject.eSet(getTarget(eReference), null);
									} else {
										Object copyReferencedEObject = get(referencedEObject);
										if (copyReferencedEObject == null) {
											if (eReference.getEOpposite() == null) {
												copyEObject.eSet(getTarget(eReference), referencedEObject);
											}
										} else {
											copyEObject.eSet(getTarget(eReference), copyReferencedEObject);
										}
									}
								}
							}
						}
					};
					
					// We fixup the CD first so that when serialized it will be to the correct object already. Simplifies apply later.
					Iterator itr = contents.iterator();
					while (itr.hasNext()) {
						Object o = itr.next();
						if (o instanceof ChangeDescription) {
							fixupCD((ChangeDescription) o);
						}
					}

				    Collection result = copier.copyAll(contents);
				    copier.copyReferences();
					overridesCache.addAll(result);	// Make a copy for the override cache to be used next time needed.
				}
				
				if (!contents.isEmpty()) {
					// TODO It could be either the old event model or the new ChangeDescription. When we remove Event Model we need to remove
					// the test. This could be the override cache too, so we must apply the contents in the order they are in the resource.
					try {
						List events = null;
						Object[] eventsParm = null;
						Iterator itr = contents.iterator();
						while (itr.hasNext()) {
							Object o = itr.next();
							if (o instanceof ChangeDescription) {
								ChangeDescription cd = (ChangeDescription) o;
								fixupCD(cd);
								cd.apply();
							} else if (isEventUtilLoaded()) {
								if (events == null) {
									events = new ArrayList(1);
									events.add(null); // EventUtil needs a list, but we will be calling one by one. So just reuse this list.
									eventsParm = new Object[] { events};
								}								
								// It is the old format.
								events.set(0, o);
								try {
									Object util = CREATE_EVENT_UTIL_METHOD.invoke(EVENT_FACTORY_INSTANCE, new Object[] {mergeIntoJavaClass, rset});
									DO_FORWARD_EVENTS_METHOD.invoke(util, eventsParm);
								} catch (IllegalArgumentException e) {
								} catch (IllegalAccessException e) {
								} catch (InvocationTargetException e) {
									BeaninfoPlugin.getPlugin().getLogger().log(new Status(IStatus.WARNING, BeaninfoPlugin.PI_BEANINFO_PLUGINID, 0, "Error processing file\"" + overrideRes.getURI() + "\"", e.getCause())); //$NON-NLS-1$ //$NON-NLS-2$
								}
							}
						}
					} finally {
						uninstallRootResource();
					}						
				}
			} 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$						
			}
		}
		
		/*
		 * fix it up so that references to "X:ROOT#//@root" are replaced with reference to the javaclass.
		 */
		private void fixupCD(ChangeDescription cd) {
			EStructuralFeature keyFeature = ChangePackage.eINSTANCE.getEObjectToChangesMapEntry_Key();
			Iterator changes = cd.getObjectChanges().iterator();
			while (changes.hasNext()) {
				EObject entry = (EObject) changes.next();
				EObject key = (EObject) entry.eGet(keyFeature, false);
				if (key != null && key.eIsProxy()) {
					// See if it is our special.
					URI uri = ((InternalEObject) key).eProxyURI();
					String rootFrag = uri.fragment();
					if (BeaninfoPlugin.ROOT_SCHEMA.equals(uri.scheme()) && BeaninfoPlugin.ROOT_OPAQUE.equals(uri.opaquePart()) && (rootFrag != null && rootFrag.startsWith(ROOT_FRAGMENT))) {
						// It is one of ours. Get the fragment, remove the leading //root and append to the end of the
						// uri from the java class itself.
						if (rootFrag.length() <= ROOT_FRAGMENT.length())
							entry.eSet(keyFeature, mergeIntoJavaClass);	// No sub-path, so just the java class.
						else {
							// There is a sub-path below the java class that is needed. Need to walk down the path.
							String[] path = FRAGMENT_SPLITTER.split(rootFrag.substring(ROOT_FRAGMENT.length()+1));
							InternalEObject newKey = (InternalEObject) mergeIntoJavaClass;
							for (int i = 0; newKey != null && i < path.length; i++) {
								newKey = (InternalEObject) newKey.eObjectForURIFragmentSegment(path[i]);
							}
							if (newKey != null)
								entry.eSet(keyFeature, newKey);
						}
					}
				}
			}
		}
		
		/*
		 * Uninstall the fake root resource. This must be called after installRootResource has been called. So must use try/finally. 
		 * 
		 * 
		 * @since 1.2.0
		 */
		private void uninstallRootResource() {
			Resource root = rset.getResource(ROOT_URI, false);
			if (root != null)
				rset.getResources().remove(root);
		}
	}
	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() {
			/**
			 * Comment for <code>serialVersionUID</code>
			 * 
			 * @since 1.1.0
			 */
			private static final long serialVersionUID = 1L;

			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.
		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 (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, 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, 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);

		// 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,
					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() {
			/**
			 * Comment for <code>serialVersionUID</code>
			 * 
			 * @since 1.1.0
			 */
			private static final long serialVersionUID = 1L;

			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) {
					isDoingAllOperations = 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() {
			/**
			 * Comment for <code>serialVersionUID</code>
			 * 
			 * @since 1.1.0
			 */
			private static final long serialVersionUID = 1L;

			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.
		// Note. The Bean specs only state that it should be "add<ListenerType>" but the
		// introspector implicitly adds an additional constraint in that the listener type
		// should end with "Listener". If it doesn't the introspector would actually throw
		// an index out of bounds. We'll just ignore such methods.

		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

		// Beans introspector also requires that the "listener" part of the name be a
		// suffix of the type name. So if the type name was "ISomeListener" then
		// the method name must be "addSomeListener" (actually "addomeListener"
		// would also be valid according to the introspector!).
		// This allows the type to be an interface using the "I" convention while not
		// requiring the "I" to be in the name of the event.		
		if (!parmType.getName().endsWith(name.substring(3)))
			return null;	// It is not "add{ListenerType}".

		// 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.
		// Note. The Bean specs only state that it should be "add<ListenerType>" but the
		// introspector implicitly adds an additional constraint in that the listener type name
		// should end with "Listener". If it doesn't the introspector would actually throw
		// an index out of bounds. We'll just ignore such methods.
		

		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

		// Beans introspector also requires that the "listener" part of the name be a
		// suffix of the type name. So if the type name was "ISomeListener" then
		// the method name must be "removeSomeListener" (actually "removeomeListener"
		// would also be valid according to the introspector!).
		// This allows the type to be an interface using the "I" convention while not
		// requiring the "I" to be in the name of the event.
		if (!parmType.getName().endsWith(name.substring(6)))
			return null;	// It is not "add{ListenerType}".

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

	}

	/**
	 * Marh the factory as stale, but leave the overrides alone. They are not stale.
	 * @param stale
	 * 
	 * @since 1.1.0.1
	 */
	public void markStaleFactory(ProxyFactoryRegistry stale) {
		markStaleFactory(stale, false);
	}
	
	/**
	 * Mark this factory as the stale factory.
	 * 
	 * @param clearOverriddes clear the overrides too. They are stale.
	 */
	public void markStaleFactory(ProxyFactoryRegistry stale, boolean clearOverriddes) {
		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;
				if (clearOverriddes) {
					retrievedExtensionDocument = CLEAR_EXTENSIONS;
					if (classEntry != null) {
						classEntry.markDeleted();
						classEntry = null; // Get a new one next time.
					}
				}
			}
		}
	}

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


}
