--- /dev/null
+/*******************************************************************************
+ * 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.JavaModelException;
+import net.sourceforge.phpdt.internal.corext.util.JavaModelUtil;
+import net.sourceforge.phpeclipse.PHPCore;
+
+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.
+ * <p>
+ * The following Java element hierarchy is surfaced by this content provider:
+ * <p>
+ * <pre>
+Java model (<code>IJavaModel</code>)
+ Java project (<code>IJavaProject</code>)
+ package fragment root (<code>IPackageFragmentRoot</code>)
+ package fragment (<code>IPackageFragment</code>)
+ compilation unit (<code>ICompilationUnit</code>)
+ binary class file (<code>IClassFile</code>)
+ * </pre>
+ * </p>
+ * <p>
+ * 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.
+ * </p>
+ * 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 org.eclipse.jdt.ui.IWorkingCopyProvider
+ * @see JavaCore#getSharedWorkingCopies(org.eclipse.jdt.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 <code>StandardJavaElementContentProvider</code>.
+ *
+ * @param provideMembers if <code>true</code> members below compilation units
+ * and class files are provided.
+ * @param provideWorkingCopy if <code>true</code> 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 <code>true</code> if the content provider provides members;
+ * otherwise <code>false</code> 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 <code>true</code> then members are provided.
+ * If <code>false</code> 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 <code>true</code> if the content provider provides
+ * working copy members; otherwise <code>false</code> 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 <code>true</code> members are provided from a
+ * working copy if one exists in JDT core. If <code>false</code> 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= PHPCore.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= PHPCore.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;
+ }
+
+
+}