1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.ui;
13 import java.util.ArrayList;
14 import java.util.List;
16 import net.sourceforge.phpdt.core.ICompilationUnit;
17 import net.sourceforge.phpdt.core.IJavaElement;
18 import net.sourceforge.phpdt.core.IJavaElementDelta;
19 import net.sourceforge.phpdt.core.IJavaModel;
20 import net.sourceforge.phpdt.core.IJavaProject;
21 import net.sourceforge.phpdt.core.IPackageFragment;
22 import net.sourceforge.phpdt.core.IPackageFragmentRoot;
23 import net.sourceforge.phpdt.core.IParent;
24 import net.sourceforge.phpdt.core.ISourceReference;
25 import net.sourceforge.phpdt.core.JavaCore;
26 import net.sourceforge.phpdt.core.JavaModelException;
27 import net.sourceforge.phpdt.internal.corext.util.JavaModelUtil;
29 import org.eclipse.core.resources.IFile;
30 import org.eclipse.core.resources.IFolder;
31 import org.eclipse.core.resources.IProject;
32 import org.eclipse.core.resources.IResource;
33 import org.eclipse.core.runtime.CoreException;
34 import org.eclipse.jface.viewers.ITreeContentProvider;
35 import org.eclipse.jface.viewers.Viewer;
38 * A base content provider for Java elements. It provides access to the Java
39 * element hierarchy without listening to changes in the Java model. If updating
40 * the presentation on Java model change is required than clients have to
41 * subclass, listen to Java model changes and have to update the UI using
42 * corresponding methods provided by the JFace viewers or their own UI
45 * The following Java element hierarchy is surfaced by this content provider:
59 * package fragment root (
61 * IPackageFragmentRoot
83 * Note that when the entire Java project is declared to be package fragment
84 * root, the corresponding package fragment root element that normally appears
85 * between the Java project and the package fragments is automatically filtered
88 * This content provider can optionally return working copy elements for members
89 * below compilation units. If enabled, working copy members are returned for
90 * those compilation units in the Java element hierarchy for which a shared
91 * working copy exists in JDT core.
93 * @see net.sourceforge.phpdt.ui.IWorkingCopyProvider
94 * @see JavaCore#getSharedWorkingCopies(net.sourceforge.phpdt.core.IBufferFactory)
98 public class StandardJavaElementContentProvider implements
99 ITreeContentProvider, IWorkingCopyProvider {
101 protected static final Object[] NO_CHILDREN = new Object[0];
103 protected boolean fProvideMembers = false;
105 protected boolean fProvideWorkingCopy = false;
108 * Creates a new content provider. The content provider does not provide
109 * members of compilation units or class files and it does not provide
110 * working copy elements.
112 public StandardJavaElementContentProvider() {
116 * Creates a new <code>StandardJavaElementContentProvider</code>.
118 * @param provideMembers
119 * if <code>true</code> members below compilation units and
120 * class files are provided.
121 * @param provideWorkingCopy
122 * if <code>true</code> the element provider provides working
123 * copies members of compilation units which have an associated
124 * working copy in JDT core. Otherwise only original elements are
127 public StandardJavaElementContentProvider(boolean provideMembers,
128 boolean provideWorkingCopy) {
129 fProvideMembers = provideMembers;
130 fProvideWorkingCopy = provideWorkingCopy;
134 * Returns whether members are provided when asking for a compilation units
135 * or class file for its children.
137 * @return <code>true</code> if the content provider provides members;
138 * otherwise <code>false</code> is returned
140 public boolean getProvideMembers() {
141 return fProvideMembers;
145 * Sets whether the content provider is supposed to return members when
146 * asking a compilation unit or class file for its children.
149 * if <code>true</code> then members are provided. If
150 * <code>false</code> compilation units and class files are the
151 * leaves provided by this content provider.
153 public void setProvideMembers(boolean b) {
158 * Returns whether the provided members are from a working copy or the
159 * original compilation unit.
161 * @return <code>true</code> if the content provider provides working copy
162 * members; otherwise <code>false</code> is returned
164 * @see #setProvideWorkingCopy(boolean)
166 public boolean getProvideWorkingCopy() {
167 return fProvideWorkingCopy;
171 * Sets whether the members are provided from a shared working copy that
172 * exists for a original compilation unit in the Java element hierarchy.
175 * if <code>true</code> members are provided from a working
176 * copy if one exists in JDT core. If <code>false</code> the
177 * provider always returns original elements.
179 public void setProvideWorkingCopy(boolean b) {
180 fProvideWorkingCopy = b;
186 * @see IWorkingCopyProvider#providesWorkingCopies()
188 public boolean providesWorkingCopies() {
189 return fProvideWorkingCopy;
193 * (non-Javadoc) Method declared on IStructuredContentProvider.
195 public Object[] getElements(Object parent) {
196 return getChildren(parent);
200 * (non-Javadoc) Method declared on IContentProvider.
202 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
206 * (non-Javadoc) Method declared on IContentProvider.
208 public void dispose() {
212 * (non-Javadoc) Method declared on ITreeContentProvider.
214 public Object[] getChildren(Object element) {
215 if (!exists(element))
219 if (element instanceof IJavaModel)
220 return getJavaProjects((IJavaModel) element);
222 // if (element instanceof IJavaProject)
223 // return getPackageFragmentRoots((IJavaProject)element);
225 if (element instanceof IPackageFragmentRoot)
226 return getPackageFragments((IPackageFragmentRoot) element);
228 // if (element instanceof IPackageFragment)
229 // return getPackageContents((IPackageFragment)element);
231 if (element instanceof IFolder)
232 return getResources((IFolder) element);
234 if (fProvideMembers && element instanceof ISourceReference
235 && element instanceof IParent) {
236 if (fProvideWorkingCopy && element instanceof ICompilationUnit) {
237 element = JavaModelUtil
238 .toWorkingCopy((ICompilationUnit) element);
240 return ((IParent) element).getChildren();
242 } catch (JavaModelException e) {
251 * @see ITreeContentProvider
253 public boolean hasChildren(Object element) {
254 if (fProvideMembers) {
255 // assume CUs and class files are never empty
256 if (element instanceof ICompilationUnit) {
258 // element instanceof IClassFile) {
262 // don't allow to drill down into a compilation unit or class file
263 if (element instanceof ICompilationUnit ||
264 // element instanceof IClassFile ||
265 element instanceof IFile)
269 if (element instanceof IJavaProject) {
270 IJavaProject jp = (IJavaProject) element;
271 if (!jp.getProject().isOpen()) {
276 if (element instanceof IParent) {
278 // when we have Java children return true, else we fetch all the
280 if (((IParent) element).hasChildren())
282 } catch (JavaModelException e) {
286 Object[] children = getChildren(element);
287 return (children != null) && children.length > 0;
291 * (non-Javadoc) Method declared on ITreeContentProvider.
293 public Object getParent(Object element) {
294 if (!exists(element))
296 return internalGetParent(element);
299 private Object[] getPackageFragments(IPackageFragmentRoot root)
300 throws JavaModelException {
301 IJavaElement[] fragments = root.getChildren();
302 // Object[] nonJavaResources= root.getNonJavaResources();
303 // if (nonJavaResources == null)
305 // return concatenate(fragments, nonJavaResources);
309 * Note: This method is for internal use only. Clients should not call this
312 // protected Object[] getPackageFragmentRoots(IJavaProject project) throws
313 // JavaModelException {
314 // if (!project.getProject().isOpen())
315 // return NO_CHILDREN;
317 // IPackageFragmentRoot[] roots= project.getPackageFragmentRoots();
318 // List list= new ArrayList(roots.length);
319 // // filter out package fragments that correspond to projects and
320 // // replace them with the package fragments directly
321 // for (int i= 0; i < roots.length; i++) {
322 // IPackageFragmentRoot root= (IPackageFragmentRoot)roots[i];
323 // if (isProjectPackageFragmentRoot(root)) {
324 // Object[] children= root.getChildren();
325 // for (int k= 0; k < children.length; k++)
326 // list.add(children[k]);
328 // else if (hasChildren(root)) {
332 // return concatenate(list.toArray(), project.getNonJavaResources());
335 * Note: This method is for internal use only. Clients should not call this
338 protected Object[] getJavaProjects(IJavaModel jm) throws JavaModelException {
339 return jm.getJavaProjects();
342 // private Object[] getPackageContents(IPackageFragment fragment) throws
343 // JavaModelException {
344 // if (fragment.getKind() == IPackageFragmentRoot.K_SOURCE) {
345 // return concatenate(fragment.getCompilationUnits(),
346 // fragment.getNonJavaResources());
348 // return concatenate(fragment.getClassFiles(),
349 // fragment.getNonJavaResources());
352 private Object[] getResources(IFolder folder) {
354 // filter out folders that are package fragment roots
355 Object[] members = folder.members();
356 List nonJavaResources = new ArrayList();
357 for (int i = 0; i < members.length; i++) {
358 Object o = members[i];
359 // A folder can also be a package fragement root in the
362 // + src <- source folder
363 // + excluded <- excluded from class path
364 // + included <- a new source folder.
365 // Included is a member of excluded, but since it is rendered as
367 // folder we have to exclude it as a normal child.
368 if (o instanceof IFolder) {
369 IJavaElement element = JavaCore.create((IFolder) o);
370 if (element instanceof IPackageFragmentRoot
371 && element.exists()) {
375 nonJavaResources.add(o);
377 return nonJavaResources.toArray();
378 } catch (CoreException e) {
384 * Note: This method is for internal use only. Clients should not call this
387 protected boolean isClassPathChange(IJavaElementDelta delta) {
389 // need to test the flags only for package fragment roots
390 if (delta.getElement().getElementType() != IJavaElement.PACKAGE_FRAGMENT_ROOT)
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) || ((flags & IJavaElementDelta.F_REORDER) != 0));
400 * Note: This method is for internal use only. Clients should not call this
403 protected Object skipProjectPackageFragmentRoot(IPackageFragmentRoot root) {
405 if (isProjectPackageFragmentRoot(root))
406 return root.getParent();
408 } catch (JavaModelException e) {
414 * Note: This method is for internal use only. Clients should not call this
417 protected boolean isPackageFragmentEmpty(IJavaElement element)
418 throws JavaModelException {
419 if (element instanceof IPackageFragment) {
420 IPackageFragment fragment = (IPackageFragment) element;
421 if (!(fragment.hasChildren()))
423 // fragment.getNonJavaResources().length > 0) &&
424 // fragment.hasSubpackages())
431 * Note: This method is for internal use only. Clients should not call this
434 protected boolean isProjectPackageFragmentRoot(IPackageFragmentRoot root)
435 throws JavaModelException {
436 IResource resource = root.getResource();
437 return (resource instanceof IProject);
441 * Note: This method is for internal use only. Clients should not call this
444 protected boolean exists(Object element) {
445 if (element == null) {
448 if (element instanceof IResource) {
449 return ((IResource) element).exists();
451 if (element instanceof IJavaElement) {
452 return ((IJavaElement) element).exists();
458 * Note: This method is for internal use only. Clients should not call this
461 protected Object internalGetParent(Object element) {
462 if (element instanceof IJavaProject) {
463 return ((IJavaProject) element).getJavaModel();
465 // try to map resources to the containing package fragment
466 if (element instanceof IResource) {
467 IResource parent = ((IResource) element).getParent();
468 IJavaElement jParent = JavaCore.create(parent);
469 // http://bugs.eclipse.org/bugs/show_bug.cgi?id=31374
470 if (jParent != null && jParent.exists())
475 // for package fragments that are contained in a project package
477 // we have to skip the package fragment root as the parent.
478 if (element instanceof IPackageFragment) {
479 IPackageFragmentRoot parent = (IPackageFragmentRoot) ((IPackageFragment) element)
481 return skipProjectPackageFragmentRoot(parent);
483 if (element instanceof IJavaElement) {
484 IJavaElement candidate = ((IJavaElement) element).getParent();
485 // If the parent is a CU we might have shown working copy elements
486 // below CU level. If so
487 // return the original element instead of the working copy.
488 if (candidate != null
489 && candidate.getElementType() == IJavaElement.COMPILATION_UNIT) {
490 candidate = JavaModelUtil
491 .toOriginal((ICompilationUnit) candidate);
499 * Note: This method is for internal use only. Clients should not call this
502 protected static Object[] concatenate(Object[] a1, Object[] a2) {
503 int a1Len = a1.length;
504 int a2Len = a2.length;
505 Object[] res = new Object[a1Len + a2Len];
506 System.arraycopy(a1, 0, res, 0, a1Len);
507 System.arraycopy(a2, 0, res, a1Len, a2Len);