KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 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.lang.reflect.InvocationTargetException JavaDoc;
14 import java.util.ArrayList JavaDoc;
15 import java.util.List JavaDoc;
16
17 import org.eclipse.core.runtime.IProgressMonitor;
18 import org.eclipse.core.runtime.OperationCanceledException;
19
20 import org.eclipse.jface.operation.IRunnableContext;
21 import org.eclipse.jface.operation.IRunnableWithProgress;
22
23 import org.eclipse.jdt.core.*;
24
25 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
26 import org.eclipse.jdt.internal.ui.JavaPlugin;
27
28 /**
29  * Manages a type hierarchy, to keep it refreshed, and to allow it to be shared.
30  */

31 public class TypeHierarchyLifeCycle implements ITypeHierarchyChangedListener, IElementChangedListener {
32     
33     private boolean fHierarchyRefreshNeeded;
34     private ITypeHierarchy fHierarchy;
35     private IJavaElement fInputElement;
36     private boolean fIsSuperTypesOnly;
37     
38     private List JavaDoc fChangeListeners;
39     
40     public TypeHierarchyLifeCycle() {
41         this(false);
42     }
43     
44     public TypeHierarchyLifeCycle(boolean isSuperTypesOnly) {
45         fHierarchy= null;
46         fInputElement= null;
47         fIsSuperTypesOnly= isSuperTypesOnly;
48         fChangeListeners= new ArrayList JavaDoc(2);
49     }
50     
51     public ITypeHierarchy getHierarchy() {
52         return fHierarchy;
53     }
54     
55     public IJavaElement getInputElement() {
56         return fInputElement;
57     }
58     
59     
60     public void freeHierarchy() {
61         if (fHierarchy != null) {
62             fHierarchy.removeTypeHierarchyChangedListener(this);
63             JavaCore.removeElementChangedListener(this);
64             fHierarchy= null;
65             fInputElement= null;
66         }
67     }
68     
69     public void removeChangedListener(ITypeHierarchyLifeCycleListener listener) {
70         fChangeListeners.remove(listener);
71     }
72     
73     public void addChangedListener(ITypeHierarchyLifeCycleListener listener) {
74         if (!fChangeListeners.contains(listener)) {
75             fChangeListeners.add(listener);
76         }
77     }
78     
79     private void fireChange(IType[] changedTypes) {
80         for (int i= fChangeListeners.size()-1; i>=0; i--) {
81             ITypeHierarchyLifeCycleListener curr= (ITypeHierarchyLifeCycleListener) fChangeListeners.get(i);
82             curr.typeHierarchyChanged(this, changedTypes);
83         }
84     }
85             
86     public void ensureRefreshedTypeHierarchy(final IJavaElement element, IRunnableContext context) throws InvocationTargetException JavaDoc, InterruptedException JavaDoc {
87         if (element == null || !element.exists()) {
88             freeHierarchy();
89             return;
90         }
91         boolean hierachyCreationNeeded= (fHierarchy == null || !element.equals(fInputElement));
92         
93         if (hierachyCreationNeeded || fHierarchyRefreshNeeded) {
94             
95             IRunnableWithProgress op= new IRunnableWithProgress() {
96                 public void run(IProgressMonitor pm) throws InvocationTargetException JavaDoc, InterruptedException JavaDoc {
97                     try {
98                         doHierarchyRefresh(element, pm);
99                     } catch (JavaModelException e) {
100                         throw new InvocationTargetException JavaDoc(e);
101                     } catch (OperationCanceledException e) {
102                         throw new InterruptedException JavaDoc();
103                     }
104                 }
105             };
106             fHierarchyRefreshNeeded= true;
107             context.run(true, true, op);
108             fHierarchyRefreshNeeded= false;
109         }
110     }
111     
112     private ITypeHierarchy createTypeHierarchy(IJavaElement element, IProgressMonitor pm) throws JavaModelException {
113         if (element.getElementType() == IJavaElement.TYPE) {
114             IType type= (IType) element;
115             if (fIsSuperTypesOnly) {
116                 return type.newSupertypeHierarchy(pm);
117             } else {
118                 return type.newTypeHierarchy(pm);
119             }
120         } else {
121             IRegion region= JavaCore.newRegion();
122             if (element.getElementType() == IJavaElement.JAVA_PROJECT) {
123                 // for projects only add the contained source folders
124
IPackageFragmentRoot[] roots= ((IJavaProject) element).getPackageFragmentRoots();
125                 for (int i= 0; i < roots.length; i++) {
126                     if (!roots[i].isExternal()) {
127                         region.add(roots[i]);
128                     }
129                 }
130             } else if (element.getElementType() == IJavaElement.PACKAGE_FRAGMENT) {
131                 IPackageFragmentRoot[] roots= element.getJavaProject().getPackageFragmentRoots();
132                 String JavaDoc name= element.getElementName();
133                 for (int i= 0; i < roots.length; i++) {
134                     IPackageFragment pack= roots[i].getPackageFragment(name);
135                     if (pack.exists()) {
136                         region.add(pack);
137                     }
138                 }
139             } else {
140                 region.add(element);
141             }
142             IJavaProject jproject= element.getJavaProject();
143             return jproject.newTypeHierarchy(region, pm);
144         }
145     }
146     
147     
148     public synchronized void doHierarchyRefresh(IJavaElement element, IProgressMonitor pm) throws JavaModelException {
149         boolean hierachyCreationNeeded= (fHierarchy == null || !element.equals(fInputElement));
150         // to ensure the order of the two listeners always remove / add listeners on operations
151
// on type hierarchies
152
if (fHierarchy != null) {
153             fHierarchy.removeTypeHierarchyChangedListener(this);
154             JavaCore.removeElementChangedListener(this);
155         }
156         if (hierachyCreationNeeded) {
157             fHierarchy= createTypeHierarchy(element, pm);
158             if (pm != null && pm.isCanceled()) {
159                 throw new OperationCanceledException();
160             }
161             fInputElement= element;
162         } else {
163             fHierarchy.refresh(pm);
164         }
165         fHierarchy.addTypeHierarchyChangedListener(this);
166         JavaCore.addElementChangedListener(this);
167         fHierarchyRefreshNeeded= false;
168     }
169     
170     /*
171      * @see ITypeHierarchyChangedListener#typeHierarchyChanged
172      */

173     public void typeHierarchyChanged(ITypeHierarchy typeHierarchy) {
174         fHierarchyRefreshNeeded= true;
175         fireChange(null);
176     }
177
178     /*
179      * @see IElementChangedListener#elementChanged(ElementChangedEvent)
180      */

181     public void elementChanged(ElementChangedEvent event) {
182         if (fChangeListeners.isEmpty()) {
183             return;
184         }
185         
186         if (fHierarchyRefreshNeeded) {
187             return;
188         } else {
189             ArrayList JavaDoc changedTypes= new ArrayList JavaDoc();
190             processDelta(event.getDelta(), changedTypes);
191             if (changedTypes.size() > 0) {
192                 fireChange((IType[]) changedTypes.toArray(new IType[changedTypes.size()]));
193             }
194         }
195     }
196     
197     /*
198      * Assume that the hierarchy is intact (no refresh needed)
199      */

200     private void processDelta(IJavaElementDelta delta, ArrayList JavaDoc changedTypes) {
201         IJavaElement element= delta.getElement();
202         switch (element.getElementType()) {
203             case IJavaElement.TYPE:
204                 processTypeDelta((IType) element, changedTypes);
205                 processChildrenDelta(delta, changedTypes); // (inner types)
206
break;
207             case IJavaElement.JAVA_MODEL:
208             case IJavaElement.JAVA_PROJECT:
209             case IJavaElement.PACKAGE_FRAGMENT_ROOT:
210             case IJavaElement.PACKAGE_FRAGMENT:
211                 processChildrenDelta(delta, changedTypes);
212                 break;
213             case IJavaElement.COMPILATION_UNIT:
214                 ICompilationUnit cu= (ICompilationUnit)element;
215                 if (!JavaModelUtil.isPrimary(cu)) {
216                     return;
217                 }
218                 
219                 if (delta.getKind() == IJavaElementDelta.CHANGED && isPossibleStructuralChange(delta.getFlags())) {
220                     try {
221                         if (cu.exists()) {
222                             IType[] types= cu.getAllTypes();
223                             for (int i= 0; i < types.length; i++) {
224                                 processTypeDelta(types[i], changedTypes);
225                             }
226                         }
227                     } catch (JavaModelException e) {
228                         JavaPlugin.log(e);
229                     }
230                 } else {
231                     processChildrenDelta(delta, changedTypes);
232                 }
233                 break;
234             case IJavaElement.CLASS_FILE:
235                 if (delta.getKind() == IJavaElementDelta.CHANGED) {
236                     IType type= ((IClassFile) element).getType();
237                     processTypeDelta(type, changedTypes);
238                 } else {
239                     processChildrenDelta(delta, changedTypes);
240                 }
241                 break;
242         }
243     }
244     
245     private boolean isPossibleStructuralChange(int flags) {
246         return (flags & (IJavaElementDelta.F_CONTENT | IJavaElementDelta.F_FINE_GRAINED)) == IJavaElementDelta.F_CONTENT;
247     }
248     
249     private void processTypeDelta(IType type, ArrayList JavaDoc changedTypes) {
250         if (getHierarchy().contains(type)) {
251             changedTypes.add(type);
252         }
253     }
254     
255     private void processChildrenDelta(IJavaElementDelta delta, ArrayList JavaDoc changedTypes) {
256         IJavaElementDelta[] children= delta.getAffectedChildren();
257         for (int i= 0; i < children.length; i++) {
258             processDelta(children[i], changedTypes); // recursive
259
}
260     }
261     
262
263 }
264
Popular Tags