KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > ui > browsing > JavaBrowsingContentProvider


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.browsing;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Arrays JavaDoc;
15 import java.util.Collection JavaDoc;
16 import java.util.Iterator JavaDoc;
17 import java.util.List JavaDoc;
18
19 import org.eclipse.core.resources.IResource;
20
21 import org.eclipse.swt.widgets.Control;
22 import org.eclipse.swt.widgets.Display;
23
24 import org.eclipse.jface.viewers.AbstractTreeViewer;
25 import org.eclipse.jface.viewers.IBasicPropertyConstants;
26 import org.eclipse.jface.viewers.ListViewer;
27 import org.eclipse.jface.viewers.StructuredViewer;
28 import org.eclipse.jface.viewers.TableViewer;
29 import org.eclipse.jface.viewers.Viewer;
30
31 import org.eclipse.jdt.core.ElementChangedEvent;
32 import org.eclipse.jdt.core.IClassFile;
33 import org.eclipse.jdt.core.ICompilationUnit;
34 import org.eclipse.jdt.core.IElementChangedListener;
35 import org.eclipse.jdt.core.IImportContainer;
36 import org.eclipse.jdt.core.IJavaElement;
37 import org.eclipse.jdt.core.IJavaElementDelta;
38 import org.eclipse.jdt.core.IJavaProject;
39 import org.eclipse.jdt.core.IPackageDeclaration;
40 import org.eclipse.jdt.core.IPackageFragment;
41 import org.eclipse.jdt.core.IPackageFragmentRoot;
42 import org.eclipse.jdt.core.IParent;
43 import org.eclipse.jdt.core.ISourceReference;
44 import org.eclipse.jdt.core.IType;
45 import org.eclipse.jdt.core.IWorkingCopy;
46 import org.eclipse.jdt.core.JavaCore;
47 import org.eclipse.jdt.core.JavaModelException;
48
49 import org.eclipse.jdt.ui.StandardJavaElementContentProvider;
50
51 import org.eclipse.jdt.internal.ui.JavaPlugin;
52
53 class JavaBrowsingContentProvider extends StandardJavaElementContentProvider implements IElementChangedListener {
54
55     private StructuredViewer fViewer;
56     private Object JavaDoc fInput;
57     private JavaBrowsingPart fBrowsingPart;
58     private int fReadsInDisplayThread;
59
60
61     public JavaBrowsingContentProvider(boolean provideMembers, JavaBrowsingPart browsingPart) {
62         super(provideMembers);
63         fBrowsingPart= browsingPart;
64         fViewer= fBrowsingPart.getViewer();
65         JavaCore.addElementChangedListener(this);
66     }
67
68     public boolean hasChildren(Object JavaDoc element) {
69         startReadInDisplayThread();
70         try{
71             return super.hasChildren(element);
72         } finally {
73             finishedReadInDisplayThread();
74         }
75     }
76
77     public Object JavaDoc[] getChildren(Object JavaDoc element) {
78         if (!exists(element))
79             return NO_CHILDREN;
80
81         startReadInDisplayThread();
82         try {
83             if (element instanceof Collection JavaDoc) {
84                 Collection JavaDoc elements= (Collection JavaDoc)element;
85                 if (elements.isEmpty())
86                     return NO_CHILDREN;
87                 Object JavaDoc[] result= new Object JavaDoc[0];
88                 Iterator JavaDoc iter= ((Collection JavaDoc)element).iterator();
89                 while (iter.hasNext()) {
90                     Object JavaDoc[] children= getChildren(iter.next());
91                     if (children != NO_CHILDREN)
92                         result= concatenate(result, children);
93                 }
94                 return result;
95             }
96             if (element instanceof IPackageFragment)
97                 return getPackageContents((IPackageFragment)element);
98             if (fProvideMembers && element instanceof IType)
99                 return getChildren((IType)element);
100             if (fProvideMembers && element instanceof ISourceReference && element instanceof IParent)
101                 return removeImportAndPackageDeclarations(super.getChildren(element));
102             if (element instanceof IJavaProject)
103                 return getPackageFragmentRoots((IJavaProject)element);
104             return super.getChildren(element);
105         } catch (JavaModelException e) {
106             return NO_CHILDREN;
107         } finally {
108             finishedReadInDisplayThread();
109         }
110     }
111
112     private Object JavaDoc[] getPackageContents(IPackageFragment fragment) throws JavaModelException {
113         ISourceReference[] sourceRefs;
114         if (fragment.getKind() == IPackageFragmentRoot.K_SOURCE) {
115             sourceRefs= fragment.getCompilationUnits();
116         }
117         else {
118             IClassFile[] classFiles= fragment.getClassFiles();
119             List JavaDoc topLevelClassFile= new ArrayList JavaDoc();
120             for (int i= 0; i < classFiles.length; i++) {
121                 IType type= classFiles[i].getType();
122                 if (type != null && type.getDeclaringType() == null && !type.isAnonymous() && !type.isLocal())
123                     topLevelClassFile.add(classFiles[i]);
124             }
125             sourceRefs= (ISourceReference[])topLevelClassFile.toArray(new ISourceReference[topLevelClassFile.size()]);
126         }
127
128         Object JavaDoc[] result= new Object JavaDoc[0];
129         for (int i= 0; i < sourceRefs.length; i++)
130             result= concatenate(result, removeImportAndPackageDeclarations(getChildren(sourceRefs[i])));
131         return concatenate(result, fragment.getNonJavaResources());
132     }
133
134     private Object JavaDoc[] removeImportAndPackageDeclarations(Object JavaDoc[] members) {
135         ArrayList JavaDoc tempResult= new ArrayList JavaDoc(members.length);
136         for (int i= 0; i < members.length; i++)
137             if (!(members[i] instanceof IImportContainer) && !(members[i] instanceof IPackageDeclaration))
138                 tempResult.add(members[i]);
139         return tempResult.toArray();
140     }
141
142     private Object JavaDoc[] getChildren(IType type) throws JavaModelException{
143         IParent parent;
144         if (type.isBinary())
145             parent= type.getClassFile();
146         else {
147             parent= type.getCompilationUnit();
148         }
149         if (type.getDeclaringType() != null)
150             return type.getChildren();
151
152         // Add import declarations
153
IJavaElement[] members= parent.getChildren();
154         ArrayList JavaDoc tempResult= new ArrayList JavaDoc(members.length);
155         for (int i= 0; i < members.length; i++)
156             if ((members[i] instanceof IImportContainer))
157                 tempResult.add(members[i]);
158         tempResult.addAll(Arrays.asList(type.getChildren()));
159         return tempResult.toArray();
160     }
161
162     protected Object JavaDoc[] getPackageFragmentRoots(IJavaProject project) throws JavaModelException {
163         if (!project.getProject().isOpen())
164             return NO_CHILDREN;
165
166         IPackageFragmentRoot[] roots= project.getPackageFragmentRoots();
167         List JavaDoc list= new ArrayList JavaDoc(roots.length);
168         // filter out package fragments that correspond to projects and
169
// replace them with the package fragments directly
170
for (int i= 0; i < roots.length; i++) {
171             IPackageFragmentRoot root= roots[i];
172             if (!root.isExternal()) {
173                 Object JavaDoc[] children= root.getChildren();
174                 for (int k= 0; k < children.length; k++)
175                     list.add(children[k]);
176             }
177             else if (hasChildren(root)) {
178                 list.add(root);
179             }
180         }
181         return concatenate(list.toArray(), project.getNonJavaResources());
182     }
183
184     // ---------------- Element change handling
185

186     /* (non-Javadoc)
187      * Method declared on IContentProvider.
188      */

189     public void inputChanged(Viewer viewer, Object JavaDoc oldInput, Object JavaDoc newInput) {
190         super.inputChanged(viewer, oldInput, newInput);
191
192         if (newInput instanceof Collection JavaDoc) {
193             // Get a template object from the collection
194
Collection JavaDoc col= (Collection JavaDoc)newInput;
195             if (!col.isEmpty())
196                 newInput= col.iterator().next();
197             else
198                 newInput= null;
199         }
200         fInput= newInput;
201     }
202
203     /* (non-Javadoc)
204      * Method declared on IContentProvider.
205      */

206     public void dispose() {
207         super.dispose();
208         JavaCore.removeElementChangedListener(this);
209     }
210
211     /* (non-Javadoc)
212      * Method declared on IElementChangedListener.
213      */

214     public void elementChanged(final ElementChangedEvent event) {
215         try {
216             processDelta(event.getDelta());
217         } catch(JavaModelException e) {
218             JavaPlugin.log(e.getStatus());
219         }
220     }
221
222
223     /**
224      * Processes a delta recursively. When more than two children are affected the
225      * tree is fully refreshed starting at this node. The delta is processed in the
226      * current thread but the viewer updates are posted to the UI thread.
227      */

228     protected void processDelta(IJavaElementDelta delta) throws JavaModelException {
229         int kind= delta.getKind();
230         int flags= delta.getFlags();
231         final IJavaElement element= delta.getElement();
232         final boolean isElementValidForView= fBrowsingPart.isValidElement(element);
233
234         if (!getProvideWorkingCopy() && element instanceof IWorkingCopy && ((IWorkingCopy)element).isWorkingCopy())
235             return;
236
237         if (element != null && element.getElementType() == IJavaElement.COMPILATION_UNIT && !isOnClassPath((ICompilationUnit)element))
238             return;
239
240         // handle open and closing of a solution or project
241
if (((flags & IJavaElementDelta.F_CLOSED) != 0) || ((flags & IJavaElementDelta.F_OPENED) != 0)) {
242             postRefresh(null);
243             return;
244         }
245
246         if (kind == IJavaElementDelta.REMOVED) {
247             Object JavaDoc parent= internalGetParent(element);
248             if (isElementValidForView) {
249                 if (element instanceof IClassFile) {
250                     postRemove(((IClassFile)element).getType());
251                 } else if (element instanceof ICompilationUnit && !((ICompilationUnit)element).isWorkingCopy()) {
252                         postRefresh(null);
253                 } else if (element instanceof ICompilationUnit && ((ICompilationUnit)element).isWorkingCopy()) {
254                     if (getProvideWorkingCopy())
255                         postRefresh(null);
256                 } else if (parent instanceof ICompilationUnit && getProvideWorkingCopy() && !((ICompilationUnit)parent).isWorkingCopy()) {
257                     if (element instanceof IWorkingCopy && ((IWorkingCopy)element).isWorkingCopy()) {
258                         // working copy removed from system - refresh
259
postRefresh(null);
260                     }
261                 } else if (element instanceof IWorkingCopy && ((IWorkingCopy)element).isWorkingCopy() && parent != null && parent.equals(fInput))
262                     // closed editor - removing working copy
263
postRefresh(null);
264                 else
265                     postRemove(element);
266             }
267
268             if (fBrowsingPart.isAncestorOf(element, fInput)) {
269                 if (element instanceof IWorkingCopy && ((IWorkingCopy)element).isWorkingCopy()) {
270                     postAdjustInputAndSetSelection(((IJavaElement) fInput).getPrimaryElement());
271                 } else
272                     postAdjustInputAndSetSelection(null);
273             }
274
275             if (fInput != null && fInput.equals(element))
276                 postRefresh(null);
277
278             if (parent instanceof IPackageFragment && fBrowsingPart.isValidElement(parent)) {
279                 // refresh if package gets empty (might be filtered)
280
if (isPackageFragmentEmpty((IPackageFragment)parent) && fViewer.testFindItem(parent) != null)
281                         postRefresh(null);
282             }
283
284             return;
285         }
286         if (kind == IJavaElementDelta.ADDED && delta.getMovedFromElement() != null && element instanceof ICompilationUnit)
287             return;
288
289         if (kind == IJavaElementDelta.ADDED) {
290             if (isElementValidForView) {
291                 Object JavaDoc parent= internalGetParent(element);
292                 if (element instanceof IClassFile) {
293                     postAdd(parent, ((IClassFile)element).getType());
294                 } else if (element instanceof ICompilationUnit && !((ICompilationUnit)element).isWorkingCopy()) {
295                         postAdd(parent, ((ICompilationUnit)element).getTypes());
296                 } else if (parent instanceof ICompilationUnit && getProvideWorkingCopy() && !((ICompilationUnit)parent).isWorkingCopy()) {
297                     // do nothing
298
} else if (element instanceof IWorkingCopy && ((IWorkingCopy)element).isWorkingCopy()) {
299                     // new working copy comes to live
300
postRefresh(null);
301                 } else
302                     postAdd(parent, element);
303             } else if (fInput == null) {
304                 IJavaElement newInput= fBrowsingPart.findInputForJavaElement(element);
305                 if (newInput != null)
306                     postAdjustInputAndSetSelection(element);
307             } else if (element instanceof IType && fBrowsingPart.isValidInput(element)) {
308                 IJavaElement cu1= element.getAncestor(IJavaElement.COMPILATION_UNIT);
309                 IJavaElement cu2= ((IJavaElement)fInput).getAncestor(IJavaElement.COMPILATION_UNIT);
310                 if (cu1 != null && cu2 != null && cu1.equals(cu2))
311                     postAdjustInputAndSetSelection(element);
312             }
313             return;
314         }
315
316         if (kind == IJavaElementDelta.CHANGED) {
317             if (fInput != null && fInput.equals(element) && (flags & IJavaElementDelta.F_CHILDREN) != 0 && (flags & IJavaElementDelta.F_FINE_GRAINED) != 0) {
318                 postRefresh(null, true);
319                 return;
320             }
321             if (isElementValidForView && (flags & IJavaElementDelta.F_MODIFIERS) != 0) {
322                     postUpdateIcon(element);
323             }
324         }
325
326         if (isClassPathChange(delta))
327              // throw the towel and do a full refresh
328
postRefresh(null);
329
330         if ((flags & IJavaElementDelta.F_ARCHIVE_CONTENT_CHANGED) != 0 && fInput instanceof IJavaElement) {
331             IPackageFragmentRoot pkgRoot= (IPackageFragmentRoot)element;
332             IJavaElement inputsParent= ((IJavaElement)fInput).getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
333             if (pkgRoot.equals(inputsParent))
334                 postRefresh(null);
335         }
336
337         // the source attachment of a JAR has changed
338
if (element instanceof IPackageFragmentRoot && (((flags & IJavaElementDelta.F_SOURCEATTACHED) != 0 || ((flags & IJavaElementDelta.F_SOURCEDETACHED)) != 0)))
339             postUpdateIcon(element);
340
341         IJavaElementDelta[] affectedChildren= delta.getAffectedChildren();
342         if (affectedChildren.length > 1) {
343             // a package fragment might become non empty refresh from the parent
344
if (element instanceof IPackageFragment) {
345                 IJavaElement parent= (IJavaElement)internalGetParent(element);
346                 // avoid posting a refresh to an invisible parent
347
if (element.equals(fInput)) {
348                     postRefresh(element);
349                 } else {
350                     postRefresh(parent);
351                 }
352             }
353             // more than one child changed, refresh from here downwards
354
if (element instanceof IPackageFragmentRoot && isElementValidForView) {
355                 postRefresh(skipProjectPackageFragmentRoot((IPackageFragmentRoot)element));
356                 return;
357             }
358         }
359         for (int i= 0; i < affectedChildren.length; i++) {
360             processDelta(affectedChildren[i]);
361         }
362     }
363
364     private boolean isOnClassPath(ICompilationUnit element) throws JavaModelException {
365         IJavaProject project= element.getJavaProject();
366         if (project == null || !project.exists())
367             return false;
368         return project.isOnClasspath(element);
369     }
370
371     /**
372      * Updates the package icon
373      */

374      private void postUpdateIcon(final IJavaElement element) {
375         postRunnable(new Runnable JavaDoc() {
376             public void run() {
377                 Control ctrl= fViewer.getControl();
378                 if (ctrl != null && !ctrl.isDisposed())
379                     fViewer.update(element, new String JavaDoc[]{IBasicPropertyConstants.P_IMAGE});
380             }
381         });
382      }
383
384     private void postRefresh(final Object JavaDoc root, final boolean updateLabels) {
385         postRunnable(new Runnable JavaDoc() {
386             public void run() {
387                 Control ctrl= fViewer.getControl();
388                 if (ctrl != null && !ctrl.isDisposed())
389                     fViewer.refresh(root, updateLabels);
390             }
391         });
392     }
393
394     private void postRefresh(final Object JavaDoc root) {
395         postRefresh(root, false);
396     }
397
398     private void postAdd(final Object JavaDoc parent, final Object JavaDoc element) {
399         postAdd(parent, new Object JavaDoc[] {element});
400     }
401
402     private void postAdd(final Object JavaDoc parent, final Object JavaDoc[] elements) {
403         if (elements == null || elements.length <= 0)
404             return;
405
406         postRunnable(new Runnable JavaDoc() {
407             public void run() {
408                 Control ctrl= fViewer.getControl();
409                 if (ctrl != null && !ctrl.isDisposed()) {
410                     Object JavaDoc[] newElements= getNewElements(elements);
411                     if (fViewer instanceof AbstractTreeViewer) {
412                         if (fViewer.testFindItem(parent) == null) {
413                             Object JavaDoc root= ((AbstractTreeViewer)fViewer).getInput();
414                             if (root != null)
415                                 ((AbstractTreeViewer)fViewer).add(root, newElements);
416                         }
417                         else
418                             ((AbstractTreeViewer)fViewer).add(parent, newElements);
419                     }
420                     else if (fViewer instanceof ListViewer)
421                         ((ListViewer)fViewer).add(newElements);
422                     else if (fViewer instanceof TableViewer)
423                         ((TableViewer)fViewer).add(newElements);
424                     if (fViewer.testFindItem(elements[0]) != null)
425                         fBrowsingPart.adjustInputAndSetSelection(elements[0]);
426                 }
427             }
428         });
429     }
430
431     private Object JavaDoc[] getNewElements(Object JavaDoc[] elements) {
432         int elementsLength= elements.length;
433         ArrayList JavaDoc result= new ArrayList JavaDoc(elementsLength);
434         for (int i= 0; i < elementsLength; i++) {
435             Object JavaDoc element= elements[i];
436             if (fViewer.testFindItem(element) == null)
437                 result.add(element);
438         }
439         return result.toArray();
440     }
441
442     private void postRemove(final Object JavaDoc element) {
443         postRemove(new Object JavaDoc[] {element});
444     }
445
446     private void postRemove(final Object JavaDoc[] elements) {
447         if (elements.length <= 0)
448             return;
449
450         postRunnable(new Runnable JavaDoc() {
451             public void run() {
452                 Control ctrl= fViewer.getControl();
453                 if (ctrl != null && !ctrl.isDisposed()) {
454                     if (fViewer instanceof AbstractTreeViewer)
455                         ((AbstractTreeViewer)fViewer).remove(elements);
456                     else if (fViewer instanceof ListViewer)
457                         ((ListViewer)fViewer).remove(elements);
458                     else if (fViewer instanceof TableViewer)
459                         ((TableViewer)fViewer).remove(elements);
460                 }
461             }
462         });
463     }
464
465     private void postAdjustInputAndSetSelection(final Object JavaDoc element) {
466         postRunnable(new Runnable JavaDoc() {
467             public void run() {
468                 Control ctrl= fViewer.getControl();
469                 if (ctrl != null && !ctrl.isDisposed()) {
470                     ctrl.setRedraw(false);
471                     fBrowsingPart.adjustInputAndSetSelection(element);
472                     ctrl.setRedraw(true);
473                 }
474             }
475         });
476     }
477
478     protected void startReadInDisplayThread() {
479         if (isDisplayThread())
480             fReadsInDisplayThread++;
481     }
482
483     protected void finishedReadInDisplayThread() {
484         if (isDisplayThread())
485             fReadsInDisplayThread--;
486     }
487
488     private boolean isDisplayThread() {
489         Control ctrl= fViewer.getControl();
490         if (ctrl == null)
491             return false;
492
493         Display currentDisplay= Display.getCurrent();
494         return currentDisplay != null && currentDisplay.equals(ctrl.getDisplay());
495     }
496
497     private void postRunnable(final Runnable JavaDoc r) {
498         Control ctrl= fViewer.getControl();
499         if (ctrl != null && !ctrl.isDisposed()) {
500             fBrowsingPart.setProcessSelectionEvents(false);
501             try {
502                 if (isDisplayThread() && fReadsInDisplayThread == 0)
503                     ctrl.getDisplay().syncExec(r);
504                 else
505                     ctrl.getDisplay().asyncExec(r);
506             } finally {
507                 fBrowsingPart.setProcessSelectionEvents(true);
508             }
509         }
510     }
511
512     /**
513      * Returns the parent for the element.
514      * <p>
515      * Note: This method will return a working copy if the
516      * parent is a working copy. The super class implementation
517      * returns the original element instead.
518      * </p>
519      */

520     protected Object JavaDoc internalGetParent(Object JavaDoc element) {
521         if (element instanceof IJavaProject) {
522             return ((IJavaProject)element).getJavaModel();
523         }
524         // try to map resources to the containing package fragment
525
if (element instanceof IResource) {
526             IResource parent= ((IResource)element).getParent();
527             Object JavaDoc jParent= JavaCore.create(parent);
528             if (jParent != null)
529                 return jParent;
530             return parent;
531         }
532
533         // for package fragments that are contained in a project package fragment
534
// we have to skip the package fragment root as the parent.
535
if (element instanceof IPackageFragment) {
536             IPackageFragmentRoot parent= (IPackageFragmentRoot)((IPackageFragment)element).getParent();
537             return skipProjectPackageFragmentRoot(parent);
538         }
539         if (element instanceof IJavaElement)
540             return ((IJavaElement)element).getParent();
541
542         return null;
543     }
544 }
545
Popular Tags