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;
39 * A base content provider for Java elements. It provides access to the
40 * Java element hierarchy without listening to changes in the Java model.
41 * If updating the presentation on Java model change is required than
42 * clients have to subclass, listen to Java model changes and have to update
43 * the UI using corresponding methods provided by the JFace viewers or their
44 * own UI presentation.
46 * The following Java element hierarchy is surfaced by this content provider:
49 Java model (<code>IJavaModel</code>)
50 Java project (<code>IJavaProject</code>)
51 package fragment root (<code>IPackageFragmentRoot</code>)
52 package fragment (<code>IPackageFragment</code>)
53 compilation unit (<code>ICompilationUnit</code>)
54 binary class file (<code>IClassFile</code>)
58 * Note that when the entire Java project is declared to be package fragment root,
59 * the corresponding package fragment root element that normally appears between the
60 * Java project and the package fragments is automatically filtered out.
62 * This content provider can optionally return working copy elements for members
63 * below compilation units. If enabled, working copy members are returned for those
64 * compilation units in the Java element hierarchy for which a shared working copy exists
67 * @see net.sourceforge.phpdt.ui.IWorkingCopyProvider
68 * @see JavaCore#getSharedWorkingCopies(net.sourceforge.phpdt.core.IBufferFactory)
72 public class StandardJavaElementContentProvider implements ITreeContentProvider, IWorkingCopyProvider {
74 protected static final Object[] NO_CHILDREN= new Object[0];
76 protected boolean fProvideMembers= false;
77 protected boolean fProvideWorkingCopy= false;
80 * Creates a new content provider. The content provider does not
81 * provide members of compilation units or class files and it does
82 * not provide working copy elements.
84 public StandardJavaElementContentProvider() {
88 * Creates a new <code>StandardJavaElementContentProvider</code>.
90 * @param provideMembers if <code>true</code> members below compilation units
91 * and class files are provided.
92 * @param provideWorkingCopy if <code>true</code> the element provider provides
93 * working copies members of compilation units which have an associated working
94 * copy in JDT core. Otherwise only original elements are provided.
96 public StandardJavaElementContentProvider(boolean provideMembers, boolean provideWorkingCopy) {
97 fProvideMembers= provideMembers;
98 fProvideWorkingCopy= provideWorkingCopy;
102 * Returns whether members are provided when asking
103 * for a compilation units or class file for its children.
105 * @return <code>true</code> if the content provider provides members;
106 * otherwise <code>false</code> is returned
108 public boolean getProvideMembers() {
109 return fProvideMembers;
113 * Sets whether the content provider is supposed to return members
114 * when asking a compilation unit or class file for its children.
116 * @param b if <code>true</code> then members are provided.
117 * If <code>false</code> compilation units and class files are the
118 * leaves provided by this content provider.
120 public void setProvideMembers(boolean b) {
125 * Returns whether the provided members are from a working
126 * copy or the original compilation unit.
128 * @return <code>true</code> if the content provider provides
129 * working copy members; otherwise <code>false</code> is
132 * @see #setProvideWorkingCopy(boolean)
134 public boolean getProvideWorkingCopy() {
135 return fProvideWorkingCopy;
139 * Sets whether the members are provided from a shared working copy
140 * that exists for a original compilation unit in the Java element hierarchy.
142 * @param b if <code>true</code> members are provided from a
143 * working copy if one exists in JDT core. If <code>false</code> the
144 * provider always returns original elements.
146 public void setProvideWorkingCopy(boolean b) {
147 fProvideWorkingCopy= b;
151 * @see IWorkingCopyProvider#providesWorkingCopies()
153 public boolean providesWorkingCopies() {
154 return fProvideWorkingCopy;
158 * Method declared on IStructuredContentProvider.
160 public Object[] getElements(Object parent) {
161 return getChildren(parent);
165 * Method declared on IContentProvider.
167 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
171 * Method declared on IContentProvider.
173 public void dispose() {
177 * Method declared on ITreeContentProvider.
179 public Object[] getChildren(Object element) {
180 if (!exists(element))
184 if (element instanceof IJavaModel)
185 return getJavaProjects((IJavaModel)element);
187 // if (element instanceof IJavaProject)
188 // return getPackageFragmentRoots((IJavaProject)element);
190 if (element instanceof IPackageFragmentRoot)
191 return getPackageFragments((IPackageFragmentRoot)element);
193 // if (element instanceof IPackageFragment)
194 // return getPackageContents((IPackageFragment)element);
196 if (element instanceof IFolder)
197 return getResources((IFolder)element);
199 if (fProvideMembers && element instanceof ISourceReference && element instanceof IParent) {
200 if (fProvideWorkingCopy && element instanceof ICompilationUnit) {
201 element= JavaModelUtil.toWorkingCopy((ICompilationUnit) element);
203 return ((IParent)element).getChildren();
205 } catch (JavaModelException e) {
212 * @see ITreeContentProvider
214 public boolean hasChildren(Object element) {
215 if (fProvideMembers) {
216 // assume CUs and class files are never empty
217 if (element instanceof ICompilationUnit ){
219 // element instanceof IClassFile) {
223 // don't allow to drill down into a compilation unit or class file
224 if (element instanceof ICompilationUnit ||
225 // element instanceof IClassFile ||
226 element instanceof IFile)
230 if (element instanceof IJavaProject) {
231 IJavaProject jp= (IJavaProject)element;
232 if (!jp.getProject().isOpen()) {
237 if (element instanceof IParent) {
239 // when we have Java children return true, else we fetch all the children
240 if (((IParent)element).hasChildren())
242 } catch(JavaModelException e) {
246 Object[] children= getChildren(element);
247 return (children != null) && children.length > 0;
251 * Method declared on ITreeContentProvider.
253 public Object getParent(Object element) {
254 if (!exists(element))
256 return internalGetParent(element);
259 private Object[] getPackageFragments(IPackageFragmentRoot root) throws JavaModelException {
260 IJavaElement[] fragments= root.getChildren();
261 // Object[] nonJavaResources= root.getNonJavaResources();
262 // if (nonJavaResources == null)
264 // return concatenate(fragments, nonJavaResources);
268 * Note: This method is for internal use only. Clients should not call this method.
270 // protected Object[] getPackageFragmentRoots(IJavaProject project) throws JavaModelException {
271 // if (!project.getProject().isOpen())
272 // return NO_CHILDREN;
274 // IPackageFragmentRoot[] roots= project.getPackageFragmentRoots();
275 // List list= new ArrayList(roots.length);
276 // // filter out package fragments that correspond to projects and
277 // // replace them with the package fragments directly
278 // for (int i= 0; i < roots.length; i++) {
279 // IPackageFragmentRoot root= (IPackageFragmentRoot)roots[i];
280 // if (isProjectPackageFragmentRoot(root)) {
281 // Object[] children= root.getChildren();
282 // for (int k= 0; k < children.length; k++)
283 // list.add(children[k]);
285 // else if (hasChildren(root)) {
289 // return concatenate(list.toArray(), project.getNonJavaResources());
293 * Note: This method is for internal use only. Clients should not call this method.
295 protected Object[] getJavaProjects(IJavaModel jm) throws JavaModelException {
296 return jm.getJavaProjects();
299 // private Object[] getPackageContents(IPackageFragment fragment) throws JavaModelException {
300 // if (fragment.getKind() == IPackageFragmentRoot.K_SOURCE) {
301 // return concatenate(fragment.getCompilationUnits(), fragment.getNonJavaResources());
303 // return concatenate(fragment.getClassFiles(), fragment.getNonJavaResources());
306 private Object[] getResources(IFolder folder) {
308 // filter out folders that are package fragment roots
309 Object[] members= folder.members();
310 List nonJavaResources= new ArrayList();
311 for (int i= 0; i < members.length; i++) {
312 Object o= members[i];
313 // A folder can also be a package fragement root in the following case
315 // + src <- source folder
316 // + excluded <- excluded from class path
317 // + included <- a new source folder.
318 // Included is a member of excluded, but since it is rendered as a source
319 // folder we have to exclude it as a normal child.
320 if (o instanceof IFolder) {
321 IJavaElement element= JavaCore.create((IFolder)o);
322 if (element instanceof IPackageFragmentRoot && element.exists()) {
326 nonJavaResources.add(o);
328 return nonJavaResources.toArray();
329 } catch(CoreException e) {
335 * Note: This method is for internal use only. Clients should not call this method.
337 protected boolean isClassPathChange(IJavaElementDelta delta) {
339 // need to test the flags only for package fragment roots
340 if (delta.getElement().getElementType() != IJavaElement.PACKAGE_FRAGMENT_ROOT)
343 int flags= delta.getFlags();
344 return (delta.getKind() == IJavaElementDelta.CHANGED &&
345 ((flags & IJavaElementDelta.F_ADDED_TO_CLASSPATH) != 0) ||
346 ((flags & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) != 0) ||
347 ((flags & IJavaElementDelta.F_REORDER) != 0));
351 * Note: This method is for internal use only. Clients should not call this method.
353 protected Object skipProjectPackageFragmentRoot(IPackageFragmentRoot root) {
355 if (isProjectPackageFragmentRoot(root))
356 return root.getParent();
358 } catch(JavaModelException e) {
364 * Note: This method is for internal use only. Clients should not call this method.
366 protected boolean isPackageFragmentEmpty(IJavaElement element) throws JavaModelException {
367 if (element instanceof IPackageFragment) {
368 IPackageFragment fragment= (IPackageFragment)element;
369 if (!(fragment.hasChildren() ) )
371 // fragment.getNonJavaResources().length > 0) && fragment.hasSubpackages())
378 * Note: This method is for internal use only. Clients should not call this method.
380 protected boolean isProjectPackageFragmentRoot(IPackageFragmentRoot root) throws JavaModelException {
381 IResource resource= root.getResource();
382 return (resource instanceof IProject);
386 * Note: This method is for internal use only. Clients should not call this method.
388 protected boolean exists(Object element) {
389 if (element == null) {
392 if (element instanceof IResource) {
393 return ((IResource)element).exists();
395 if (element instanceof IJavaElement) {
396 return ((IJavaElement)element).exists();
402 * Note: This method is for internal use only. Clients should not call this method.
404 protected Object internalGetParent(Object element) {
405 if (element instanceof IJavaProject) {
406 return ((IJavaProject)element).getJavaModel();
408 // try to map resources to the containing package fragment
409 if (element instanceof IResource) {
410 IResource parent= ((IResource)element).getParent();
411 IJavaElement jParent= JavaCore.create(parent);
412 // http://bugs.eclipse.org/bugs/show_bug.cgi?id=31374
413 if (jParent != null && jParent.exists())
418 // for package fragments that are contained in a project package fragment
419 // we have to skip the package fragment root as the parent.
420 if (element instanceof IPackageFragment) {
421 IPackageFragmentRoot parent= (IPackageFragmentRoot)((IPackageFragment)element).getParent();
422 return skipProjectPackageFragmentRoot(parent);
424 if (element instanceof IJavaElement) {
425 IJavaElement candidate= ((IJavaElement)element).getParent();
426 // If the parent is a CU we might have shown working copy elements below CU level. If so
427 // return the original element instead of the working copy.
428 if (candidate != null && candidate.getElementType() == IJavaElement.COMPILATION_UNIT) {
429 candidate= JavaModelUtil.toOriginal((ICompilationUnit) candidate);
437 * Note: This method is for internal use only. Clients should not call this method.
439 protected static Object[] concatenate(Object[] a1, Object[] a2) {
440 int a1Len= a1.length;
441 int a2Len= a2.length;
442 Object[] res= new Object[a1Len + a2Len];
443 System.arraycopy(a1, 0, res, 0, a1Len);
444 System.arraycopy(a2, 0, res, a1Len, a2Len);