]>
Commit | Line | Data |
---|---|---|
1b2798f6 EK |
1 | /******************************************************************************* |
2 | * Copyright (c) 2000, 2011 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.ui; | |
12 | ||
13 | import java.util.ArrayList; | |
14 | import java.util.List; | |
15 | ||
16 | import org.eclipse.core.runtime.CoreException; | |
17 | ||
18 | import org.eclipse.core.resources.IFile; | |
19 | import org.eclipse.core.resources.IFolder; | |
20 | import org.eclipse.core.resources.IProject; | |
21 | import org.eclipse.core.resources.IResource; | |
22 | ||
23 | import org.eclipse.jface.viewers.ITreeContentProvider; | |
24 | import org.eclipse.jface.viewers.Viewer; | |
25 | ||
26 | import org.eclipse.jdt.core.IClassFile; | |
27 | import org.eclipse.jdt.core.ICompilationUnit; | |
28 | import org.eclipse.jdt.core.IJarEntryResource; | |
29 | import org.eclipse.jdt.core.IJavaElement; | |
30 | import org.eclipse.jdt.core.IJavaElementDelta; | |
31 | import org.eclipse.jdt.core.IJavaModel; | |
32 | import org.eclipse.jdt.core.IJavaProject; | |
33 | import org.eclipse.jdt.core.IPackageFragment; | |
34 | import org.eclipse.jdt.core.IPackageFragmentRoot; | |
35 | import org.eclipse.jdt.core.IParent; | |
36 | import org.eclipse.jdt.core.ISourceReference; | |
37 | import org.eclipse.jdt.core.ITypeRoot; | |
38 | import org.eclipse.jdt.core.JavaCore; | |
39 | import org.eclipse.jdt.core.JavaModelException; | |
40 | ||
41 | import org.eclipse.jdt.internal.ui.JavaPlugin; | |
42 | import org.eclipse.jdt.internal.ui.actions.ActionUtil; | |
43 | import org.eclipse.jdt.internal.ui.javaeditor.JavaEditorBreadcrumb.JavaEditorBreadcrumbContentProvider; | |
44 | ||
45 | /** | |
46 | * A base content provider for Java elements. It provides access to the | |
47 | * Java element hierarchy without listening to changes in the Java model. | |
48 | * If updating the presentation on Java model change is required than | |
49 | * clients have to subclass, listen to Java model changes and have to update | |
50 | * the UI using corresponding methods provided by the JFace viewers or their | |
51 | * own UI presentation. | |
52 | * <p> | |
53 | * The following Java element hierarchy is surfaced by this content provider: | |
54 | * <p> | |
55 | * <pre> | |
56 | Java model (<code>IJavaModel</code>) | |
57 | Java project (<code>IJavaProject</code>) | |
58 | package fragment root (<code>IPackageFragmentRoot</code>) | |
59 | package fragment (<code>IPackageFragment</code>) | |
60 | compilation unit (<code>ICompilationUnit</code>) | |
61 | binary class file (<code>IClassFile</code>) | |
62 | * </pre> | |
63 | * </p> | |
64 | * <p> | |
65 | * Note that when the entire Java project is declared to be package fragment root, | |
66 | * the corresponding package fragment root element that normally appears between the | |
67 | * Java project and the package fragments is automatically filtered out. | |
68 | * </p> | |
69 | * | |
70 | * @since 2.0 | |
71 | */ | |
72 | public class StandardJavaElementContentProvider implements ITreeContentProvider, IWorkingCopyProvider { | |
73 | ||
74 | protected static final Object[] NO_CHILDREN= new Object[0]; | |
75 | protected boolean fProvideMembers; | |
76 | protected boolean fProvideWorkingCopy; | |
77 | ||
78 | /** | |
79 | * Creates a new content provider. The content provider does not | |
80 | * provide members of compilation units or class files. | |
81 | */ | |
82 | public StandardJavaElementContentProvider() { | |
83 | this(false); | |
84 | } | |
85 | ||
86 | /** | |
87 | * @param provideMembers if <code>true</code> members below compilation units | |
88 | * @param provideWorkingCopy if <code>true</code> working copies are provided | |
89 | * @deprecated Use {@link #StandardJavaElementContentProvider(boolean)} instead. | |
90 | * Since 3.0 compilation unit children are always provided as working copies. The Java Model | |
91 | * does not support the 'original' mode anymore. | |
92 | */ | |
93 | public StandardJavaElementContentProvider(boolean provideMembers, boolean provideWorkingCopy) { | |
94 | this(provideMembers); | |
95 | } | |
96 | ||
97 | ||
98 | /** | |
99 | * Creates a new <code>StandardJavaElementContentProvider</code>. | |
100 | * | |
101 | * @param provideMembers if <code>true</code> members below compilation units | |
102 | * and class files are provided. | |
103 | */ | |
104 | public StandardJavaElementContentProvider(boolean provideMembers) { | |
105 | fProvideMembers= provideMembers; | |
106 | fProvideWorkingCopy= provideMembers; | |
107 | } | |
108 | ||
109 | /** | |
110 | * Returns whether members are provided when asking | |
111 | * for a compilation units or class file for its children. | |
112 | * | |
113 | * @return <code>true</code> if the content provider provides members; | |
114 | * otherwise <code>false</code> is returned | |
115 | */ | |
116 | public boolean getProvideMembers() { | |
117 | return fProvideMembers; | |
118 | } | |
119 | ||
120 | /** | |
121 | * Sets whether the content provider is supposed to return members | |
122 | * when asking a compilation unit or class file for its children. | |
123 | * | |
124 | * @param b if <code>true</code> then members are provided. | |
125 | * If <code>false</code> compilation units and class files are the | |
126 | * leaves provided by this content provider. | |
127 | */ | |
128 | public void setProvideMembers(boolean b) { | |
129 | //hello | |
130 | fProvideMembers= b; | |
131 | } | |
132 | ||
133 | /** | |
134 | * @return returns <code>true</code> if working copies are provided | |
135 | * @deprecated Since 3.0 compilation unit children are always provided as working copies. The Java model | |
136 | * does not support the 'original' mode anymore. | |
137 | */ | |
138 | public boolean getProvideWorkingCopy() { | |
139 | return fProvideWorkingCopy; | |
140 | } | |
141 | ||
142 | /** | |
143 | * @param b specifies if working copies should be provided | |
144 | * @deprecated Since 3.0 compilation unit children are always provided from the working copy. The Java model | |
145 | * offers a unified world and does not support the 'original' mode anymore. | |
146 | */ | |
147 | public void setProvideWorkingCopy(boolean b) { | |
148 | fProvideWorkingCopy= b; | |
149 | } | |
150 | ||
151 | /* (non-Javadoc) | |
152 | * @see IWorkingCopyProvider#providesWorkingCopies() | |
153 | */ | |
154 | public boolean providesWorkingCopies() { | |
155 | return getProvideWorkingCopy(); | |
156 | } | |
157 | ||
158 | /* (non-Javadoc) | |
159 | * Method declared on IStructuredContentProvider. | |
160 | */ | |
161 | public Object[] getElements(Object parent) { | |
162 | return getChildren(parent); | |
163 | } | |
164 | ||
165 | /* (non-Javadoc) | |
166 | * Method declared on IContentProvider. | |
167 | */ | |
168 | public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { | |
169 | } | |
170 | ||
171 | /* (non-Javadoc) | |
172 | * Method declared on IContentProvider. | |
173 | */ | |
174 | public void dispose() { | |
175 | } | |
176 | ||
177 | /* (non-Javadoc) | |
178 | * Method declared on ITreeContentProvider. | |
179 | */ | |
180 | public Object[] getChildren(Object element) { | |
181 | if (!exists(element)) | |
182 | return NO_CHILDREN; | |
183 | ||
184 | try { | |
185 | if (element instanceof IJavaModel) | |
186 | return getJavaProjects((IJavaModel)element); | |
187 | ||
188 | if (element instanceof IJavaProject) | |
189 | return getPackageFragmentRoots((IJavaProject)element); | |
190 | ||
191 | if (element instanceof IPackageFragmentRoot) | |
192 | return getPackageFragmentRootContent((IPackageFragmentRoot)element); | |
193 | ||
194 | if (element instanceof IPackageFragment) | |
195 | return getPackageContent((IPackageFragment)element); | |
196 | ||
197 | if (element instanceof IFolder) | |
198 | return getFolderContent((IFolder)element); | |
199 | ||
200 | if (element instanceof IJarEntryResource) { | |
201 | return ((IJarEntryResource) element).getChildren(); | |
202 | } | |
203 | ||
204 | if (getProvideMembers() && element instanceof ISourceReference && element instanceof IParent) { | |
205 | return ((IParent)element).getChildren(); | |
206 | } | |
207 | } catch (CoreException e) { | |
208 | return NO_CHILDREN; | |
209 | } | |
210 | return NO_CHILDREN; | |
211 | } | |
212 | ||
213 | /* (non-Javadoc) | |
214 | * @see ITreeContentProvider | |
215 | */ | |
216 | public boolean hasChildren(Object element) { | |
217 | if (getProvideMembers()) { | |
218 | // assume CUs and class files are never empty | |
219 | if (element instanceof ICompilationUnit || | |
220 | element instanceof IClassFile) { | |
221 | return true; | |
222 | } | |
223 | } else { | |
224 | // don't allow to drill down into a compilation unit or class file | |
225 | if (element instanceof ICompilationUnit || | |
226 | element instanceof IClassFile || | |
227 | element instanceof IFile) | |
228 | return false; | |
229 | } | |
230 | ||
231 | if (element instanceof IJavaProject) { | |
232 | IJavaProject jp= (IJavaProject)element; | |
233 | if (!jp.getProject().isOpen()) { | |
234 | return false; | |
235 | } | |
236 | } | |
237 | ||
238 | if (element instanceof IParent) { | |
239 | try { | |
240 | // when we have Java children return true, else we fetch all the children | |
241 | if (((IParent)element).hasChildren()) | |
242 | return true; | |
243 | } catch(JavaModelException e) { | |
244 | return true; | |
245 | } | |
246 | } | |
247 | Object[] children= getChildren(element); | |
248 | return (children != null) && children.length > 0; | |
249 | } | |
250 | ||
251 | /* (non-Javadoc) | |
252 | * Method declared on ITreeContentProvider. | |
253 | */ | |
254 | public Object getParent(Object element) { | |
255 | if (!exists(element)) | |
256 | return null; | |
257 | return internalGetParent(element); | |
258 | } | |
259 | ||
260 | /** | |
261 | * Evaluates all children of a given {@link IPackageFragmentRoot}. Clients can override this method. | |
262 | * @param root The root to evaluate the children for. | |
263 | * @return The children of the root | |
264 | * @exception JavaModelException if the package fragment root does not exist or if an | |
265 | * exception occurs while accessing its corresponding resource | |
266 | * | |
267 | * @since 3.3 | |
268 | */ | |
269 | protected Object[] getPackageFragmentRootContent(IPackageFragmentRoot root) throws JavaModelException { | |
270 | IJavaElement[] fragments= root.getChildren(); | |
271 | if (isProjectPackageFragmentRoot(root)) { | |
272 | return fragments; | |
273 | } | |
274 | Object[] nonJavaResources= root.getNonJavaResources(); | |
275 | if (nonJavaResources == null) | |
276 | return fragments; | |
277 | return concatenate(fragments, nonJavaResources); | |
278 | } | |
279 | ||
280 | /** | |
281 | * Evaluates all children of a given {@link IJavaProject}. Clients can override this method. | |
282 | * @param project The Java project to evaluate the children for. | |
283 | * @return The children of the project. Typically these are package fragment roots but can also be other elements. | |
284 | * @exception JavaModelException if the Java project does not exist or if an | |
285 | * exception occurs while accessing its corresponding resource | |
286 | */ | |
287 | protected Object[] getPackageFragmentRoots(IJavaProject project) throws JavaModelException { | |
288 | if (!project.getProject().isOpen()) | |
289 | return NO_CHILDREN; | |
290 | ||
291 | IPackageFragmentRoot[] roots= project.getPackageFragmentRoots(); | |
292 | List<Object> list= new ArrayList<Object>(roots.length); | |
293 | // filter out package fragments that correspond to projects and | |
294 | // replace them with the package fragments directly | |
295 | for (int i= 0; i < roots.length; i++) { | |
296 | IPackageFragmentRoot root= roots[i]; | |
297 | if (isProjectPackageFragmentRoot(root)) { | |
298 | Object[] fragments= getPackageFragmentRootContent(root); | |
299 | for (int j= 0; j < fragments.length; j++) { | |
300 | list.add(fragments[j]); | |
301 | } | |
302 | } else { | |
303 | list.add(root); | |
304 | } | |
305 | } | |
306 | Object[] resources= project.getNonJavaResources(); | |
307 | for (int i= 0; i < resources.length; i++) { | |
308 | list.add(resources[i]); | |
309 | } | |
310 | return list.toArray(); | |
311 | } | |
312 | ||
313 | /** | |
314 | * Evaluates all Java projects of a given {@link IJavaModel}. Clients can override this method. | |
315 | * | |
316 | * @param jm the Java model | |
317 | * @return the projects | |
318 | * @throws JavaModelException thrown if accessing the model failed | |
319 | */ | |
320 | protected Object[] getJavaProjects(IJavaModel jm) throws JavaModelException { | |
321 | return jm.getJavaProjects(); | |
322 | } | |
323 | ||
324 | /** | |
325 | * Evaluates all children of a given {@link IPackageFragment}. Clients can override this method. | |
326 | * @param fragment The fragment to evaluate the children for. | |
327 | * @return The children of the given package fragment. | |
328 | * @exception JavaModelException if the package fragment does not exist or if an | |
329 | * exception occurs while accessing its corresponding resource | |
330 | * | |
331 | * @since 3.3 | |
332 | */ | |
333 | protected Object[] getPackageContent(IPackageFragment fragment) throws JavaModelException { | |
334 | if (fragment.getKind() == IPackageFragmentRoot.K_SOURCE) { | |
335 | return concatenate(fragment.getCompilationUnits(), fragment.getNonJavaResources()); | |
336 | } | |
337 | return concatenate(fragment.getClassFiles(), fragment.getNonJavaResources()); | |
338 | } | |
339 | ||
340 | /** | |
341 | * Evaluates all children of a given {@link IFolder}. Clients can override this method. | |
342 | * @param folder The folder to evaluate the children for. | |
343 | * @return The children of the given folder. | |
344 | * @exception CoreException if the folder does not exist. | |
345 | * | |
346 | * @since 3.3 | |
347 | */ | |
348 | protected Object[] getFolderContent(IFolder folder) throws CoreException { | |
349 | IResource[] members= folder.members(); | |
350 | IJavaProject javaProject= JavaCore.create(folder.getProject()); | |
351 | if (javaProject == null || !javaProject.exists()) | |
352 | return members; | |
353 | boolean isFolderOnClasspath = javaProject.isOnClasspath(folder); | |
354 | List<IResource> nonJavaResources= new ArrayList<IResource>(); | |
355 | // Can be on classpath but as a member of non-java resource folder | |
356 | for (int i= 0; i < members.length; i++) { | |
357 | IResource member= members[i]; | |
358 | // A resource can also be a java element | |
359 | // in the case of exclusion and inclusion filters. | |
360 | // We therefore exclude Java elements from the list | |
361 | // of non-Java resources. | |
362 | if (isFolderOnClasspath) { | |
363 | if (javaProject.findPackageFragmentRoot(member.getFullPath()) == null) { | |
364 | nonJavaResources.add(member); | |
365 | } | |
366 | } else if (!javaProject.isOnClasspath(member)) { | |
367 | nonJavaResources.add(member); | |
368 | } else { | |
369 | IJavaElement element= JavaCore.create(member, javaProject); | |
370 | if (element instanceof IPackageFragmentRoot | |
371 | && javaProject.equals(element.getJavaProject()) | |
372 | && ((IPackageFragmentRoot)element).getKind() != IPackageFragmentRoot.K_SOURCE) { | |
373 | // don't skip libs and class folders on the classpath of their project | |
374 | nonJavaResources.add(member); | |
375 | } | |
376 | } | |
377 | } | |
378 | return nonJavaResources.toArray(); | |
379 | } | |
380 | ||
381 | /** | |
382 | * Tests if the a Java element delta contains a class path change | |
383 | * | |
384 | * @param delta the Java element delta | |
385 | * @return returns <code>true</code> if the delta contains a class path change | |
386 | */ | |
387 | protected boolean isClassPathChange(IJavaElementDelta delta) { | |
388 | ||
389 | // need to test the flags only for package fragment roots | |
390 | if (delta.getElement().getElementType() != IJavaElement.PACKAGE_FRAGMENT_ROOT) | |
391 | return false; | |
392 | ||
393 | int flags= delta.getFlags(); | |
394 | return (delta.getKind() == IJavaElementDelta.CHANGED && | |
395 | ((flags & IJavaElementDelta.F_ADDED_TO_CLASSPATH) != 0) || | |
396 | ((flags & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) != 0) || | |
397 | ((flags & IJavaElementDelta.F_REORDER) != 0)); | |
398 | } | |
399 | ||
400 | /** | |
401 | * Note: This method is for internal use only. Clients should not call this method. | |
402 | * | |
403 | * @param root the package fragment root | |
404 | * @return returns the element representing the root. | |
405 | * | |
406 | * @noreference This method is not intended to be referenced by clients. | |
407 | */ | |
408 | protected Object skipProjectPackageFragmentRoot(IPackageFragmentRoot root) { | |
409 | if (isProjectPackageFragmentRoot(root)) | |
410 | return root.getParent(); | |
411 | return root; | |
412 | } | |
413 | ||
414 | /** | |
415 | * Tests if the given element is a empty package fragment. | |
416 | * | |
417 | * @param element the element to test | |
418 | * @return returns <code>true</code> if the package fragment is empty | |
419 | * @throws JavaModelException thrown if accessing the element failed | |
420 | */ | |
421 | protected boolean isPackageFragmentEmpty(IJavaElement element) throws JavaModelException { | |
422 | if (element instanceof IPackageFragment) { | |
423 | IPackageFragment fragment= (IPackageFragment)element; | |
424 | if (fragment.exists() && !(fragment.hasChildren() || fragment.getNonJavaResources().length > 0) && fragment.hasSubpackages()) | |
425 | return true; | |
426 | } | |
427 | return false; | |
428 | } | |
429 | ||
430 | /** | |
431 | * Tests if the package fragment root is located on the project. | |
432 | * | |
433 | * @param root the package fragment root | |
434 | * @return returns <code>true</code> if the package fragment root is the located on the project | |
435 | */ | |
436 | protected boolean isProjectPackageFragmentRoot(IPackageFragmentRoot root) { | |
437 | IJavaProject javaProject= root.getJavaProject(); | |
438 | return javaProject != null && javaProject.getPath().equals(root.getPath()); | |
439 | } | |
440 | ||
441 | /** | |
442 | * Note: This method is for internal use only. Clients should not call this method. | |
443 | * | |
444 | * @param element the element to test | |
445 | * @return returns <code>true</code> if the element exists | |
446 | * | |
447 | * @noreference This method is not intended to be referenced by clients. | |
448 | */ | |
449 | protected boolean exists(Object element) { | |
450 | if (element == null) { | |
451 | return false; | |
452 | } | |
453 | if (element instanceof IResource) { | |
454 | return ((IResource)element).exists(); | |
455 | } | |
456 | if (element instanceof IJavaElement) { | |
457 | return ((IJavaElement)element).exists(); | |
458 | } | |
459 | return true; | |
460 | } | |
461 | ||
462 | /** | |
463 | * Note: This method is for internal use only. Clients should not call this method. | |
464 | * | |
465 | * @param element the element | |
466 | * @return the parent of the element | |
467 | * | |
468 | * @noreference This method is not intended to be referenced by clients. | |
469 | */ | |
470 | protected Object internalGetParent(Object element) { | |
471 | ||
472 | // try to map resources to the containing package fragment | |
473 | if (element instanceof IResource) { | |
474 | IResource parent= ((IResource)element).getParent(); | |
475 | IJavaElement jParent= JavaCore.create(parent); | |
476 | // http://bugs.eclipse.org/bugs/show_bug.cgi?id=31374 | |
477 | if (jParent != null && jParent.exists()) | |
478 | return jParent; | |
479 | return parent; | |
480 | } else if (element instanceof IJavaElement) { | |
481 | IJavaElement parent= ((IJavaElement) element).getParent(); | |
482 | // for package fragments that are contained in a project package fragment | |
483 | // we have to skip the package fragment root as the parent. | |
484 | if (element instanceof IPackageFragment) { | |
485 | return skipProjectPackageFragmentRoot((IPackageFragmentRoot) parent); | |
486 | } | |
487 | return parent; | |
488 | } else if (element instanceof IJarEntryResource) { | |
489 | return ((IJarEntryResource) element).getParent(); | |
490 | } | |
491 | return null; | |
492 | } | |
493 | ||
494 | public void generated_5709024900711033448(JavaEditorBreadcrumbContentProvider javaeditorbreadcrumbcontentprovider, Object inputElement) { | |
495 | if (inputElement instanceof IPackageFragment) { | |
496 | javaeditorbreadcrumbcontentprovider.fElements= javaeditorbreadcrumbcontentprovider.getPackageContent((IPackageFragment) inputElement); | |
497 | } else if (inputElement instanceof IProject) { | |
498 | IProject project= (IProject) inputElement; | |
499 | if (project.isAccessible()) { | |
500 | try { | |
501 | javaeditorbreadcrumbcontentprovider.fElements= ((IProject) inputElement).members(); | |
502 | } catch (CoreException e) { | |
503 | JavaPlugin.log(e); | |
504 | } | |
505 | } else { | |
506 | javaeditorbreadcrumbcontentprovider.fElements= new Object[0]; | |
507 | } | |
508 | } else if (inputElement instanceof IPackageFragmentRoot) { | |
509 | Object[] fragments= getChildren(inputElement); | |
510 | ||
511 | ArrayList<Object> packages= new ArrayList<Object>(); | |
512 | for (int i= 0; i < fragments.length; i++) { | |
513 | Object object= fragments[i]; | |
514 | if (object instanceof IPackageFragment) { | |
515 | try { | |
516 | if (((IPackageFragment) object).hasChildren()) | |
517 | packages.add(object); | |
518 | } catch (JavaModelException e) { | |
519 | JavaPlugin.log(e); | |
520 | packages.add(object); | |
521 | } | |
522 | } else { | |
523 | packages.add(object); | |
524 | } | |
525 | } | |
526 | javaeditorbreadcrumbcontentprovider.fElements= packages.toArray(); | |
527 | } else if (inputElement instanceof IJavaModel) { | |
528 | javaeditorbreadcrumbcontentprovider.fElements= javaeditorbreadcrumbcontentprovider.getAccessibleProjects((IJavaModel)inputElement); | |
529 | } else { | |
530 | javaeditorbreadcrumbcontentprovider.fElements= getChildren(inputElement); | |
531 | } | |
532 | } | |
533 | ||
534 | public Object generated_4346198621616378328(Object element) { | |
535 | Object result= getParent(element); | |
536 | ||
537 | if (result instanceof ITypeRoot) { | |
538 | if (ActionUtil.isOnBuildPath((IJavaElement) result)) { | |
539 | result= getParent(result); | |
540 | } else { | |
541 | result= ((ITypeRoot) result).getResource(); | |
542 | if (result instanceof IFile) | |
543 | result= getParent(result); | |
544 | } | |
545 | } | |
546 | return result; | |
547 | } | |
548 | ||
549 | /** | |
550 | * Utility method to concatenate two arrays. | |
551 | * | |
552 | * @param a1 the first array | |
553 | * @param a2 the second array | |
554 | * @return the concatenated array | |
555 | */ | |
556 | protected static Object[] concatenate(Object[] a1, Object[] a2) { | |
557 | int a1Len= a1.length; | |
558 | int a2Len= a2.length; | |
559 | if (a1Len == 0) return a2; | |
560 | if (a2Len == 0) return a1; | |
561 | Object[] res= new Object[a1Len + a2Len]; | |
562 | System.arraycopy(a1, 0, res, 0, a1Len); | |
563 | System.arraycopy(a2, 0, res, a1Len, a2Len); | |
564 | return res; | |
565 | } | |
566 | ||
567 | ||
568 | } |