View | Details | Raw Unified | Return to bug 163890 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/jst/jsf/common/internal/provisional/util/JDTBeanProperty.java (-10 / +17 lines)
Lines 30-35 Link Here
30
	protected final IType    _type;
30
	protected final IType    _type;
31
    
31
    
32
    /**
32
    /**
33
     * cached type signature, created on first request
34
     */
35
    private String _typeSignature = null;
36
    
37
    /**
33
     * @param type
38
     * @param type
34
     */
39
     */
35
    protected JDTBeanProperty(IType type)
40
    protected JDTBeanProperty(IType type)
Lines 114-130 Link Here
114
	 */
119
	 */
115
	public String getTypeSignature()
120
	public String getTypeSignature()
116
    {
121
    {
117
        try
122
        if (_typeSignature == null) {
118
        {
123
            try
119
            String unResolvedSig = getUnresolvedType();
124
            {
120
            final String signature = TypeUtil.resolveTypeSignature(_type, unResolvedSig);
125
                String unresolvedSig = getUnresolvedType();
121
            return signature;
126
                _typeSignature = TypeUtil.resolveTypeSignature(_type, unresolvedSig);
122
        }
127
            }
123
        catch (JavaModelException jme)
128
            catch (JavaModelException jme)
124
        {
129
            {
125
            JSFCommonPlugin.log(jme, "Error resolving bean property type signature"); //$NON-NLS-1$
130
                JSFCommonPlugin.log(jme, "Error resolving bean property type signature");
126
            return null;
131
                return null;
132
            }
127
        }
133
        }
134
        return _typeSignature;
128
    }
135
    }
129
136
130
    private String getUnresolvedType() throws JavaModelException
137
    private String getUnresolvedType() throws JavaModelException
(-)src/org/eclipse/jst/jsf/context/symbol/internal/impl/IJavaTypeDescriptor2Impl.java (-26 / +36 lines)
Lines 18-24 Link Here
18
import java.util.List;
18
import java.util.List;
19
import java.util.Map;
19
import java.util.Map;
20
20
21
import org.eclipse.core.runtime.NullProgressMonitor;
22
import org.eclipse.emf.common.notify.Notification;
21
import org.eclipse.emf.common.notify.Notification;
23
import org.eclipse.emf.common.util.BasicEList;
22
import org.eclipse.emf.common.util.BasicEList;
24
import org.eclipse.emf.common.util.EList;
23
import org.eclipse.emf.common.util.EList;
Lines 27-33 Link Here
27
import org.eclipse.jdt.core.Flags;
26
import org.eclipse.jdt.core.Flags;
28
import org.eclipse.jdt.core.IMethod;
27
import org.eclipse.jdt.core.IMethod;
29
import org.eclipse.jdt.core.IType;
28
import org.eclipse.jdt.core.IType;
30
import org.eclipse.jdt.core.ITypeHierarchy;
31
import org.eclipse.jdt.core.JavaModelException;
29
import org.eclipse.jdt.core.JavaModelException;
32
import org.eclipse.jdt.core.Signature;
30
import org.eclipse.jdt.core.Signature;
33
import org.eclipse.jst.jsf.common.JSFCommonPlugin;
31
import org.eclipse.jst.jsf.common.JSFCommonPlugin;
Lines 41-46 Link Here
41
import org.eclipse.jst.jsf.context.symbol.internal.provisional.IJavaTypeDescriptor2;
39
import org.eclipse.jst.jsf.context.symbol.internal.provisional.IJavaTypeDescriptor2;
42
import org.eclipse.jst.jsf.context.symbol.internal.provisional.IObjectSymbol;
40
import org.eclipse.jst.jsf.context.symbol.internal.provisional.IObjectSymbol;
43
import org.eclipse.jst.jsf.context.symbol.internal.provisional.IPropertySymbol;
41
import org.eclipse.jst.jsf.context.symbol.internal.provisional.IPropertySymbol;
42
import org.eclipse.jst.jsf.context.symbol.internal.typeinfocache.TypeInfoCache;
44
43
45
44
46
/**
45
/**
Lines 163-179 Link Here
163
        
162
        
164
        if (type_ != null)
163
        if (type_ != null)
165
        {
164
        {
166
            // TODO: type hierarchy is potentially expensive, should
165
            final TypeInfoCache typeInfoCache = TypeInfoCache.getInstance();
167
            // cache once and listen for changes
166
            IType[] interfaceTypes = typeInfoCache.getCachedInterfaceTypes(type_);
168
            try {
167
            if (interfaceTypes == null) {
169
                final ITypeHierarchy  hierarchy = 
168
                interfaceTypes = typeInfoCache.cacheInterfaceTypesFor(type_);
170
                    type_.newSupertypeHierarchy(new NullProgressMonitor());
171
                final IType[] interfaceTypes = hierarchy.getAllInterfaces();
172
                copySignatures(interfaces, interfaceTypes);
173
            } catch (JavaModelException e) {
174
                JSFCommonPlugin.log(e);
175
            }
169
            }
176
170
            copySignatures(interfaces, interfaceTypes);
177
        }
171
        }
178
        
172
        
179
        return interfaces;
173
        return interfaces;
Lines 187-202 Link Here
187
        
181
        
188
        if (type_ != null)
182
        if (type_ != null)
189
        {
183
        {
190
            // TODO: type hierarchy is potentially expensive, should
184
            final TypeInfoCache typeInfoCache = TypeInfoCache.getInstance();
191
            // cache once and listen for changes
185
            IType[] supertypes = typeInfoCache.getCachedSupertypes(type_);
192
            try {
186
            if (supertypes == null) {
193
                final ITypeHierarchy  hierarchy = 
187
                supertypes = typeInfoCache.cacheSupertypesFor(type_);
194
                    type_.newSupertypeHierarchy(new NullProgressMonitor());
195
                final IType[] interfaceTypes = hierarchy.getAllSuperclasses(type_);
196
                copySignatures(interfaces, interfaceTypes);
197
            } catch (JavaModelException e) {
198
                JSFCommonPlugin.log(e);
199
            }
188
            }
189
            copySignatures(interfaces, supertypes);
200
        }
190
        }
201
        
191
        
202
        return interfaces;
192
        return interfaces;
Lines 235-243 Link Here
235
	 * @generated NOT
225
	 * @generated NOT
236
	 */
