| /******************************************************************************* |
| * Copyright (c) 2000, 2006 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.ui.browsing; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import org.eclipse.core.runtime.CoreException; |
| |
| import org.eclipse.core.resources.IFolder; |
| import org.eclipse.core.resources.IResource; |
| |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Display; |
| |
| import org.eclipse.jface.viewers.ITreeContentProvider; |
| import org.eclipse.jface.viewers.StructuredViewer; |
| import org.eclipse.jface.viewers.TreeViewer; |
| |
| import org.eclipse.jdt.core.ICompilationUnit; |
| import org.eclipse.jdt.core.IJavaElement; |
| import org.eclipse.jdt.core.IJavaElementDelta; |
| import org.eclipse.jdt.core.IJavaProject; |
| import org.eclipse.jdt.core.IPackageFragment; |
| import org.eclipse.jdt.core.IPackageFragmentRoot; |
| import org.eclipse.jdt.core.JavaCore; |
| import org.eclipse.jdt.core.JavaModelException; |
| |
| import org.eclipse.jdt.internal.ui.JavaPlugin; |
| |
| /** |
| * Tree content provider for the hierarchical layout in the packages view. |
| * <p> |
| * XXX: The standard Java browsing part content provider needs and calls |
| * the browsing part/view. This class currently doesn't need to do so |
| * but might be required to later. |
| * </p> |
| */ |
| class PackagesViewHierarchicalContentProvider extends LogicalPackagesProvider implements ITreeContentProvider { |
| |
| public PackagesViewHierarchicalContentProvider(StructuredViewer viewer){ |
| super(viewer); |
| } |
| |
| /* |
| * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(Object) |
| */ |
| public Object[] getChildren(Object parentElement) { |
| try { |
| if (parentElement instanceof IJavaElement) { |
| IJavaElement iJavaElement= (IJavaElement) parentElement; |
| int type= iJavaElement.getElementType(); |
| |
| switch (type) { |
| case IJavaElement.JAVA_PROJECT : |
| { |
| |
| //create new element mapping |
| fMapToLogicalPackage.clear(); |
| fMapToPackageFragments.clear(); |
| IJavaProject project= (IJavaProject) parentElement; |
| |
| IPackageFragment[] topLevelChildren= getTopLevelChildrenByElementName(project.getPackageFragments()); |
| List list= new ArrayList(); |
| for (int i= 0; i < topLevelChildren.length; i++) { |
| IPackageFragment fragment= topLevelChildren[i]; |
| |
| IJavaElement el= fragment.getParent(); |
| if (el instanceof IPackageFragmentRoot) { |
| IPackageFragmentRoot root= (IPackageFragmentRoot) el; |
| if (!root.isArchive() || !root.isExternal()) |
| list.add(fragment); |
| } |
| } |
| |
| IPackageFragmentRoot[] packageFragmentRoots= project.getPackageFragmentRoots(); |
| List folders= new ArrayList(); |
| for (int i= 0; i < packageFragmentRoots.length; i++) { |
| IPackageFragmentRoot root= packageFragmentRoots[i]; |
| IResource resource= root.getUnderlyingResource(); |
| if (resource != null && resource instanceof IFolder) { |
| folders.addAll(getFolders(((IFolder)resource).members())); |
| } |
| } |
| |
| Object[] logicalPackages= combineSamePackagesIntoLogialPackages((IPackageFragment[]) list.toArray(new IPackageFragment[list.size()])); |
| if (folders.size() > 0) { |
| if (logicalPackages.length > 0) |
| folders.addAll(Arrays.asList(logicalPackages)); |
| return folders.toArray(); |
| } else { |
| return logicalPackages; |
| } |
| } |
| |
| case IJavaElement.PACKAGE_FRAGMENT_ROOT : |
| { |
| IPackageFragmentRoot root= (IPackageFragmentRoot) parentElement; |
| |
| //create new element mapping |
| fMapToLogicalPackage.clear(); |
| fMapToPackageFragments.clear(); |
| IResource resource= root.getUnderlyingResource(); |
| if (root.isArchive()) { |
| IPackageFragment[] fragments= new IPackageFragment[0]; |
| IJavaElement[] els= root.getChildren(); |
| fragments= getTopLevelChildrenByElementName(els); |
| addFragmentsToMap(fragments); |
| return fragments; |
| |
| } else if (resource != null && resource instanceof IFolder) { |
| List children= getFoldersAndElements(((IFolder)resource).members()); |
| |
| IPackageFragment defaultPackage= root.getPackageFragment(""); //$NON-NLS-1$ |
| if(defaultPackage.exists()) |
| children.add(defaultPackage); |
| |
| addFragmentsToMap(children); |
| return children.toArray(); |
| } else { |
| return NO_CHILDREN; |
| } |
| } |
| |
| case IJavaElement.PACKAGE_FRAGMENT : |
| { |
| IPackageFragment packageFragment= (IPackageFragment) parentElement; |
| if (packageFragment.isDefaultPackage()) |
| return NO_CHILDREN; |
| |
| IResource resource= packageFragment.getUnderlyingResource(); |
| if (resource != null && resource instanceof IFolder) { |
| List folders= getFoldersAndElements(((IFolder)resource).members()); |
| addFragmentsToMap(folders); |
| return folders.toArray(); |
| } |
| } |
| } |
| |
| //@Improve: rewrite using concatenate |
| } else if (parentElement instanceof LogicalPackage) { |
| |
| List children= new ArrayList(); |
| LogicalPackage logicalPackage= (LogicalPackage) parentElement; |
| IPackageFragment[] elements= logicalPackage.getFragments(); |
| for (int i= 0; i < elements.length; i++) { |
| IPackageFragment fragment= elements[i]; |
| IPackageFragment[] objects= findNextLevelChildrenByElementName((IPackageFragmentRoot) fragment.getParent(), fragment); |
| children.addAll(Arrays.asList(objects)); |
| } |
| return combineSamePackagesIntoLogialPackages((IPackageFragment[]) children.toArray(new IPackageFragment[children.size()])); |
| } else if (parentElement instanceof IFolder) { |
| IFolder folder= (IFolder)parentElement; |
| IResource[] resources= folder.members(); |
| List children = getFoldersAndElements(resources); |
| addFragmentsToMap(children); |
| return children.toArray(); |
| } |
| |
| } catch (JavaModelException e) { |
| return NO_CHILDREN; |
| } catch (CoreException e) { |
| return NO_CHILDREN; |
| } |
| return NO_CHILDREN; |
| } |
| |
| private void addFragmentsToMap(List elements) { |
| List packageFragments= new ArrayList(); |
| for (Iterator iter= elements.iterator(); iter.hasNext();) { |
| Object elem= iter.next(); |
| if (elem instanceof IPackageFragment) |
| packageFragments.add(elem); |
| } |
| addFragmentsToMap((IPackageFragment[])packageFragments.toArray(new IPackageFragment[packageFragments.size()])); |
| } |
| |
| private List getFoldersAndElements(IResource[] resources) throws CoreException { |
| List list= new ArrayList(); |
| for (int i= 0; i < resources.length; i++) { |
| IResource resource= resources[i]; |
| |
| if (resource instanceof IFolder) { |
| IFolder folder= (IFolder) resource; |
| IJavaElement element= JavaCore.create(folder); |
| |
| if (element instanceof IPackageFragment) { |
| list.add(element); |
| } else { |
| list.add(folder); |
| } |
| } |
| } |
| return list; |
| } |
| |
| private List getFolders(IResource[] resources) throws CoreException { |
| List list= new ArrayList(); |
| for (int i= 0; i < resources.length; i++) { |
| IResource resource= resources[i]; |
| |
| if (resource instanceof IFolder) { |
| IFolder folder= (IFolder) resource; |
| IJavaElement element= JavaCore.create(folder); |
| |
| if (element == null) { |
| list.add(folder); |
| } |
| } |
| } |
| return list; |
| } |
| |
| private IPackageFragment[] findNextLevelChildrenByElementName(IPackageFragmentRoot parent, IPackageFragment fragment) { |
| List list= new ArrayList(); |
| try { |
| |
| IJavaElement[] children= parent.getChildren(); |
| String fragmentname= fragment.getElementName(); |
| for (int i= 0; i < children.length; i++) { |
| IJavaElement element= children[i]; |
| if (element instanceof IPackageFragment) { |
| IPackageFragment frag= (IPackageFragment) element; |
| |
| String name= element.getElementName(); |
| if (name.length() > fragmentname.length() && name.charAt(fragmentname.length()) == '.' && frag.exists() && !IPackageFragment.DEFAULT_PACKAGE_NAME.equals(fragmentname) && name.startsWith(fragmentname) && !name.equals(fragmentname)) { |
| String tail= name.substring(fragmentname.length() + 1); |
| if (!IPackageFragment.DEFAULT_PACKAGE_NAME.equals(tail) && tail.indexOf('.') == -1) { |
| list.add(frag); |
| } |
| } |
| } |
| } |
| |
| } catch (JavaModelException e) { |
| JavaPlugin.log(e); |
| } |
| return (IPackageFragment[]) list.toArray(new IPackageFragment[list.size()]); |
| } |
| |
| private IPackageFragment[] getTopLevelChildrenByElementName(IJavaElement[] elements){ |
| List topLevelElements= new ArrayList(); |
| for (int i= 0; i < elements.length; i++) { |
| IJavaElement iJavaElement= elements[i]; |
| //if the name of the PackageFragment is the top level package it will contain no "." separators |
| if (iJavaElement instanceof IPackageFragment && iJavaElement.getElementName().indexOf('.')==-1){ |
| topLevelElements.add(iJavaElement); |
| } |
| } |
| return (IPackageFragment[]) topLevelElements.toArray(new IPackageFragment[topLevelElements.size()]); |
| } |
| |
| /* |
| * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(Object) |
| */ |
| public Object getParent(Object element) { |
| |
| try { |
| if (element instanceof IPackageFragment) { |
| IPackageFragment fragment= (IPackageFragment) element; |
| if(!fragment.exists()) |
| return null; |
| Object parent= getHierarchicalParent(fragment); |
| if(parent instanceof IPackageFragment) { |
| IPackageFragment pkgFragment= (IPackageFragment)parent; |
| LogicalPackage logicalPkg= findLogicalPackage(pkgFragment); |
| if (logicalPkg != null) |
| return logicalPkg; |
| else { |
| LogicalPackage lp= createLogicalPackage(pkgFragment); |
| if(lp == null) |
| return pkgFragment; |
| else return lp; |
| } |
| } |
| return parent; |
| |
| } else if(element instanceof LogicalPackage){ |
| LogicalPackage el= (LogicalPackage) element; |
| IPackageFragment fragment= el.getFragments()[0]; |
| Object parent= getHierarchicalParent(fragment); |
| |
| if(parent instanceof IPackageFragment){ |
| IPackageFragment pkgFragment= (IPackageFragment) parent; |
| LogicalPackage logicalPkg= findLogicalPackage(pkgFragment); |
| if (logicalPkg != null) |
| return logicalPkg; |
| else { |
| LogicalPackage lp= createLogicalPackage(pkgFragment); |
| if(lp == null) |
| return pkgFragment; |
| else return lp; |
| } |
| } else |
| return fragment.getJavaProject(); |
| } else if (element instanceof IFolder) { |
| IFolder folder = (IFolder) element; |
| IResource res = folder.getParent(); |
| |
| IJavaElement el = JavaCore.create(res); |
| if (el != null) { |
| return el; |
| } else { |
| return res; |
| } |
| } |
| |
| } catch (JavaModelException e) { |
| JavaPlugin.log(e); |
| } |
| return null; |
| } |
| |
| /* |
| * Check if the given IPackageFragment should be the member of a |
| * LogicalPackage and if so creates the LogicalPackage and adds it to the |
| * map. |
| */ |
| private LogicalPackage createLogicalPackage(IPackageFragment pkgFragment) { |
| if(!fInputIsProject) |
| return null; |
| |
| List fragments= new ArrayList(); |
| try { |
| IPackageFragmentRoot[] roots= pkgFragment.getJavaProject().getPackageFragmentRoots(); |
| for (int i= 0; i < roots.length; i++) { |
| IPackageFragmentRoot root= roots[i]; |
| IPackageFragment fragment= root.getPackageFragment(pkgFragment.getElementName()); |
| if(fragment.exists() && !fragment.equals(pkgFragment)) |
| fragments.add(fragment); |
| } |
| if(!fragments.isEmpty()) { |
| LogicalPackage logicalPackage= new LogicalPackage(pkgFragment); |
| fMapToLogicalPackage.put(getKey(pkgFragment), logicalPackage); |
| Iterator iter= fragments.iterator(); |
| while(iter.hasNext()){ |
| IPackageFragment f= (IPackageFragment)iter.next(); |
| if(logicalPackage.belongs(f)){ |
| logicalPackage.add(f); |
| fMapToLogicalPackage.put(getKey(f), logicalPackage); |
| } |
| } |
| |
| return logicalPackage; |
| } |
| |
| } catch (JavaModelException e) { |
| JavaPlugin.log(e); |
| } |
| |
| return null; |
| } |
| |
| private Object getHierarchicalParent(IPackageFragment fragment) throws JavaModelException { |
| IJavaElement parent= fragment.getParent(); |
| |
| if ((parent instanceof IPackageFragmentRoot) && parent.exists()) { |
| IPackageFragmentRoot root= (IPackageFragmentRoot) parent; |
| if (root.isArchive() || !fragment.exists()) { |
| return findNextLevelParentByElementName(fragment); |
| } else { |
| IResource resource= fragment.getUnderlyingResource(); |
| if ((resource != null) && (resource instanceof IFolder)) { |
| IFolder folder= (IFolder) resource; |
| IResource res= folder.getParent(); |
| |
| IJavaElement el= JavaCore.create(res); |
| if (el != null) { |
| return el; |
| } else { |
| return res; |
| } |
| } |
| } |
| } |
| return parent; |
| } |
| |
| private Object findNextLevelParentByElementName(IPackageFragment child) { |
| String name= child.getElementName(); |
| |
| int index= name.lastIndexOf('.'); |
| if (index != -1) { |
| String realParentName= name.substring(0, index); |
| IPackageFragment element= ((IPackageFragmentRoot) child.getParent()).getPackageFragment(realParentName); |
| if (element.exists()) { |
| return element; |
| } |
| } |
| return child.getParent(); |
| } |
| |
| |
| /* |
| * @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(Object) |
| */ |
| public boolean hasChildren(Object element) { |
| |
| if (element instanceof IPackageFragment) { |
| IPackageFragment fragment= (IPackageFragment) element; |
| if(fragment.isDefaultPackage() || !fragment.exists()) |
| return false; |
| } |
| return getChildren(element).length > 0; |
| } |
| |
| /* |
| * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(Object) |
| */ |
| public Object[] getElements(Object inputElement) { |
| return getChildren(inputElement); |
| } |
| |
| protected void processDelta(IJavaElementDelta delta) throws JavaModelException { |
| |
| int kind = delta.getKind(); |
| final IJavaElement element = delta.getElement(); |
| |
| if (isClassPathChange(delta)) { |
| Object input= fViewer.getInput(); |
| if (input != null) { |
| if (fInputIsProject && input.equals(element.getJavaProject())) { |
| postRefresh(input); |
| return; |
| } else if (!fInputIsProject && input.equals(element)) { |
| if (element.exists()) |
| postRefresh(input); |
| else |
| postRemove(input); |
| return; |
| } |
| } |
| } |
| |
| if (kind == IJavaElementDelta.REMOVED) { |
| Object input= fViewer.getInput(); |
| if (input != null && input.equals(element)) { |
| postRemove(input); |
| return; |
| } |
| } |
| |
| if (element instanceof IPackageFragment) { |
| final IPackageFragment frag = (IPackageFragment) element; |
| |
| //if fragment was in LogicalPackage refresh, |
| //otherwise just remove |
| if (kind == IJavaElementDelta.REMOVED) { |
| removeElement(frag); |
| return; |
| |
| } else if (kind == IJavaElementDelta.ADDED) { |
| |
| Object parent= getParent(frag); |
| addElement(frag, parent); |
| return; |
| |
| } else if (kind == IJavaElementDelta.CHANGED) { |
| //just refresh |
| LogicalPackage logicalPkg= findLogicalPackage(frag); |
| //in case changed object is filtered out |
| if (logicalPkg != null) |
| postRefresh(findElementToRefresh(logicalPkg)); |
| else |
| postRefresh(findElementToRefresh(frag)); |
| return; |
| } |
| } |
| |
| processAffectedChildren(delta); |
| } |
| |
| private Object findElementToRefresh(Object object) { |
| Object toBeRefreshed= object; |
| if (fViewer.testFindItem(object) == null) { |
| Object parent= getParent(object); |
| if(parent instanceof IPackageFragmentRoot && fInputIsProject) |
| parent= ((IPackageFragmentRoot)parent).getJavaProject(); |
| |
| if(parent != null) |
| toBeRefreshed= parent; |
| } |
| return toBeRefreshed; |
| } |
| |
| private void processAffectedChildren(IJavaElementDelta delta) throws JavaModelException { |
| IJavaElementDelta[] affectedChildren = delta.getAffectedChildren(); |
| for (int i = 0; i < affectedChildren.length; i++) { |
| if (!(affectedChildren[i] instanceof ICompilationUnit)) { |
| processDelta(affectedChildren[i]); |
| } |
| } |
| } |
| |
| private void postAdd(final Object child, final Object parent) { |
| postRunnable(new Runnable() { |
| public void run() { |
| Control ctrl = fViewer.getControl(); |
| if (ctrl != null && !ctrl.isDisposed()) { |
| ((TreeViewer)fViewer).add(parent, child); |
| } |
| } |
| }); |
| } |
| |
| private void postRemove(final Object object) { |
| postRunnable(new Runnable() { |
| public void run() { |
| Control ctrl = fViewer.getControl(); |
| if (ctrl != null && !ctrl.isDisposed()) { |
| ((TreeViewer)fViewer).remove(object); |
| } |
| } |
| }); |
| } |
| |
| private void postRefresh(final Object object) { |
| postRunnable(new Runnable() { |
| public void run() { |
| Control ctrl= fViewer.getControl(); |
| if (ctrl != null && !ctrl.isDisposed()) { |
| ((TreeViewer) fViewer).refresh(object); |
| } |
| } |
| }); |
| } |
| |
| private void postRunnable(final Runnable r) { |
| Control ctrl= fViewer.getControl(); |
| if (ctrl != null && !ctrl.isDisposed()) { |
| // fBrowsingPart.setProcessSelectionEvents(false); |
| try { |
| Display currentDisplay= Display.getCurrent(); |
| if (currentDisplay != null && currentDisplay.equals(ctrl.getDisplay())) |
| ctrl.getDisplay().syncExec(r); |
| else |
| ctrl.getDisplay().asyncExec(r); |
| } finally { |
| // fBrowsingPart.setProcessSelectionEvents(true); |
| } |
| } |
| } |
| |
| private void addElement(IPackageFragment frag, Object parent) { |
| |
| String key= getKey(frag); |
| LogicalPackage lp= (LogicalPackage)fMapToLogicalPackage.get(key); |
| |
| //if fragment must be added to an existing LogicalPackage |
| if (lp != null && lp.belongs(frag)){ |
| lp.add(frag); |
| return; |
| } |
| |
| //if a new LogicalPackage must be created |
| IPackageFragment iPackageFragment= (IPackageFragment)fMapToPackageFragments.get(key); |
| if (iPackageFragment!= null && !iPackageFragment.equals(frag)){ |
| lp= new LogicalPackage(iPackageFragment); |
| lp.add(frag); |
| //add new LogicalPackage to LogicalPackages map |
| fMapToLogicalPackage.put(key, lp); |
| |
| //determine who to refresh |
| if (parent instanceof IPackageFragmentRoot){ |
| IPackageFragmentRoot root= (IPackageFragmentRoot) parent; |
| if (fInputIsProject){ |
| postRefresh(root.getJavaProject()); |
| } else { |
| postRefresh(root); |
| } |
| } else { |
| //@Improve: Should this be replaced by a refresh? |
| postAdd(lp, parent); |
| postRemove(iPackageFragment); |
| } |
| |
| } |
| //if this is a new Package Fragment |
| else { |
| fMapToPackageFragments.put(key, frag); |
| |
| //determine who to refresh |
| if (parent instanceof IPackageFragmentRoot) { |
| IPackageFragmentRoot root= (IPackageFragmentRoot) parent; |
| if (fInputIsProject) { |
| postAdd(frag, root.getJavaProject()); |
| } else |
| postAdd(frag, root); |
| } else { |
| postAdd(frag, parent); |
| } |
| } |
| } |
| |
| private void removeElement(IPackageFragment frag) { |
| |
| String key= getKey(frag); |
| LogicalPackage lp= (LogicalPackage)fMapToLogicalPackage.get(key); |
| |
| if(lp != null){ |
| lp.remove(frag); |
| //if the LogicalPackage needs to revert back to a PackageFragment |
| //remove it from the LogicalPackages map and add the PackageFragment |
| //to the PackageFragment map |
| if (lp.getFragments().length == 1) { |
| IPackageFragment fragment= lp.getFragments()[0]; |
| fMapToPackageFragments.put(key, fragment); |
| fMapToLogicalPackage.remove(key); |
| |
| //remove the LogicalPackage from viewer |
| postRemove(lp); |
| |
| Object parent= getParent(fragment); |
| if (parent instanceof IPackageFragmentRoot) { |
| parent= ((IPackageFragmentRoot)parent).getJavaProject(); |
| } |
| postAdd(fragment, parent); |
| } |
| |
| } else { |
| //remove the fragment from the fragment map and viewer |
| IPackageFragment fragment= (IPackageFragment) fMapToPackageFragments.get(key); |
| if (fragment!= null && fragment.equals(frag)) { |
| fMapToPackageFragments.remove(key); |
| postRemove(frag); |
| } |
| } |
| } |
| } |