KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > ui > typehierarchy > TypeHierarchyContentProvider


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.ui.typehierarchy;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.List JavaDoc;
15
16 import org.eclipse.core.runtime.Assert;
17
18 import org.eclipse.jface.viewers.ITreeContentProvider;
19 import org.eclipse.jface.viewers.TreeViewer;
20 import org.eclipse.jface.viewers.Viewer;
21 import org.eclipse.jface.viewers.ViewerFilter;
22
23 import org.eclipse.jdt.core.IJavaElement;
24 import org.eclipse.jdt.core.IMember;
25 import org.eclipse.jdt.core.IMethod;
26 import org.eclipse.jdt.core.IType;
27 import org.eclipse.jdt.core.ITypeHierarchy;
28 import org.eclipse.jdt.core.JavaModelException;
29
30 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
31 import org.eclipse.jdt.internal.corext.util.MethodOverrideTester;
32
33 import org.eclipse.jdt.ui.IWorkingCopyProvider;
34
35 /**
36  * Base class for content providers for type hierarchy viewers.
37  * Implementors must override 'getTypesInHierarchy'.
38  * Java delta processing is also performed by the content provider
39  */

40 public abstract class TypeHierarchyContentProvider implements ITreeContentProvider, IWorkingCopyProvider {
41     protected static final Object JavaDoc[] NO_ELEMENTS= new Object JavaDoc[0];
42     
43     protected TypeHierarchyLifeCycle fTypeHierarchy;
44     protected IMember[] fMemberFilter;
45     
46     protected TreeViewer fViewer;
47
48     private ViewerFilter fWorkingSetFilter;
49     private MethodOverrideTester fMethodOverrideTester;
50     private ITypeHierarchyLifeCycleListener fTypeHierarchyLifeCycleListener;
51     
52     
53     public TypeHierarchyContentProvider(TypeHierarchyLifeCycle lifecycle) {
54         fTypeHierarchy= lifecycle;
55         fMemberFilter= null;
56         fWorkingSetFilter= null;
57         fMethodOverrideTester= null;
58         fTypeHierarchyLifeCycleListener= new ITypeHierarchyLifeCycleListener() {
59             public void typeHierarchyChanged(TypeHierarchyLifeCycle typeHierarchyProvider, IType[] changedTypes) {
60                 if (changedTypes == null) {
61                     fMethodOverrideTester= null;
62                 }
63             }
64         };
65         lifecycle.addChangedListener(fTypeHierarchyLifeCycleListener);
66     }
67     
68     /**
69      * Sets members to filter the hierarchy for. Set to <code>null</code> to disable member filtering.
70      * When member filtering is enabled, the hierarchy contains only types that contain
71      * an implementation of one of the filter members and the members themself.
72      * The hierarchy can be empty as well.
73      */

74     public final void setMemberFilter(IMember[] memberFilter) {
75         fMemberFilter= memberFilter;
76     }
77
78     private boolean initializeMethodOverrideTester(IMethod filterMethod, IType typeToFindIn) {
79         IType filterType= filterMethod.getDeclaringType();
80         ITypeHierarchy hierarchy= fTypeHierarchy.getHierarchy();
81         
82         boolean filterOverrides= JavaModelUtil.isSuperType(hierarchy, typeToFindIn, filterType);
83         IType focusType= filterOverrides ? filterType : typeToFindIn;
84         
85         if (fMethodOverrideTester == null || !fMethodOverrideTester.getFocusType().equals(focusType)) {
86             fMethodOverrideTester= new MethodOverrideTester(focusType, hierarchy);
87         }
88         return filterOverrides;
89     }
90     
91     private void addCompatibleMethods(IMethod filterMethod, IType typeToFindIn, List JavaDoc children) throws JavaModelException {
92         boolean filterMethodOverrides= initializeMethodOverrideTester(filterMethod, typeToFindIn);
93         IMethod[] methods= typeToFindIn.getMethods();
94         for (int i= 0; i < methods.length; i++) {
95             IMethod curr= methods[i];
96             if (isCompatibleMethod(filterMethod, curr, filterMethodOverrides) && !children.contains(curr)) {
97                 children.add(curr);
98             }
99         }
100     }
101     
102     private boolean hasCompatibleMethod(IMethod filterMethod, IType typeToFindIn) throws JavaModelException {
103         boolean filterMethodOverrides= initializeMethodOverrideTester(filterMethod, typeToFindIn);
104         IMethod[] methods= typeToFindIn.getMethods();
105         for (int i= 0; i < methods.length; i++) {
106             if (isCompatibleMethod(filterMethod, methods[i], filterMethodOverrides)) {
107                 return true;
108             }
109         }
110         return false;
111     }
112     
113     private boolean isCompatibleMethod(IMethod filterMethod, IMethod method, boolean filterOverrides) throws JavaModelException {
114         if (filterOverrides) {
115             return fMethodOverrideTester.isSubsignature(filterMethod, method);
116         } else {
117             return fMethodOverrideTester.isSubsignature(method, filterMethod);
118         }
119     }
120
121     /**
122      * The members to filter or <code>null</code> if member filtering is disabled.
123      */

124     public IMember[] getMemberFilter() {
125         return fMemberFilter;
126     }
127     
128     /**
129      * Sets a filter representing a working set or <code>null</code> if working sets are disabled.
130      */

131     public void setWorkingSetFilter(ViewerFilter filter) {
132         fWorkingSetFilter= filter;
133     }
134         
135     
136     protected final ITypeHierarchy getHierarchy() {
137         return fTypeHierarchy.getHierarchy();
138     }
139     
140     
141     /* (non-Javadoc)
142      * @see IReconciled#providesWorkingCopies()
143      */

144     public boolean providesWorkingCopies() {
145         return true;
146     }
147     
148     
149     /*
150      * Called for the root element
151      * @see IStructuredContentProvider#getElements
152      */

153     public Object JavaDoc[] getElements(Object JavaDoc parent) {
154         ArrayList JavaDoc types= new ArrayList JavaDoc();
155         getRootTypes(types);
156         for (int i= types.size() - 1; i >= 0; i--) {
157             IType curr= (IType) types.get(i);
158             try {
159                 if (!isInTree(curr)) {
160                     types.remove(i);
161                 }
162             } catch (JavaModelException e) {
163                 // ignore
164
}
165         }
166         return types.toArray();
167     }
168     
169     protected void getRootTypes(List JavaDoc res) {
170         ITypeHierarchy hierarchy= getHierarchy();
171         if (hierarchy != null) {
172             IType input= hierarchy.getType();
173             if (input != null) {
174                 res.add(input);
175             }
176             // opened on a region: dont show
177
}
178     }
179     
180     /**
181      * Hook to overwrite. Filter will be applied on the returned types
182      */

183     protected abstract void getTypesInHierarchy(IType type, List JavaDoc res);
184     
185     /**
186      * Hook to overwrite. Return null if parent is ambiguous.
187      */

188     protected abstract IType getParentType(IType type);
189     
190     
191     private boolean isInScope(IType type) {
192         if (fWorkingSetFilter != null && !fWorkingSetFilter.select(null, null, type)) {
193             return false;
194         }
195         
196         IJavaElement input= fTypeHierarchy.getInputElement();
197         int inputType= input.getElementType();
198         if (inputType == IJavaElement.TYPE) {
199             return true;
200         }
201         
202         IJavaElement parent= type.getAncestor(input.getElementType());
203         if (inputType == IJavaElement.PACKAGE_FRAGMENT) {
204             if (parent == null || parent.getElementName().equals(input.getElementName())) {
205                 return true;
206             }
207         } else if (input.equals(parent)) {
208             return true;
209         }
210         return false;
211     }
212     
213     /*
214      * Called for the tree children.
215      * @see ITreeContentProvider#getChildren
216      */

217     public Object JavaDoc[] getChildren(Object JavaDoc element) {
218         if (element instanceof IType) {
219             try {
220                 IType type= (IType)element;
221     
222                 List JavaDoc children= new ArrayList JavaDoc();
223                 if (fMemberFilter != null) {
224                     addFilteredMemberChildren(type, children);
225                 }
226     
227                 addTypeChildren(type, children);
228                 
229                 return children.toArray();
230             } catch (JavaModelException e) {
231                 // ignore
232
}
233         }
234         return NO_ELEMENTS;
235     }
236     
237     /*
238      * @see ITreeContentProvider#hasChildren
239      */

240     public boolean hasChildren(Object JavaDoc element) {
241         if (element instanceof IType) {
242             try {
243                 IType type= (IType) element;
244                 return hasTypeChildren(type) || (fMemberFilter != null && hasMemberFilterChildren(type));
245             } catch (JavaModelException e) {
246                 return false;
247             }
248         }
249         return false;
250     }
251     
252     private void addFilteredMemberChildren(IType parent, List JavaDoc children) throws JavaModelException {
253         for (int i= 0; i < fMemberFilter.length; i++) {
254             IMember member= fMemberFilter[i];
255             if (parent.equals(member.getDeclaringType())) {
256                 if (!children.contains(member)) {
257                     children.add(member);
258                 }
259             } else if (member instanceof IMethod) {
260                 addCompatibleMethods((IMethod) member, parent, children);
261             }
262         }
263     }
264         
265     private void addTypeChildren(IType type, List JavaDoc children) throws JavaModelException {
266         ArrayList JavaDoc types= new ArrayList JavaDoc();
267         getTypesInHierarchy(type, types);
268         int len= types.size();
269         for (int i= 0; i < len; i++) {
270             IType curr= (IType) types.get(i);
271             if (isInTree(curr)) {
272                 children.add(curr);
273             }
274         }
275     }
276     
277     protected final boolean isInTree(IType type) throws JavaModelException {
278         if (isInScope(type)) {
279             if (fMemberFilter != null) {
280                 return hasMemberFilterChildren(type) || hasTypeChildren(type);
281             } else {
282                 return true;
283             }
284         }
285         return hasTypeChildren(type);
286     }
287     
288     private boolean hasMemberFilterChildren(IType type) throws JavaModelException {
289         for (int i= 0; i < fMemberFilter.length; i++) {
290             IMember member= fMemberFilter[i];
291             if (type.equals(member.getDeclaringType())) {
292                 return true;
293             } else if (member instanceof IMethod) {
294                 if (hasCompatibleMethod((IMethod) member, type)) {
295                     return true;
296                 }
297             }
298         }
299         return false;
300     }
301         
302     private boolean hasTypeChildren(IType type) throws JavaModelException {
303         ArrayList JavaDoc types= new ArrayList JavaDoc();
304         getTypesInHierarchy(type, types);
305         int len= types.size();
306         for (int i= 0; i < len; i++) {
307             IType curr= (IType) types.get(i);
308             if (isInTree(curr)) {
309                 return true;
310             }
311         }
312         return false;
313     }
314     
315     /*
316      * @see IContentProvider#inputChanged
317      */

318     public void inputChanged(Viewer part, Object JavaDoc oldInput, Object JavaDoc newInput) {
319         Assert.isTrue(part instanceof TreeViewer);
320         fViewer= (TreeViewer)part;
321     }
322     
323     /*
324      * @see IContentProvider#dispose
325      */

326     public void dispose() {
327         fTypeHierarchy.removeChangedListener(fTypeHierarchyLifeCycleListener);
328         
329     }
330     
331     /*
332      * @see ITreeContentProvider#getParent
333      */

334     public Object JavaDoc getParent(Object JavaDoc element) {
335         if (element instanceof IMember) {
336             IMember member= (IMember) element;
337             if (member.getElementType() == IJavaElement.TYPE) {
338                 return getParentType((IType)member);
339             }
340             return member.getDeclaringType();
341         }
342         return null;
343     }
344     
345     protected final boolean isAnonymous(IType type) {
346         return type.getElementName().length() == 0;
347     }
348     
349     protected final boolean isAnonymousFromInterface(IType type) {
350         return isAnonymous(type) && fTypeHierarchy.getHierarchy().getSuperInterfaces(type).length != 0;
351     }
352     
353     protected final boolean isObject(IType type) {
354         return "Object".equals(type.getElementName()) && type.getDeclaringType() == null && "java.lang".equals(type.getPackageFragment().getElementName()); //$NON-NLS-1$//$NON-NLS-2$
355
}
356
357
358
359
360     
361 }
362
Popular Tags