226
	 */
237
	public EList getBeanProperties() {
227
	public EList getBeanProperties() {
238
		BasicEList list = new BasicEList();
228
        TypeInfoCache typeInfoCache = TypeInfoCache.getInstance();
239
		list.addAll(getPropertiesInternal());
229
        IBeanPropertySymbol[] properties = typeInfoCache.getCachedPropertySymbols(type);
240
		return list;
230
        Collection propertyColl;
231
        if (properties == null) {
232
            propertyColl = getPropertiesInternal();
233
            properties = (IBeanPropertySymbol[]) propertyColl.toArray(new IBeanPropertySymbol[propertyColl.size()]);
234
            typeInfoCache.cachePropertySymbols(type, properties);
235
        } else {
236
            propertyColl = new ArrayList(properties.length);
237
            Collections.addAll(propertyColl, properties);
238
        }
239
        BasicEList list = new BasicEList(propertyColl);
240
        return list;
241
	}
241
	}
242
242
243
	/**
243
	/**
Lines 247-254 Link Here
247
	 * @generated NOT
247
	 * @generated NOT
248
	 */
248
	 */
249
	public EList getBeanMethods() {
249
	public EList getBeanMethods() {
250
		BasicEList list = new BasicEList();
250
        TypeInfoCache typeInfoCache = TypeInfoCache.getInstance();
251
		list.addAll(getMethodsInternal());
251
        IBeanMethodSymbol[] methods = typeInfoCache.getCachedMethodSymbols(type);
252
        Collection methodColl;
253
        if (methods == null) {
254
            methodColl = getMethodsInternal();
255
            methods = (IBeanMethodSymbol[]) methodColl.toArray(new IBeanMethodSymbol[methodColl.size()]);
256
            typeInfoCache.cacheMethodSymbols(type, methods);
257
        } else {
258
            methodColl = new ArrayList(methods.length);
259
            Collections.addAll(methodColl, methods);
260
        }
261
		BasicEList list = new BasicEList(methodColl);
252
		return list;
262
		return list;
253
	}
263
	}
