### Eclipse Workspace Patch 1.0
#P org.eclipse.jst.jsf.common
Index: src/org/eclipse/jst/jsf/common/internal/provisional/util/JDTBeanProperty.java
===================================================================
RCS file: /cvsroot/webtools/org.eclipse.jsf/components/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/internal/provisional/util/JDTBeanProperty.java,v
retrieving revision 1.3
diff -u -r1.3 JDTBeanProperty.java
--- src/org/eclipse/jst/jsf/common/internal/provisional/util/JDTBeanProperty.java 7 Apr 2007 00:27:43 -0000 1.3
+++ src/org/eclipse/jst/jsf/common/internal/provisional/util/JDTBeanProperty.java 10 Apr 2007 15:07:21 -0000
@@ -30,6 +30,11 @@
protected final IType _type;
/**
+ * cached type signature, created on first request
+ */
+ private String _typeSignature = null;
+
+ /**
* @param type
*/
protected JDTBeanProperty(IType type)
@@ -114,17 +119,19 @@
*/
public String getTypeSignature()
{
- try
- {
- String unResolvedSig = getUnresolvedType();
- final String signature = TypeUtil.resolveTypeSignature(_type, unResolvedSig);
- return signature;
- }
- catch (JavaModelException jme)
- {
- JSFCommonPlugin.log(jme, "Error resolving bean property type signature"); //$NON-NLS-1$
- return null;
+ if (_typeSignature == null) {
+ try
+ {
+ String unresolvedSig = getUnresolvedType();
+ _typeSignature = TypeUtil.resolveTypeSignature(_type, unresolvedSig);
+ }
+ catch (JavaModelException jme)
+ {
+ JSFCommonPlugin.log(jme, "Error resolving bean property type signature");
+ return null;
+ }
}
+ return _typeSignature;
}
private String getUnresolvedType() throws JavaModelException
Index: src/org/eclipse/jst/jsf/context/symbol/internal/impl/IJavaTypeDescriptor2Impl.java
===================================================================
RCS file: /cvsroot/webtools/org.eclipse.jsf/components/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/context/symbol/internal/impl/IJavaTypeDescriptor2Impl.java,v
retrieving revision 1.4
diff -u -r1.4 IJavaTypeDescriptor2Impl.java
--- src/org/eclipse/jst/jsf/context/symbol/internal/impl/IJavaTypeDescriptor2Impl.java 7 Apr 2007 00:27:43 -0000 1.4
+++ src/org/eclipse/jst/jsf/context/symbol/internal/impl/IJavaTypeDescriptor2Impl.java 10 Apr 2007 15:07:21 -0000
@@ -18,7 +18,6 @@
import java.util.List;
import java.util.Map;
-import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
@@ -27,7 +26,6 @@
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jst.jsf.common.JSFCommonPlugin;
@@ -41,6 +39,7 @@
import org.eclipse.jst.jsf.context.symbol.internal.provisional.IJavaTypeDescriptor2;
import org.eclipse.jst.jsf.context.symbol.internal.provisional.IObjectSymbol;
import org.eclipse.jst.jsf.context.symbol.internal.provisional.IPropertySymbol;
+import org.eclipse.jst.jsf.context.symbol.internal.typeinfocache.TypeInfoCache;
/**
@@ -163,17 +162,12 @@
if (type_ != null)
{
- // TODO: type hierarchy is potentially expensive, should
- // cache once and listen for changes
- try {
- final ITypeHierarchy hierarchy =
- type_.newSupertypeHierarchy(new NullProgressMonitor());
- final IType[] interfaceTypes = hierarchy.getAllInterfaces();
- copySignatures(interfaces, interfaceTypes);
- } catch (JavaModelException e) {
- JSFCommonPlugin.log(e);
+ final TypeInfoCache typeInfoCache = TypeInfoCache.getInstance();
+ IType[] interfaceTypes = typeInfoCache.getCachedInterfaceTypes(type_);
+ if (interfaceTypes == null) {
+ interfaceTypes = typeInfoCache.cacheInterfaceTypesFor(type_);
}
-
+ copySignatures(interfaces, interfaceTypes);
}
return interfaces;
@@ -187,16 +181,12 @@
if (type_ != null)
{
- // TODO: type hierarchy is potentially expensive, should
- // cache once and listen for changes
- try {
- final ITypeHierarchy hierarchy =
- type_.newSupertypeHierarchy(new NullProgressMonitor());
- final IType[] interfaceTypes = hierarchy.getAllSuperclasses(type_);
- copySignatures(interfaces, interfaceTypes);
- } catch (JavaModelException e) {
- JSFCommonPlugin.log(e);
+ final TypeInfoCache typeInfoCache = TypeInfoCache.getInstance();
+ IType[] supertypes = typeInfoCache.getCachedSupertypes(type_);
+ if (supertypes == null) {
+ supertypes = typeInfoCache.cacheSupertypesFor(type_);
}
+ copySignatures(interfaces, supertypes);
}
return interfaces;
@@ -235,9 +225,19 @@
* @generated NOT
*/
public EList getBeanProperties() {
- BasicEList list = new BasicEList();
- list.addAll(getPropertiesInternal());
- return list;
+ TypeInfoCache typeInfoCache = TypeInfoCache.getInstance();
+ IBeanPropertySymbol[] properties = typeInfoCache.getCachedPropertySymbols(type);
+ Collection propertyColl;
+ if (properties == null) {
+ propertyColl = getPropertiesInternal();
+ properties = (IBeanPropertySymbol[]) propertyColl.toArray(new IBeanPropertySymbol[propertyColl.size()]);
+ typeInfoCache.cachePropertySymbols(type, properties);
+ } else {
+ propertyColl = new ArrayList(properties.length);
+ Collections.addAll(propertyColl, properties);
+ }
+ BasicEList list = new BasicEList(propertyColl);
+ return list;
}
/**
@@ -247,8 +247,18 @@
* @generated NOT
*/
public EList getBeanMethods() {
- BasicEList list = new BasicEList();
- list.addAll(getMethodsInternal());
+ TypeInfoCache typeInfoCache = TypeInfoCache.getInstance();
+ IBeanMethodSymbol[] methods = typeInfoCache.getCachedMethodSymbols(type);
+ Collection methodColl;
+ if (methods == null) {
+ methodColl = getMethodsInternal();
+ methods = (IBeanMethodSymbol[]) methodColl.toArray(new IBeanMethodSymbol[methodColl.size()]);
+ typeInfoCache.cacheMethodSymbols(type, methods);
+ } else {
+ methodColl = new ArrayList(methods.length);
+ Collections.addAll(methodColl, methods);
+ }
+ BasicEList list = new BasicEList(methodColl);
return list;
}
Index: src/org/eclipse/jst/jsf/context/symbol/internal/typeinfocache/TypeInfo.java
===================================================================
RCS file: src/org/eclipse/jst/jsf/context/symbol/internal/typeinfocache/TypeInfo.java
diff -N src/org/eclipse/jst/jsf/context/symbol/internal/typeinfocache/TypeInfo.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/jst/jsf/context/symbol/internal/typeinfocache/TypeInfo.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,100 @@
+package org.eclipse.jst.jsf.context.symbol.internal.typeinfocache;
+
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jst.jsf.context.symbol.internal.provisional.IBeanMethodSymbol;
+import org.eclipse.jst.jsf.context.symbol.internal.provisional.IBeanPropertySymbol;
+
+/**This class contains all info that is cached for a given IType.
+ * @see org.eclipse.jst.jsf.context.symbol.internal.typeinfocache.TypeInfoCache
+ *
+ * @author Matthias
+ */
+class TypeInfo {
+
+ /**Empty String array. Used for the (usual) case when a type has no missing supertypes.
+ */
+ public static String[] NO_NAMES = new String[0];
+
+ private IBeanMethodSymbol[] methods = null;
+ private IBeanPropertySymbol[] properties = null;
+ private IType[] supertypes = null;
+ private IType[] interfaceTypes = null;
+ private String[] missingSupertypeNames = null;
+
+ /**Creates an empty TypeInfo object
+ */
+ public TypeInfo() {
+ super();
+ }
+
+ /**Returns the method symbols. Returns null
if none have been cached.
+ * @return the method symbols. May be null.
+ */
+ public IBeanMethodSymbol[] getMethodSymbols() {
+ return methods;
+ }
+
+ /**Returns the property symbols. Returns null
if none have been cached.
+ * @return the property symbols. May be null.
+ */
+ public IBeanPropertySymbol[] getPropertySymbols() {
+ return properties;
+ }
+
+ /**Sets the methods symbols to be cached.
+ * @param methods - the method symbols
+ */
+ public void setMethodSymbols(IBeanMethodSymbol[] methods) {
+ this.methods = methods;
+ }
+
+ /**Sets the property symbols to be cached.
+ * @param properties - the property symbols
+ */
+ public void setPropertySymbols(IBeanPropertySymbol[] properties) {
+ this.properties = properties;
+ }
+
+ /**Returns the supertypes. Returns null
if none have been cached.
+ * @return the supertypes. May be null.
+ */
+ public IType[] getSupertypes() {
+ return supertypes;
+ }
+
+ /**Sets the supertypes to be cached.
+ * @param superTypes - the property symbols
+ */
+ public void setSupertypes(IType[] superTypes) {
+ this.supertypes = superTypes;
+ }
+
+ /**Returns the interface types. Returns null
if none have been cached.
+ * @return the interface types. May be null.
+ */
+ public IType[] getInterfaceTypes() {
+ return interfaceTypes;
+ }
+
+ /**Sets the interface types to be cached.
+ * @param interfaceTypes - the property symbols
+ */
+ public void setInterfaceTypes(IType[] interfaceTypes) {
+ this.interfaceTypes = interfaceTypes;
+ }
+
+ /**Returns the names of the missing supertypes. Returns null
if none have been cached.
+ * @return the names of the missing supertypes. May be null.
+ */
+ public String[] getMissingSupertypeNames() {
+ return missingSupertypeNames;
+ }
+
+ /**Sets the supertypes to be cached.
+ * @param missingSupertypeNames - the names of the missing supertypes
+ */
+ public void setMissingSupertypeNames(String[] missingSupertypeNames) {
+ this.missingSupertypeNames = missingSupertypeNames;
+ }
+
+}
Index: src/org/eclipse/jst/jsf/context/symbol/internal/typeinfocache/TypeInfoCache.java
===================================================================
RCS file: src/org/eclipse/jst/jsf/context/symbol/internal/typeinfocache/TypeInfoCache.java
diff -N src/org/eclipse/jst/jsf/context/symbol/internal/typeinfocache/TypeInfoCache.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/jst/jsf/context/symbol/internal/typeinfocache/TypeInfoCache.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,476 @@
+package org.eclipse.jst.jsf.context.symbol.internal.typeinfocache;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jdt.core.ElementChangedEvent;
+import org.eclipse.jdt.core.IClassFile;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IElementChangedListener;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaElementDelta;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.ITypeHierarchy;
+import org.eclipse.jdt.core.ITypeRoot;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.core.PackageFragment;
+import org.eclipse.jst.jsf.common.JSFCommonPlugin;
+import org.eclipse.jst.jsf.context.symbol.internal.provisional.IBeanMethodSymbol;
+import org.eclipse.jst.jsf.context.symbol.internal.provisional.IBeanPropertySymbol;
+
+/**Provides a cache for java IType properties. It can cache bean property symbols, method symbols,
+ * supertypes and implemented interfaces per IType. The cache listens to changes in the java model
+ * and invalidates affected properties, but does not update them.
+ *
+ * @author Matthias
+ */
+public class TypeInfoCache implements IElementChangedListener {
+
+ private static TypeInfoCache instance = null;
+
+ /**Returns the TypeInfoCache instance.
+ *
+ * @return the TypeInfoCache instance
+ */
+ public static synchronized TypeInfoCache getInstance() {
+ if (instance == null) {
+ instance = new TypeInfoCache();
+ JavaCore.addElementChangedListener(instance, ElementChangedEvent.POST_CHANGE);
+ }
+ return instance;
+ }
+
+ private Map /**/ cachedInfo;
+ private Map /*>*/ cachedTypesByAffectingTypeRoot;
+ private Map /*>*/ cachedTypesByMissingSupertypename;
+
+ private TypeInfoCache() {
+ cachedInfo = new HashMap();
+ cachedTypesByAffectingTypeRoot = new HashMap();
+ cachedTypesByMissingSupertypename = new HashMap(10);
+ }
+
+ public void elementChanged(ElementChangedEvent event) {
+ updateChangedJavaElement(event.getDelta());
+ }
+
+ /**Returns the cached info({@link TypeInfo}) for a given type. Will
+ * return null
if no info has been cached or the the type/something it depends on
+ * has changed since then.
+ *
+ * @param type - the type in question
+ * @return a TypeInfo instance that contains all cached info for the given type. May be null.
+ */
+ protected TypeInfo getTypeInfo(IType type) {
+ TypeInfo info = (TypeInfo) cachedInfo.get(type);
+ return info;
+ }
+
+ /**Returns the cached bean property symbols for a given type. Will return null if no
+ * bean property symbols have been cached or the type/something it depends on has changed since
+ * then.
+ * @param beanType - the bean type in question
+ * @return the bean property symbols for the given type. May be null.
+ * @see TypeInfoCache#cachePropertySymbols(IType, IBeanPropertySymbol[])
+ */
+ public synchronized IBeanPropertySymbol[] getCachedPropertySymbols(IType beanType) {
+ TypeInfo typeInfo = getTypeInfo(beanType);
+ return typeInfo == null? null : typeInfo.getPropertySymbols();
+ }
+
+ /**Returns the cached method symbols for a given type. Will return null if no
+ * method symbols have been cached or the type/something it depends on has changed since
+ * then.
+ * @param beanType - the bean type in question
+ * @return the method symbols for the given type. May be null.
+ * @see TypeInfoCache#cacheMethodSymbols(IType, IBeanMethodSymbol[])
+ */
+ public synchronized IBeanMethodSymbol[] getCachedMethodSymbols(IType beanType) {
+ TypeInfo typeInfo = getTypeInfo(beanType);
+ return typeInfo == null? null : typeInfo.getMethodSymbols();
+ }
+
+ /**Returns the cached supertypes for a given type. Will return null if no supertypes
+ * have been cached for this type or if the type/something it depends on has changed since
+ * then.
+ * @param type - the bean type in question
+ * @return the supertypes for the given type. May be null.
+ * @see TypeInfoCache#cacheSupertypesFor(IType)
+ */
+ public synchronized IType[] getCachedSupertypes(IType type) {
+ TypeInfo typeInfo = getTypeInfo(type);
+ return typeInfo == null? null : typeInfo.getSupertypes();
+ }
+
+ /**Returns the cached implemented interfaces for a given type. Will return null if no interfaces
+ * have been cached for this type or if the type/something it depends on has changed since
+ * then.
+ * @param type - the bean type in question
+ * @return the interface types implemented by the given type. May be null.
+ * @see TypeInfoCache#cacheInterfaceTypesFor(IType)
+ */
+ public synchronized IType[] getCachedInterfaceTypes(IType type) {
+ TypeInfo typeInfo = getTypeInfo(type);
+ return typeInfo == null? null : typeInfo.getInterfaceTypes();
+ }
+
+ /**Caches the given method symbols for the given type.
+ * @param beanType - the type
+ * @param methods - the method symbols to cache
+ */
+ public synchronized void cacheMethodSymbols(IType beanType, IBeanMethodSymbol[] methods) {
+ TypeInfo typeInfo = getOrCreateTypeInfo(beanType);
+ if (typeInfo != null) {
+ typeInfo.setMethodSymbols(methods);
+ }
+ }
+
+ /**Caches the given property symbols for the given type.
+ * @param beanType - the type
+ * @param properties - the property symbols to cache
+ */
+ public synchronized void cachePropertySymbols(IType beanType, IBeanPropertySymbol[] properties) {
+ TypeInfo typeInfo = getOrCreateTypeInfo(beanType);
+ if (typeInfo != null) {
+ typeInfo.setPropertySymbols(properties);
+ }
+ }
+
+ /**Caches the supertypes for the given type. The supertypes will be calculated (and also returned)
+ * by this method.
+ * @param type - the type to cache supertypes for
+ * @return the supertypes of the given type.
+ */
+ public synchronized IType[] cacheSupertypesFor(IType type) {
+ TypeInfo typeInfo = getOrCreateTypeInfo(type);
+ return typeInfo == null? null : typeInfo.getSupertypes();
+ }
+
+ /**Caches the interface types for the given type. The interface types will be calculated (and also
+ * returned) by this method.
+ * @param type - the type to cache interface types for
+ * @return the interface types implemented by the given type.
+ */
+ public synchronized IType[] cacheInterfaceTypesFor(IType type) {
+ TypeInfo typeInfo = getOrCreateTypeInfo(type);
+ return typeInfo == null? null : typeInfo.getInterfaceTypes();
+ }
+
+ /**Returns the TypeInfo for the given type. If no TypeInfo exists for this type, an empty TypeInfo
+ * will be created and cached.
+ * @param type - the type in question
+ * @return the (modifyable) TypeInfo for the given type
+ */
+ protected TypeInfo getOrCreateTypeInfo(IType type) {
+ TypeInfo typeInfo = getTypeInfo(type);
+ if (typeInfo == null) {
+ try {
+ final ITypeHierarchy hierarchy =
+ type.newSupertypeHierarchy(new NullProgressMonitor());
+ final IType[] supertypes = hierarchy.getAllSuperclasses(type);
+ final IType[] interfaceTypes = hierarchy.getAllInterfaces();
+ final IType[] rootClasses = hierarchy.getRootClasses();
+ List missingSupertypesList = null;
+ for (int i = 0; i < rootClasses.length; i++) {
+ String superclassName = rootClasses[i].getSuperclassName();
+ if (superclassName != null) {
+ if (missingSupertypesList == null) {
+ missingSupertypesList = new ArrayList(1);
+ }
+ superclassName = shortTypename(superclassName);
+ missingSupertypesList.add(superclassName);
+ }
+ }
+ String[] missingSupertypes = null;
+ if (missingSupertypesList != null) {
+ missingSupertypes = (String[]) missingSupertypesList.toArray(new String[missingSupertypesList.size()]);
+ } else {
+ missingSupertypes = TypeInfo.NO_NAMES;
+ }
+ typeInfo = new TypeInfo();
+ typeInfo.setSupertypes(supertypes);
+ typeInfo.setInterfaceTypes(interfaceTypes);
+ typeInfo.setMissingSupertypeNames(missingSupertypes);
+ cachedInfo.put(type, typeInfo);
+ registerCachedType(type, typeInfo);
+ } catch (JavaModelException e) {
+ JSFCommonPlugin.log(e);
+ }
+ }
+ return typeInfo;
+ }
+
+ /**Returns the typename fragment after the last "." (which in most cases is identical to the
+ * unqualified typename).
+ * Used only to make sure that if n1 and n2 are names of the same type
+ * shortname(n1) equals shortname(2) even if one name is qualified and one not.
+ * @param typename
+ * @return the typename fragment after the last "."
+ */
+ private String shortTypename(String typename) {
+ int pos = typename.lastIndexOf('.');
+ if (pos >= 0) {
+ typename = typename.substring(pos + 1);
+ }
+ return typename;
+ }
+
+ /**Registers the given type for all ITypeRoot's it depends on, so that it can be uncached if
+ * one of this ITypeRoot's has changed. The type must be unregistered when it should not be watched
+ * anymore.
+ * @param type - the type
+ * @param typeInfo - TypeInfo of the given type
+ * @see TypeInfoCache#unregisterCachedType(IType, TypeInfo)
+ */
+ protected void registerCachedType(IType type, TypeInfo typeInfo) {
+ registerTypeForTypeRoot(type, type.getTypeRoot());
+ IType[] supertypes = typeInfo.getSupertypes();
+ for (int i = 0; i < supertypes.length; i++) {
+ registerTypeForTypeRoot(type, supertypes[i].getTypeRoot());
+ }
+ String[] missingSupertypeNames = typeInfo.getMissingSupertypeNames();
+ if (missingSupertypeNames != null) {
+ for (int i = 0; i < missingSupertypeNames.length; i++) {
+ registerTypeForMissingSupertype(type, missingSupertypeNames[i]);
+ }
+ }
+ }
+
+ private void registerTypeForTypeRoot(IType type, ITypeRoot typeRoot) {
+ Set dependentTypes = (Set) cachedTypesByAffectingTypeRoot.get(typeRoot);
+ if (dependentTypes == null) {
+ dependentTypes = new HashSet(5);
+ cachedTypesByAffectingTypeRoot.put(typeRoot, dependentTypes);
+ }
+ dependentTypes.add(type);
+ }
+
+ private void registerTypeForMissingSupertype(IType type, String supertype) {
+ Set dependentTypes = (Set) cachedTypesByMissingSupertypename.get(supertype);
+ if (dependentTypes == null) {
+ dependentTypes = new HashSet(5);
+ cachedTypesByMissingSupertypename.put(supertype, dependentTypes);
+ }
+ dependentTypes.add(type);
+ }
+
+ /**Unregisters the given type for all ITypeRoot's it depended on.
+ * @param type - the type
+ * @param typeInfo - TypeInfo of the given type
+ */
+ protected void unregisterCachedType(IType type, TypeInfo typeInfo) {
+ unregisterTypeForTypeRoot(type, type.getTypeRoot());
+ IType[] supertypes = typeInfo.getSupertypes();
+ for (int i = 0; i < supertypes.length; i++) {
+ unregisterTypeForTypeRoot(type, supertypes[i].getTypeRoot());
+ }
+ String[] missingSupertypeNames = typeInfo.getMissingSupertypeNames();
+ if (missingSupertypeNames != null) {
+ for (int i = 0; i < missingSupertypeNames.length; i++) {
+ unregisterTypeForMissingSupertype(type, missingSupertypeNames[i]);
+ }
+ }
+ }
+
+ private void unregisterTypeForTypeRoot(IType type, ITypeRoot typeRoot) {
+ Set dependentTypes = (Set) cachedTypesByAffectingTypeRoot.get(typeRoot);
+ if (dependentTypes != null) {
+ dependentTypes.remove(type);
+ if (dependentTypes.isEmpty()) {
+ cachedTypesByAffectingTypeRoot.remove(typeRoot);
+ }
+ }
+ }
+
+ private void unregisterTypeForMissingSupertype(IType type, String supertype) {
+ Set dependentTypes = (Set) cachedTypesByMissingSupertypename.get(supertype);
+ if (dependentTypes != null) {
+ dependentTypes.remove(type);
+ if (dependentTypes.isEmpty()) {
+ cachedTypesByMissingSupertypename.remove(supertype);
+ }
+ }
+ }
+
+ /**This will remove all cached info for all types.
+ */
+ protected synchronized void uncacheAllTypes() {
+ cachedInfo.clear();
+ cachedTypesByAffectingTypeRoot.clear();
+ cachedTypesByMissingSupertypename.clear();
+ }
+
+ /**Removes all cached info for all types that are subtypes of a type of the given ITypeRoot.
+ * @param typeRoot
+ */
+ protected synchronized void uncacheAffectedTypes(ITypeRoot typeRoot) {
+ Collection affectedTypes = (Collection) cachedTypesByAffectingTypeRoot.get(typeRoot);
+ if (affectedTypes != null && !affectedTypes.isEmpty()) {
+ List affectedTypesCopy = new ArrayList(affectedTypes);
+ for (Iterator it = affectedTypesCopy.iterator(); it.hasNext(); ) {
+ IType cachedType = (IType) it.next();
+ TypeInfo typeInfo = (TypeInfo) cachedInfo.remove(cachedType);
+ unregisterCachedType(cachedType, typeInfo);
+ }
+ }
+ }
+
+ /**Removes all cached info for all types (or subtypes of types) that specify a supertype
+ * that has a name similar to the given name.
+ * @param supertypename - the missing supertype name. May be qualified or not
+ */
+ protected synchronized void uncacheTypesWithMissingSupertype(String supertypename) {
+ Collection affectedTypes = (Collection) cachedTypesByMissingSupertypename.get(shortTypename(supertypename));
+ if (affectedTypes != null && !affectedTypes.isEmpty()) {
+ List affectedTypesCopy = new ArrayList(affectedTypes);
+ for (Iterator it = affectedTypesCopy.iterator(); it.hasNext(); ) {
+ IType cachedType = (IType) it.next();
+ TypeInfo typeInfo = (TypeInfo) cachedInfo.remove(cachedType);
+ unregisterCachedType(cachedType, typeInfo);
+ }
+ }
+ }
+
+ /**Removes all cached info that may be affected by the given change.
+ * @param delta - the change in the java model
+ */
+ protected void updateChangedJavaElement(IJavaElementDelta delta) {
+ IJavaElement element= delta.getElement();
+ switch (element.getElementType()) {
+ case IJavaElement.JAVA_MODEL:
+ updateChangedJavaModel(delta, element);
+ break;
+ case IJavaElement.JAVA_PROJECT:
+ updateChangedJavaProject(delta, element);
+ break;
+ case IJavaElement.PACKAGE_FRAGMENT_ROOT:
+ updateChangedPackageFragmentRoot(delta, element);
+ break;
+ case IJavaElement.PACKAGE_FRAGMENT:
+ updateChangedPackageFragment(delta, (PackageFragment) element);
+ break;
+ case IJavaElement.CLASS_FILE:
+ case IJavaElement.COMPILATION_UNIT:
+ updateChangedOpenable(delta, element);
+ break;
+ }
+ }
+
+ private void updateChangedChildren(IJavaElementDelta delta) {
+ if ((delta.getFlags() & IJavaElementDelta.F_CHILDREN) > 0) {
+ IJavaElementDelta[] children= delta.getAffectedChildren();
+ for (int i= 0; i < children.length; i++) {
+ updateChangedJavaElement(children[i]);
+ }
+ }
+ }
+
+ private void updateChangedJavaModel(IJavaElementDelta delta, IJavaElement element) {
+ switch (delta.getKind()) {
+ case IJavaElementDelta.ADDED :
+ case IJavaElementDelta.REMOVED :
+ uncacheAllTypes();
+ break;
+ case IJavaElementDelta.CHANGED :
+ updateChangedChildren(delta);
+ break;
+ }
+ }
+
+ private void updateChangedJavaProject(IJavaElementDelta delta, IJavaElement element) {
+ int kind = delta.getKind();
+ int flags = delta.getFlags();
+ if ((flags & IJavaElementDelta.F_OPENED) != 0) {
+ kind = IJavaElementDelta.ADDED; // affected in the same way
+ }
+ if ((flags & IJavaElementDelta.F_CLOSED) != 0) {
+ kind = IJavaElementDelta.REMOVED; // affected in the same way
+ }
+ switch (kind) {
+ case IJavaElementDelta.ADDED :
+ case IJavaElementDelta.REMOVED :
+ uncacheAllTypes();
+ break;
+ case IJavaElementDelta.CHANGED :
+ updateChangedChildren(delta);
+ break;
+ }
+ }
+
+ private void updateChangedPackageFragment(IJavaElementDelta delta, PackageFragment element) {
+ switch (delta.getKind()) {
+ case IJavaElementDelta.ADDED :
+ // if the package fragment is in the projects being considered, this could
+ // introduce new types, changing the hierarchy
+ case IJavaElementDelta.REMOVED :
+ // is a change if the package fragment contains supertypes?
+ uncacheAllTypes();
+ break;
+ case IJavaElementDelta.CHANGED :
+ // look at the files in the package fragment
+ updateChangedChildren(delta);
+ }
+ }
+
+ private void updateChangedPackageFragmentRoot(IJavaElementDelta delta, IJavaElement element) {
+ switch (delta.getKind()) {
+ case IJavaElementDelta.ADDED :
+ case IJavaElementDelta.REMOVED :
+ uncacheAllTypes();
+ break;
+ case IJavaElementDelta.CHANGED :
+ int flags = delta.getFlags();
+ if (((flags & IJavaElementDelta.F_ADDED_TO_CLASSPATH) > 0)||(flags & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) > 0) {
+ uncacheAllTypes();
+ } else {
+ updateChangedChildren(delta);
+ }
+ break;
+ }
+ }
+
+ /**Removes all cached info that may be affected by the change in this IOpenable
+ * @param delta - the change in the java model
+ * @param element - the (changed) IOpenable considered
+ */
+ protected void updateChangedOpenable(IJavaElementDelta delta, IJavaElement element) {
+ if (element instanceof ITypeRoot) {
+ ITypeRoot typeRoot = (ITypeRoot) element;
+ uncacheAffectedTypes(typeRoot);
+ // Creates missing superclass for any cached type?
+ if (delta.getKind() == IJavaElementDelta.ADDED) {
+ if (typeRoot instanceof ICompilationUnit) {
+ ICompilationUnit cu = (ICompilationUnit) typeRoot;
+ try {
+ IType[] types = cu.getAllTypes();
+ for (int i = 0; i < types.length; i++) {
+ uncacheTypesWithMissingSupertype(types[i].getElementName());
+ }
+ } catch (JavaModelException e) {
+ JSFCommonPlugin.log(IStatus.INFO, "Unable to get types for compilation unit " + cu, e);
+ uncacheAllTypes();
+ }
+ } else if (typeRoot instanceof IClassFile) {
+ IClassFile cf = (IClassFile) typeRoot;
+ try {
+ IType type = cf.getType();
+ uncacheTypesWithMissingSupertype(type.getElementName());
+ } catch (JavaModelException e) {
+ JSFCommonPlugin.log(IStatus.INFO, "Unable to get types for classfile " + cf, e);
+ uncacheAllTypes();
+ }
+ }
+ }
+ }
+ }
+
+}