/******************************************************************************* * 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 newStandardJavaElementContentProvider
.
*
* @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;
}
}