254
264
(-)src/org/eclipse/jst/jsf/context/symbol/internal/typeinfocache/TypeInfo.java (+100 lines)
Added Link Here
1
package org.eclipse.jst.jsf.context.symbol.internal.typeinfocache;
2
3
import org.eclipse.jdt.core.IType;
4
import org.eclipse.jst.jsf.context.symbol.internal.provisional.IBeanMethodSymbol;
5
import org.eclipse.jst.jsf.context.symbol.internal.provisional.IBeanPropertySymbol;
6
7
/**This class contains all info that is cached for a given IType.
8
 * @see org.eclipse.jst.jsf.context.symbol.internal.typeinfocache.TypeInfoCache
9
 * 
10
 * @author Matthias
11
 */
12
class TypeInfo {
13
    
14
    /**Empty String array. Used for the (usual) case when a type has no missing supertypes.
15
     */
16
    public static String[] NO_NAMES = new String[0];
17
18
    private IBeanMethodSymbol[] methods = null;
19
    private IBeanPropertySymbol[] properties = null;
20
    private IType[] supertypes = null;
21
    private IType[] interfaceTypes = null;
22
    private String[] missingSupertypeNames = null;
23
    
24
    /**Creates an empty TypeInfo object
25
     */
26
    public TypeInfo() {
27
        super();
28
    }
29
    
30
    /**Returns the method symbols. Returns <code>null</code> if none have been cached.
31
     * @return the method symbols. May be null.
32
     */
33
    public IBeanMethodSymbol[] getMethodSymbols() {
34
        return methods;
35
    }
36
    
37
    /**Returns the property symbols. Returns <code>null</code> if none have been cached.
38
     * @return the property symbols. May be null.
39
     */
40
    public IBeanPropertySymbol[] getPropertySymbols() {
41
        return properties;
42
    }
43
44
    /**Sets the methods symbols to be cached.
45
     * @param methods - the method symbols
46
     */
47
    public void setMethodSymbols(IBeanMethodSymbol[] methods) {
48
        this.methods = methods;
49
    }
50
51
    /**Sets the property symbols to be cached.
52
     * @param properties - the property symbols
53
     */
54
    public void setPropertySymbols(IBeanPropertySymbol[] properties) {
55
        this.properties = properties;
56
    }
57
58
    /**Returns the supertypes. Returns <code>null</code> if none have been cached.
59
     * @return the supertypes. May be null.
60
     */
61
    public IType[] getSupertypes() {
62
        return supertypes;
63
    }
64
65
    /**Sets the supertypes to be cached.
66
     * @param superTypes - the property symbols
67
     */
68
    public void setSupertypes(IType[] superTypes) {
69
        this.supertypes = superTypes;
70
    }
71
72
    /**Returns the interface types. Returns <code>null</code> if none have been cached.
73
     * @return the interface types. May be null.
74
     */
75
    public IType[] getInterfaceTypes() {
76
        return interfaceTypes;
77
    }
78
79
    /**Sets the interface types to be cached.
80
     * @param interfaceTypes - the property symbols
81
     */
82
    public void setInterfaceTypes(IType[] interfaceTypes) {
83
        this.interfaceTypes = interfaceTypes;
84
    }
85
86
    /**Returns the names of the missing supertypes. Returns <code>null</code> if none have been cached.
87
     * @return the names of the missing supertypes. May be null.
88
     */
89
    public String[] getMissingSupertypeNames() {
90
        return missingSupertypeNames;
91
    }
92
93
    /**Sets the supertypes to be cached.
94
     * @param missingSupertypeNames - the names of the missing supertypes
95
     */
96
    public void setMissingSupertypeNames(String[] missingSupertypeNames) {
97
        this.missingSupertypeNames = missingSupertypeNames;
98
    }
99
    
100
}
(-)src/org/eclipse/jst/jsf/context/symbol/internal/typeinfocache/TypeInfoCache.java (+476 lines)
Added Link Here
1
package org.eclipse.jst.jsf.context.symbol.internal.typeinfocache;
2
3
import java.util.ArrayList;
4
import java.util.Collection;
5
import java.util.HashMap;
6
import java.util.HashSet;
7
import java.util.Iterator;
8
import java.util.List;
9
import java.util.Map;
10
import java.util.Set;
11
12
import org.eclipse.core.runtime.IStatus;
13
import org.eclipse.core.runtime.NullProgressMonitor;
14
import org.eclipse.jdt.core.ElementChangedEvent;
15
import org.eclipse.jdt.core.IClassFile;
16
import org.eclipse.jdt.core.ICompilationUnit;
17
import org.eclipse.jdt.core.IElementChangedListener;
18
import org.eclipse.jdt.core.IJavaElement;
19
import org.eclipse.jdt.core.IJavaElementDelta;
20
import org.eclipse.jdt.core.IType;
21
import org.eclipse.jdt.core.ITypeHierarchy;
22
import org.eclipse.jdt.core.ITypeRoot;
23
import org.eclipse.jdt.core.JavaCore;
24
import org.eclipse.jdt.core.JavaModelException;
25
import org.eclipse.jdt.internal.core.PackageFragment;
26
import org.eclipse.jst.jsf.common.JSFCommonPlugin;
27
import org.eclipse.jst.jsf.context.symbol.internal.provisional.IBeanMethodSymbol;
28
import org.eclipse.jst.jsf.context.symbol.internal.provisional.IBeanPropertySymbol;
29
30
/**Provides a cache for java IType properties. It can cache bean property symbols, method symbols,
31
 * supertypes and implemented interfaces per IType. The cache listens to changes in the java model
32
 * and invalidates affected properties, but does not update them.
33
 * 
34
 * @author Matthias
35
 */
