/*******************************************************************************
 * 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;
/*
 *  $RCSfile: BeaninfoClassAdapter.java,v $
 *  $Revision: 1.53 $  $Date: 2006/05/23 15:43:06 $ 
 */

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 (Throwable 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) {
					isDoingAllProperties = false;
				}
			}
		}

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

	}

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

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

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

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

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

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

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

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

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

		eventListenerClass = null; // No longer need it.

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

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

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

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

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

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

		UniqueEList.FastCompare allEvents = new UniqueEList.FastCompare() {
			/**
			 * 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$
	}


}
