/******************************************************************************* * Copyright (c) 2000, 2003 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package net.sourceforge.phpdt.ui; import java.util.ArrayList; import java.util.List; import net.sourceforge.phpdt.core.ICompilationUnit; import net.sourceforge.phpdt.core.IJavaElement; import net.sourceforge.phpdt.core.IJavaElementDelta; import net.sourceforge.phpdt.core.IJavaModel; import net.sourceforge.phpdt.core.IJavaProject; import net.sourceforge.phpdt.core.IPackageFragment; import net.sourceforge.phpdt.core.IPackageFragmentRoot; import net.sourceforge.phpdt.core.IParent; import net.sourceforge.phpdt.core.ISourceReference; import net.sourceforge.phpdt.core.JavaCore; import net.sourceforge.phpdt.core.JavaModelException; import net.sourceforge.phpdt.internal.corext.util.JavaModelUtil; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.Viewer; /** * A base content provider for Java elements. It provides access to the Java * element hierarchy without listening to changes in the Java model. If updating * the presentation on Java model change is required than clients have to * subclass, listen to Java model changes and have to update the UI using * corresponding methods provided by the JFace viewers or their own UI * presentation. *

* The following Java element hierarchy is surfaced by this content provider: *

* *

 *  Java model (
 * 
 * IJavaModel
 * 
 * )
 *  Java project (
 * 
 * IJavaProject
 * 
 * )
 *  package fragment root (
 * 
 * IPackageFragmentRoot
 * 
 * )
 *  package fragment (
 * 
 * IPackageFragment
 * 
 * )
 *  compilation unit (
 * 
 * ICompilationUnit
 * 
 * )
 *  binary class file (
 * 
 * IClassFile
 * 
 * )
 * 
* *

*

* Note that when the entire Java project is declared to be package fragment * root, the corresponding package fragment root element that normally appears * between the Java project and the package fragments is automatically filtered * out. *

* This content provider can optionally return working copy elements for members * below compilation units. If enabled, working copy members are returned for * those compilation units in the Java element hierarchy for which a shared * working copy exists in JDT core. * * @see net.sourceforge.phpdt.ui.IWorkingCopyProvider * @see JavaCore#getSharedWorkingCopies(net.sourceforge.phpdt.core.IBufferFactory) * * @since 2.0 */ public class StandardJavaElementContentProvider implements ITreeContentProvider, IWorkingCopyProvider { protected static final Object[] NO_CHILDREN = new Object[0]; protected boolean fProvideMembers = false; protected boolean fProvideWorkingCopy = false; /** * Creates a new content provider. The content provider does not provide * members of compilation units or class files and it does not provide * working copy elements. */ public StandardJavaElementContentProvider() { } /** * Creates a new StandardJavaElementContentProvider. * * @param provideMembers * if true members below compilation units and * class files are provided. * @param provideWorkingCopy * if true the element provider provides working * copies members of compilation units which have an associated * working copy in JDT core. Otherwise only original elements are * provided. */ public StandardJavaElementContentProvider(boolean provideMembers, boolean provideWorkingCopy) { fProvideMembers = provideMembers; fProvideWorkingCopy = provideWorkingCopy; } /** * Returns whether members are provided when asking for a compilation units * or class file for its children. * * @return true if the content provider provides members; * otherwise false is returned */ public boolean getProvideMembers() { return fProvideMembers; } /** * Sets whether the content provider is supposed to return members when * asking a compilation unit or class file for its children. * * @param b * if true then members are provided. If * false compilation units and class files are the * leaves provided by this content provider. */ public void setProvideMembers(boolean b) { fProvideMembers = b; } /** * Returns whether the provided members are from a working copy or the * original compilation unit. * * @return true if the content provider provides working copy * members; otherwise false is returned * * @see #setProvideWorkingCopy(boolean) */ public boolean getProvideWorkingCopy() { return fProvideWorkingCopy; } /** * Sets whether the members are provided from a shared working copy that * exists for a original compilation unit in the Java element hierarchy. * * @param b * if true members are provided from a working * copy if one exists in JDT core. If false the * provider always returns original elements. */ public void setProvideWorkingCopy(boolean b) { fProvideWorkingCopy = b; } /* * (non-Javadoc) * * @see IWorkingCopyProvider#providesWorkingCopies() */ public boolean providesWorkingCopies() { return fProvideWorkingCopy; } /* * (non-Javadoc) Method declared on IStructuredContentProvider. */ public Object[] getElements(Object parent) { return getChildren(parent); } /* * (non-Javadoc) Method declared on IContentProvider. */ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { } /* * (non-Javadoc) Method declared on IContentProvider. */ public void dispose() { } /* * (non-Javadoc) Method declared on ITreeContentProvider. */ public Object[] getChildren(Object element) { if (!exists(element)) return NO_CHILDREN; try { if (element instanceof IJavaModel) return getJavaProjects((IJavaModel) element); // if (element instanceof IJavaProject) // return getPackageFragmentRoots((IJavaProject)element); // if (element instanceof IPackageFragmentRoot) return getPackageFragments((IPackageFragmentRoot) element); // if (element instanceof IPackageFragment) // return getPackageContents((IPackageFragment)element); if (element instanceof IFolder) return getResources((IFolder) element); if (fProvideMembers && element instanceof ISourceReference && element instanceof IParent) { if (fProvideWorkingCopy && element instanceof ICompilationUnit) { element = JavaModelUtil .toWorkingCopy((ICompilationUnit) element); } return ((IParent) element).getChildren(); } } catch (JavaModelException e) { return NO_CHILDREN; } return NO_CHILDREN; } /* * (non-Javadoc) * * @see ITreeContentProvider */ public boolean hasChildren(Object element) { if (fProvideMembers) { // assume CUs and class files are never empty if (element instanceof ICompilationUnit) { // || // element instanceof IClassFile) { return true; } } else { // don't allow to drill down into a compilation unit or class file if (element instanceof ICompilationUnit || // element instanceof IClassFile || element instanceof IFile) return false; } if (element instanceof IJavaProject) { IJavaProject jp = (IJavaProject) element; if (!jp.getProject().isOpen()) { return false; } } if (element instanceof IParent) { try { // when we have Java children return true, else we fetch all the // children if (((IParent) element).hasChildren()) return true; } catch (JavaModelException e) { return true; } } Object[] children = getChildren(element); return (children != null) && children.length > 0; } /* * (non-Javadoc) Method declared on ITreeContentProvider. */ public Object getParent(Object element) { if (!exists(element)) return null; return internalGetParent(element); } private Object[] getPackageFragments(IPackageFragmentRoot root) throws JavaModelException { IJavaElement[] fragments = root.getChildren(); // Object[] nonJavaResources= root.getNonJavaResources(); // if (nonJavaResources == null) return fragments; // return concatenate(fragments, nonJavaResources); } /** * Note: This method is for internal use only. Clients should not call this * method. */ // protected Object[] getPackageFragmentRoots(IJavaProject project) throws // JavaModelException { // if (!project.getProject().isOpen()) // return NO_CHILDREN; // // IPackageFragmentRoot[] roots= project.getPackageFragmentRoots(); // List list= new ArrayList(roots.length); // // filter out package fragments that correspond to projects and // // replace them with the package fragments directly // for (int i= 0; i < roots.length; i++) { // IPackageFragmentRoot root= (IPackageFragmentRoot)roots[i]; // if (isProjectPackageFragmentRoot(root)) { // Object[] children= root.getChildren(); // for (int k= 0; k < children.length; k++) // list.add(children[k]); // } // else if (hasChildren(root)) { // list.add(root); // } // } // return concatenate(list.toArray(), project.getNonJavaResources()); // } /** * Note: This method is for internal use only. Clients should not call this * method. */ protected Object[] getJavaProjects(IJavaModel jm) throws JavaModelException { return jm.getJavaProjects(); } // private Object[] getPackageContents(IPackageFragment fragment) throws // JavaModelException { // if (fragment.getKind() == IPackageFragmentRoot.K_SOURCE) { // return concatenate(fragment.getCompilationUnits(), // fragment.getNonJavaResources()); // } // return concatenate(fragment.getClassFiles(), // fragment.getNonJavaResources()); // } private Object[] getResources(IFolder folder) { try { // filter out folders that are package fragment roots Object[] members = folder.members(); List nonJavaResources = new ArrayList(); for (int i = 0; i < members.length; i++) { Object o = members[i]; // A folder can also be a package fragement root in the // following case // Project // + src <- source folder // + excluded <- excluded from class path // + included <- a new source folder. // Included is a member of excluded, but since it is rendered as // a source // folder we have to exclude it as a normal child. if (o instanceof IFolder) { IJavaElement element = JavaCore.create((IFolder) o); if (element instanceof IPackageFragmentRoot && element.exists()) { continue; } } nonJavaResources.add(o); } return nonJavaResources.toArray(); } catch (CoreException e) { return NO_CHILDREN; } } /** * Note: This method is for internal use only. Clients should not call this * method. */ protected boolean isClassPathChange(IJavaElementDelta delta) { // need to test the flags only for package fragment roots if (delta.getElement().getElementType() != IJavaElement.PACKAGE_FRAGMENT_ROOT) return false; int flags = delta.getFlags(); return (delta.getKind() == IJavaElementDelta.CHANGED && ((flags & IJavaElementDelta.F_ADDED_TO_CLASSPATH) != 0) || ((flags & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) != 0) || ((flags & IJavaElementDelta.F_REORDER) != 0)); } /** * Note: This method is for internal use only. Clients should not call this * method. */ protected Object skipProjectPackageFragmentRoot(IPackageFragmentRoot root) { try { if (isProjectPackageFragmentRoot(root)) return root.getParent(); return root; } catch (JavaModelException e) { return root; } } /** * Note: This method is for internal use only. Clients should not call this * method. */ protected boolean isPackageFragmentEmpty(IJavaElement element) throws JavaModelException { if (element instanceof IPackageFragment) { IPackageFragment fragment = (IPackageFragment) element; if (!(fragment.hasChildren())) // || // fragment.getNonJavaResources().length > 0) && // fragment.hasSubpackages()) return true; } return false; } /** * Note: This method is for internal use only. Clients should not call this * method. */ protected boolean isProjectPackageFragmentRoot(IPackageFragmentRoot root) throws JavaModelException { IResource resource = root.getResource(); return (resource instanceof IProject); } /** * Note: This method is for internal use only. Clients should not call this * method. */ protected boolean exists(Object element) { if (element == null) { return false; } if (element instanceof IResource) { return ((IResource) element).exists(); } if (element instanceof IJavaElement) { return ((IJavaElement) element).exists(); } return true; } /** * Note: This method is for internal use only. Clients should not call this * method. */ protected Object internalGetParent(Object element) { if (element instanceof IJavaProject) { return ((IJavaProject) element).getJavaModel(); } // try to map resources to the containing package fragment if (element instanceof IResource) { IResource parent = ((IResource) element).getParent(); IJavaElement jParent = JavaCore.create(parent); // http://bugs.eclipse.org/bugs/show_bug.cgi?id=31374 if (jParent != null && jParent.exists()) return jParent; return parent; } // for package fragments that are contained in a project package // fragment // we have to skip the package fragment root as the parent. if (element instanceof IPackageFragment) { IPackageFragmentRoot parent = (IPackageFragmentRoot) ((IPackageFragment) element) .getParent(); return skipProjectPackageFragmentRoot(parent); } if (element instanceof IJavaElement) { IJavaElement candidate = ((IJavaElement) element).getParent(); // If the parent is a CU we might have shown working copy elements // below CU level. If so // return the original element instead of the working copy. if (candidate != null && candidate.getElementType() == IJavaElement.COMPILATION_UNIT) { candidate = JavaModelUtil .toOriginal((ICompilationUnit) candidate); } return candidate; } return null; } /** * Note: This method is for internal use only. Clients should not call this * method. */ protected static Object[] concatenate(Object[] a1, Object[] a2) { int a1Len = a1.length; int a2Len = a2.length; Object[] res = new Object[a1Len + a2Len]; System.arraycopy(a1, 0, res, 0, a1Len); System.arraycopy(a2, 0, res, a1Len, a2Len); return res; } }