36
public class TypeInfoCache implements IElementChangedListener {
37
    
38
    private static TypeInfoCache instance = null;
39
    
40
    /**Returns the TypeInfoCache instance.
41
     * 
42
     * @return the TypeInfoCache instance
43
     */
44
    public static synchronized TypeInfoCache getInstance() {
45
        if (instance == null) {
46
            instance = new TypeInfoCache();
47
            JavaCore.addElementChangedListener(instance, ElementChangedEvent.POST_CHANGE);
48
        }
49
        return instance;
50
    }
51
    
52
    private Map /*<IType, TypeInfo>*/ cachedInfo;
53
    private Map /*<ITypeRoot, Set<IType>>*/ cachedTypesByAffectingTypeRoot;
54
    private Map /*<String, Set<IType>>*/ cachedTypesByMissingSupertypename;
55
    
56
    private TypeInfoCache() {
57
        cachedInfo = new HashMap();
58
        cachedTypesByAffectingTypeRoot = new HashMap();
59
        cachedTypesByMissingSupertypename = new HashMap(10);
60
    }
61
62
    public void elementChanged(ElementChangedEvent event) {
63
        updateChangedJavaElement(event.getDelta());
64
    }
65
    
66
    /**Returns the cached info({@link TypeInfo}) for a given type. Will
67
     * return <code>null</code> if no info has been cached or the the type/something it depends on
68
     * has changed since then.
69
     * 
70
     * @param type - the type in question
71
     * @return a TypeInfo instance that contains all cached info for the given type. May be null.  
72
     */
73
    protected TypeInfo getTypeInfo(IType type) {
74
        TypeInfo info = (TypeInfo) cachedInfo.get(type);
75
        return info;
76
    }
77
78
    /**Returns the cached bean property symbols for a given type. Will return null if no
79
     * bean property symbols have been cached or the type/something it depends on has changed since
80
     * then.
81
     * @param beanType - the bean type in question
82
     * @return the bean property symbols for the given type. May be null.
83
     * @see TypeInfoCache#cachePropertySymbols(IType, IBeanPropertySymbol[])
84
     */
85
    public synchronized IBeanPropertySymbol[] getCachedPropertySymbols(IType beanType) {
86
        TypeInfo typeInfo = getTypeInfo(beanType);
87
        return typeInfo == null? null : typeInfo.getPropertySymbols();
88
    }
89
90
    /**Returns the cached method symbols for a given type. Will return null if no
91
     * method symbols have been cached or the type/something it depends on has changed since
92
     * then.
93
     * @param beanType - the bean type in question
94
     * @return the method symbols for the given type. May be null.
95
     * @see TypeInfoCache#cacheMethodSymbols(IType, IBeanMethodSymbol[])
96
     */
97
    public synchronized IBeanMethodSymbol[] getCachedMethodSymbols(IType beanType) {
98
        TypeInfo typeInfo = getTypeInfo(beanType);
99
        return typeInfo == null? null : typeInfo.getMethodSymbols();
100
    }
101
    
102
    /**Returns the cached supertypes for a given type. Will return null if no supertypes
103
     * have been cached for this type or if the type/something it depends on has changed since
104
     * then.
105
     * @param type - the bean type in question
106
     * @return the supertypes for the given type. May be null.
107
     * @see TypeInfoCache#cacheSupertypesFor(IType)
108
     */
109
    public synchronized IType[] getCachedSupertypes(IType type) {
110
        TypeInfo typeInfo = getTypeInfo(type);
111
        return typeInfo == null? null : typeInfo.getSupertypes();
112
    }
113
    
114
    /**Returns the cached implemented interfaces for a given type. Will return null if no interfaces
115
     * have been cached for this type or if the type/something it depends on has changed since
116
     * then.
117
     * @param type - the bean type in question
118
     * @return the interface types implemented by the given type. May be null.
119
     * @see TypeInfoCache#cacheInterfaceTypesFor(IType)
120
     */
121
    public synchronized IType[] getCachedInterfaceTypes(IType type) {
122
        TypeInfo typeInfo = getTypeInfo(type);
123
        return typeInfo == null? null : typeInfo.getInterfaceTypes();
124
    }
125
    
126
    /**Caches the given method symbols for the given type. 
127
     * @param beanType - the type
128
     * @param methods - the method symbols to cache
129
     */
130
    public synchronized void cacheMethodSymbols(IType beanType, IBeanMethodSymbol[] methods) {
131
        TypeInfo typeInfo = getOrCreateTypeInfo(beanType);
132
        if (typeInfo != null) {
133
            typeInfo.setMethodSymbols(methods);
134
        }
135
    }
136
137
    /**Caches the given property symbols for the given type. 
138
     * @param beanType - the type
139
     * @param properties - the property symbols to cache
140
     */
141
    public synchronized void cachePropertySymbols(IType beanType, IBeanPropertySymbol[] properties) {
142
        TypeInfo typeInfo = getOrCreateTypeInfo(beanType);
143
        if (typeInfo != null) {
144
            typeInfo.setPropertySymbols(properties);
145
        }
146
    }
147
    
148
    /**Caches the supertypes for the given type. The supertypes will be calculated (and also returned)
149
     * by this method.
150
     * @param type - the type to cache supertypes for
151
     * @return the supertypes of the given type.
152
     */
153
    public synchronized IType[] cacheSupertypesFor(IType type) {
154
        TypeInfo typeInfo = getOrCreateTypeInfo(type);
155
        return typeInfo == null? null : typeInfo.getSupertypes();
156
    }
157
158
    /**Caches the interface types for the given type. The interface types will be calculated (and also
159
     * returned) by this method.
160
     * @param type - the type to cache interface types for
161
     * @return the interface types implemented by the given type.
162
     */
163
    public synchronized IType[] cacheInterfaceTypesFor(IType type) {
164
        TypeInfo typeInfo = getOrCreateTypeInfo(type);
165
        return typeInfo == null? null : typeInfo.getInterfaceTypes();
166
    }
167
168
    /**Returns the TypeInfo for the given type. If no TypeInfo exists for this type, an empty TypeInfo
169
     * will be created and cached.
170
     * @param type - the type in question
171
     * @return the (modifyable) TypeInfo for the given type
172
     */
173
    protected TypeInfo getOrCreateTypeInfo(IType type) {
174
        TypeInfo typeInfo = getTypeInfo(type);
175
        if (typeInfo == null) {
176
            try {
177
                final ITypeHierarchy  hierarchy = 
178
                    type.newSupertypeHierarchy(new NullProgressMonitor());
179
                final IType[] supertypes = hierarchy.getAllSuperclasses(type);
180
                final IType[] interfaceTypes = hierarchy.getAllInterfaces();
181
                final IType[] rootClasses = hierarchy.getRootClasses();
182
                List missingSupertypesList = null;
183
                for (int i = 0; i < rootClasses.length; i++) {
184
                    String superclassName = rootClasses[i].getSuperclassName();
185
                    if (superclassName != null) {
186
                        if (missingSupertypesList == null) {
187
                            missingSupertypesList = new ArrayList(1);
188
                        }
189
                        superclassName = shortTypename(superclassName);
190
                        missingSupertypesList.add(superclassName);
191
                    }
192
                }
193
                String[] missingSupertypes = null;
194
                if (missingSupertypesList != null) {
195
                    missingSupertypes = (String[]) missingSupertypesList.toArray(new String[missingSupertypesList.size()]);
196
                } else {
197
                    missingSupertypes = TypeInfo.NO_NAMES;
198
                }
199
                typeInfo = new TypeInfo();
200
                typeInfo.setSupertypes(supertypes);
201
                typeInfo.setInterfaceTypes(interfaceTypes);
202
                typeInfo.setMissingSupertypeNames(missingSupertypes);
203
                cachedInfo.put(type, typeInfo);
204
                registerCachedType(type, typeInfo);
205
            } catch (JavaModelException e) {
206
                JSFCommonPlugin.log(e);
207
            }
208
        }
209
        return typeInfo;
210
    }
211
212
    /**Returns the typename fragment after the last "." (which in most cases is identical to the
213
     * unqualified typename).
214
     * Used only to make sure that if n1 and n2 are names of the same type
215
     * shortname(n1) equals shortname(2) even if one name is qualified and one not.
216
     * @param typename
217
     * @return the typename fragment after the last "."
218
     */
219
    private String shortTypename(String typename) {
220
        int pos = typename.lastIndexOf('.');
221
        if (pos >= 0) {
222
            typename = typename.substring(pos + 1);
223
        }
224
        return typename;
225
    }
226
    
227
    /**Registers the given type for all ITypeRoot's it depends on, so that it can be uncached if
228
     * one of this ITypeRoot's has changed. The type must be unregistered when it should not be watched
229
     * anymore.
230
     * @param type - the type
231
     * @param typeInfo - TypeInfo of the given type
232
     * @see TypeInfoCache#unregisterCachedType(IType, TypeInfo)
233
     */
234
    protected void registerCachedType(IType type, TypeInfo typeInfo) {
235
        registerTypeForTypeRoot(type, type.getTypeRoot());
236
        IType[] supertypes = typeInfo.getSupertypes();
237
        for (int i = 0; i < supertypes.length; i++) {
238
            registerTypeForTypeRoot(type, supertypes[i].getTypeRoot());
239
        }
240
        String[] missingSupertypeNames = typeInfo.getMissingSupertypeNames();
241
        if (missingSupertypeNames != null) {
242
            for (int i = 0; i < missingSupertypeNames.length; i++) {
243
                registerTypeForMissingSupertype(type, missingSupertypeNames[i]);
244
            }
245
        }
246
    }
247
248
    private void registerTypeForTypeRoot(IType type, ITypeRoot typeRoot) {
249
        Set dependentTypes = (Set) cachedTypesByAffectingTypeRoot.get(typeRoot);
250
        if (dependentTypes == null) {
251
            dependentTypes = new HashSet(5);
252
            cachedTypesByAffectingTypeRoot.put(typeRoot, dependentTypes);
253
        }
254
        dependentTypes.add(type);
255
    }
256
257
    private void registerTypeForMissingSupertype(IType type, String supertype) {
258
        Set dependentTypes = (Set) cachedTypesByMissingSupertypename.get(supertype);
259
        if (dependentTypes == null) {
260
            dependentTypes = new HashSet(5);
261
            cachedTypesByMissingSupertypename.put(supertype, dependentTypes);
262
        }
263
        dependentTypes.add(type);
264
    }
265
266
    /**Unregisters the given type for all ITypeRoot's it depended on.
267
     * @param type - the type
268
     * @param typeInfo - TypeInfo of the given type
269
     */
270
    protected void unregisterCachedType(IType type, TypeInfo typeInfo) {
271
        unregisterTypeForTypeRoot(type, type.getTypeRoot());
272
        IType[] supertypes = typeInfo.getSupertypes();
273
        for (int i = 0; i < supertypes.length; i++) {
274
            unregisterTypeForTypeRoot(type, supertypes[i].getTypeRoot());
275
        }
276
        String[] missingSupertypeNames = typeInfo.getMissingSupertypeNames();
277
        if (missingSupertypeNames != null) {
278
            for (int i = 0; i < missingSupertypeNames.length; i++) {
279
                unregisterTypeForMissingSupertype(type, missingSupertypeNames[i]);
280
            }
281
        }
282
    }
283
284
    private void unregisterTypeForTypeRoot(IType type, ITypeRoot typeRoot) {
285
        Set dependentTypes = (Set) cachedTypesByAffectingTypeRoot.get(typeRoot);
286
        if (dependentTypes != null) {
287
            dependentTypes.remove(type);
288
            if (dependentTypes.isEmpty()) {
289
                cachedTypesByAffectingTypeRoot.remove(typeRoot);
290
            }
291
        }
292
    }
293
    
294
    private void unregisterTypeForMissingSupertype(IType type, String supertype) {
295
        Set dependentTypes = (Set) cachedTypesByMissingSupertypename.get(supertype);
296
        if (dependentTypes != null) {
297
            dependentTypes.remove(type);
298
            if (dependentTypes.isEmpty()) {
299
                cachedTypesByMissingSupertypename.remove(supertype);
300
            }
301
        }
302
    }
303
    
304
    /**This will remove all cached info for all types.
305
     */
306
    protected synchronized void uncacheAllTypes() {
307
        cachedInfo.clear();
308
        cachedTypesByAffectingTypeRoot.clear();
309
        cachedTypesByMissingSupertypename.clear();
310
    }
311
    
312
    /**Removes all cached info for all types that are subtypes of a type of the given ITypeRoot. 
313
     * @param typeRoot
314
     */
315
    protected synchronized void uncacheAffectedTypes(ITypeRoot typeRoot) {
316
        Collection affectedTypes = (Collection) cachedTypesByAffectingTypeRoot.get(typeRoot);
317
        if (affectedTypes != null && !affectedTypes.isEmpty()) {
318
            List affectedTypesCopy = new ArrayList(affectedTypes);
319
            for (Iterator it = affectedTypesCopy.iterator(); it.hasNext(); ) {
320
                IType cachedType = (IType) it.next();
321
                TypeInfo typeInfo = (TypeInfo) cachedInfo.remove(cachedType);
322
                unregisterCachedType(cachedType, typeInfo);
323
            }
324
        }
325
    }
326
    
327
    /**Removes all cached info for all types (or subtypes of types) that specify a supertype
328
     * that has a name similar to the given name. 
329
     * @param supertypename - the missing supertype name. May be qualified or not
330
     */
331
    protected synchronized void uncacheTypesWithMissingSupertype(String supertypename) {
332
        Collection affectedTypes = (Collection) cachedTypesByMissingSupertypename.get(shortTypename(supertypename));
333
        if (affectedTypes != null && !affectedTypes.isEmpty()) {
334
            List affectedTypesCopy = new ArrayList(affectedTypes);
335
            for (Iterator it = affectedTypesCopy.iterator(); it.hasNext(); ) {
336
                IType cachedType = (IType) it.next();
337
                TypeInfo typeInfo = (TypeInfo) cachedInfo.remove(cachedType);
338
                unregisterCachedType(cachedType, typeInfo);
339
            }
340
        }
341
    }
342
    
343
    /**Removes all cached info that may be affected by the given change.
344
     * @param delta - the change in the java model
345
     */
346
    protected void updateChangedJavaElement(IJavaElementDelta delta) {
347
        IJavaElement element= delta.getElement();
348
        switch (element.getElementType()) {
349
            case IJavaElement.JAVA_MODEL:
350
                updateChangedJavaModel(delta, element);
351
                break;
352
            case IJavaElement.JAVA_PROJECT:
353
                updateChangedJavaProject(delta, element);
354
                break;
355
            case IJavaElement.PACKAGE_FRAGMENT_ROOT:
356
                updateChangedPackageFragmentRoot(delta, element);
357
                break;
358
            case IJavaElement.PACKAGE_FRAGMENT:
359
                updateChangedPackageFragment(delta, (PackageFragment) element);
360
                break;
361
            case IJavaElement.CLASS_FILE:
362
            case IJavaElement.COMPILATION_UNIT:
363
                updateChangedOpenable(delta, element);
364
                break;
365
        }
366
    }
367
    
368
    private void updateChangedChildren(IJavaElementDelta delta) {
369
        if ((delta.getFlags() & IJavaElementDelta.F_CHILDREN) > 0) {
370
            IJavaElementDelta[] children= delta.getAffectedChildren();
371
            for (int i= 0; i < children.length; i++) {
372
                updateChangedJavaElement(children[i]);
373
            }
374
        }
375
    }
376
377
    private void updateChangedJavaModel(IJavaElementDelta delta, IJavaElement element) {
378
        switch (delta.getKind()) {
379
            case IJavaElementDelta.ADDED :
380
            case IJavaElementDelta.REMOVED :
381
                uncacheAllTypes();
382
                break;
383
            case IJavaElementDelta.CHANGED :
384
                updateChangedChildren(delta);
385
                break;
386
        }
387
    }
388
389
    private void updateChangedJavaProject(IJavaElementDelta delta, IJavaElement element) {
390
        int kind = delta.getKind();
391
        int flags = delta.getFlags();
392
        if ((flags & IJavaElementDelta.F_OPENED) != 0) {
393
            kind = IJavaElementDelta.ADDED; // affected in the same way
394
        }
395
        if ((flags & IJavaElementDelta.F_CLOSED) != 0) {
396
            kind = IJavaElementDelta.REMOVED; // affected in the same way
397
        }
398
        switch (kind) {
399
            case IJavaElementDelta.ADDED :
400
            case IJavaElementDelta.REMOVED :
401
                uncacheAllTypes();
402
                break;
403
            case IJavaElementDelta.CHANGED :
404
                updateChangedChildren(delta);
405
                break;
406
        }
407
    }
408
409
   private void updateChangedPackageFragment(IJavaElementDelta delta, PackageFragment element) {
410
        switch (delta.getKind()) {
411
            case IJavaElementDelta.ADDED :
412
                // if the package fragment is in the projects being considered, this could
413
                // introduce new types, changing the hierarchy
414
            case IJavaElementDelta.REMOVED :
415
                // is a change if the package fragment contains supertypes?
416
                uncacheAllTypes();
417
                break;
418
            case IJavaElementDelta.CHANGED :
419
                // look at the files in the package fragment
420
                updateChangedChildren(delta);
421
        }
422
    }
423
424
    private void updateChangedPackageFragmentRoot(IJavaElementDelta delta, IJavaElement element) {
425
        switch (delta.getKind()) {
426
            case IJavaElementDelta.ADDED :
427
            case IJavaElementDelta.REMOVED :
428
                uncacheAllTypes();
429
                break;
430
            case IJavaElementDelta.CHANGED :
431
                int flags = delta.getFlags();
432
                if (((flags & IJavaElementDelta.F_ADDED_TO_CLASSPATH) > 0)||(flags & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) > 0) {
433
                    uncacheAllTypes();
434
                } else {
435
                    updateChangedChildren(delta);
436
                }
437
                break;
438
        }
439
    }
440
441
    /**Removes all cached info that may be affected by the change in this IOpenable
442
     * @param delta - the change in the java model
443
     * @param element - the (changed) IOpenable considered
444
     */
445
    protected void updateChangedOpenable(IJavaElementDelta delta, IJavaElement element) {
446
        if (element instanceof ITypeRoot) {
447
            ITypeRoot typeRoot = (ITypeRoot) element;
448
            uncacheAffectedTypes(typeRoot);
449
            // Creates missing superclass for any cached type?
450
            if (delta.getKind() == IJavaElementDelta.ADDED) {
451
                if (typeRoot instanceof ICompilationUnit) {
452
                    ICompilationUnit cu = (ICompilationUnit) typeRoot;
453
                    try {
454
                        IType[] types = cu.getAllTypes();
455
                        for (int i = 0; i < types.length; i++) {
456
                            uncacheTypesWithMissingSupertype(types[i].getElementName());
457
                        }
458
                    } catch (JavaModelException e) {
459
                        JSFCommonPlugin.log(IStatus.INFO, "Unable to get types for compilation unit " + cu, e);
460
                        uncacheAllTypes();
461
                    }
462
                } else if (typeRoot instanceof IClassFile) {
463
                    IClassFile cf = (IClassFile) typeRoot;
464
                    try {
465
                        IType type = cf.getType();
466
                        uncacheTypesWithMissingSupertype(type.getElementName());
467
                    } catch (JavaModelException e) {
468
                        JSFCommonPlugin.log(IStatus.INFO, "Unable to get types for classfile " + cf, e);
469
                        uncacheAllTypes();
470
                    }
471
                }
472
            }
473
        }
474
    }
475
476
}

Return to bug 163890