--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 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.corext.refactoring.reorg;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.IAdaptable;
+
+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.ui.IWorkingSet;
+
+import org.eclipse.jdt.core.IClassFile;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJarEntryResource;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IMember;
+import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.ISourceRange;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.SourceRange;
+
+import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
+import org.eclipse.jdt.internal.corext.refactoring.util.JavaElementUtil;
+import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
+import org.eclipse.jdt.internal.corext.util.Messages;
+
+import org.eclipse.jdt.ui.JavaElementLabels;
+
+import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels;
+
+
+public class ReorgUtils {
+
+ //workaround for bug 18311
+ private static final ISourceRange fgUnknownRange= new SourceRange(-1, 0);
+
+ private ReorgUtils() {
+ }
+
+ public static boolean isArchiveOrExternalMember(IJavaElement[] elements) {
+ for (int i= 0; i < elements.length; i++) {
+ IJavaElement element= elements[i];
+ IPackageFragmentRoot root= (IPackageFragmentRoot)element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
+ if (root != null && (root.isArchive() || root.isExternal()))
+ return true;
+ }
+ return false;
+ }
+
+ public static boolean containsOnlyProjects(List<?> elements){
+ if (elements.isEmpty())
+ return false;
+ for(Iterator<?> iter= elements.iterator(); iter.hasNext(); ) {
+ if (! isProject(iter.next()))
+ return false;
+ }
+ return true;
+ }
+
+ public static boolean isProject(Object element){
+ return (element instanceof IJavaProject) || (element instanceof IProject);
+ }
+
+ /**
+ * Checks whether the given list contains only working sets.
+ *
+ * @param elements the list with elements to check
+ * @return <code>true</code> if the list contains only working sets, <code>false</code>
+ * otherwise
+ * @since 3.5
+ */
+ public static boolean containsOnlyWorkingSets (List<?> elements){
+ if (elements.isEmpty())
+ return false;
+ for (Iterator<?> iter= elements.iterator(); iter.hasNext();) {
+ if (!isWorkingSet(iter.next()))
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Checks whether the given object is a working set.
+ *
+ * @param element the element to test
+ * @return <code>true</code> if the element is a working set, <code>false</code> otherwise
+ * @since 3.5
+ *
+ */
+
+ public static boolean isWorkingSet(Object element){
+ return (element instanceof IWorkingSet);
+ }
+
+ public static boolean isInsideCompilationUnit(IJavaElement element) {
+ return !(element instanceof ICompilationUnit) &&
+ hasAncestorOfType(element, IJavaElement.COMPILATION_UNIT);
+ }
+
+ public static boolean isInsideClassFile(IJavaElement element) {
+ return !(element instanceof IClassFile) &&
+ hasAncestorOfType(element, IJavaElement.CLASS_FILE);
+ }
+
+ public static boolean hasAncestorOfType(IJavaElement element, int type){
+ return element.getAncestor(type) != null;
+ }
+
+ /*
+ * May be <code>null</code>.
+ */
+ public static ICompilationUnit getCompilationUnit(IJavaElement javaElement){
+ if (javaElement instanceof ICompilationUnit)
+ return (ICompilationUnit) javaElement;
+ return (ICompilationUnit) javaElement.getAncestor(IJavaElement.COMPILATION_UNIT);
+ }
+
+ /*
+ * some of the returned elements may be <code>null</code>.
+ */
+ public static ICompilationUnit[] getCompilationUnits(IJavaElement[] javaElements){
+ ICompilationUnit[] result= new ICompilationUnit[javaElements.length];
+ for (int i= 0; i < javaElements.length; i++) {
+ result[i]= getCompilationUnit(javaElements[i]);
+ }
+ return result;
+ }
+
+ public static IResource getResource(IJavaElement element){
+ if (element instanceof ICompilationUnit)
+ return ((ICompilationUnit)element).getPrimary().getResource();
+ else
+ return element.getResource();
+ }
+
+ public static IResource[] getResources(IJavaElement[] elements) {
+ IResource[] result= new IResource[elements.length];
+ for (int i= 0; i < elements.length; i++) {
+ result[i]= ReorgUtils.getResource(elements[i]);
+ }
+ return result;
+ }
+
+ public static String getName(IResource resource) {
+ String resourceLabel= BasicElementLabels.getResourceName(resource);
+ switch (resource.getType()){
+ case IResource.FILE:
+ return Messages.format(RefactoringCoreMessages.ReorgUtils_0, resourceLabel);
+ case IResource.FOLDER:
+ return Messages.format(RefactoringCoreMessages.ReorgUtils_1, resourceLabel);
+ case IResource.PROJECT:
+ return Messages.format(RefactoringCoreMessages.ReorgUtils_2, resourceLabel);
+ default:
+ Assert.isTrue(false);
+ return null;
+ }
+ }
+
+ public static String getName(IJavaElement element) throws JavaModelException {
+ String pattern= createNamePattern(element);
+ String arg= JavaElementLabels.getElementLabel(element, JavaElementLabels.ALL_DEFAULT);
+ return Messages.format(pattern, arg);
+ }
+
+ private static String createNamePattern(IJavaElement element) throws JavaModelException {
+ switch(element.getElementType()){
+ case IJavaElement.CLASS_FILE:
+ return RefactoringCoreMessages.ReorgUtils_3;
+ case IJavaElement.COMPILATION_UNIT:
+ return RefactoringCoreMessages.ReorgUtils_4;
+ case IJavaElement.FIELD:
+ return RefactoringCoreMessages.ReorgUtils_5;
+ case IJavaElement.IMPORT_CONTAINER:
+ return RefactoringCoreMessages.ReorgUtils_6;
+ case IJavaElement.IMPORT_DECLARATION:
+ return RefactoringCoreMessages.ReorgUtils_7;
+ case IJavaElement.INITIALIZER:
+ return RefactoringCoreMessages.ReorgUtils_8;
+ case IJavaElement.JAVA_PROJECT:
+ return RefactoringCoreMessages.ReorgUtils_9;
+ case IJavaElement.METHOD:
+ if (((IMethod)element).isConstructor())
+ return RefactoringCoreMessages.ReorgUtils_10;
+ else
+ return RefactoringCoreMessages.ReorgUtils_11;
+ case IJavaElement.PACKAGE_DECLARATION:
+ return RefactoringCoreMessages.ReorgUtils_12;
+ case IJavaElement.PACKAGE_FRAGMENT:
+ if (JavaElementUtil.isDefaultPackage(element))
+ return RefactoringCoreMessages.ReorgUtils_13;
+ else
+ return RefactoringCoreMessages.ReorgUtils_14;
+ case IJavaElement.PACKAGE_FRAGMENT_ROOT:
+ if (((IPackageFragmentRoot) element).isArchive())
+ return RefactoringCoreMessages.ReorgUtils_21;
+ if (isSourceFolder(element))
+ return RefactoringCoreMessages.ReorgUtils_15;
+ if (isClassFolder(element))
+ return RefactoringCoreMessages.ReorgUtils_16;
+ return RefactoringCoreMessages.ReorgUtils_17;
+ case IJavaElement.TYPE:
+ IType type= (IType)element;
+ if (type.getElementName().length() == 0 && type.isAnonymous())
+ return RefactoringCoreMessages.ReorgUtils_20;
+ return RefactoringCoreMessages.ReorgUtils_18;
+ default:
+ Assert.isTrue(false);
+ return null;
+ }
+ }
+
+ public static IResource[] getResources(List<?> elements) {
+ List<IResource> resources= new ArrayList<IResource>(elements.size());
+ for (Iterator<?> iter= elements.iterator(); iter.hasNext();) {
+ Object element= iter.next();
+ if (element instanceof IResource)
+ resources.add((IResource) element);
+ }
+ return resources.toArray(new IResource[resources.size()]);
+ }
+
+ public static IJavaElement[] getJavaElements(List<?> elements) {
+ List<IJavaElement> resources= new ArrayList<IJavaElement>(elements.size());
+ for (Iterator<?> iter= elements.iterator(); iter.hasNext();) {
+ Object element= iter.next();
+ if (element instanceof IJavaElement)
+ resources.add((IJavaElement) element);
+ }
+ return resources.toArray(new IJavaElement[resources.size()]);
+ }
+
+ /**
+ * Returns the jar entry resources from the list of elements.
+ *
+ * @param elements the list of elements
+ * @return the array of jar entry resources
+ * @since 3.6
+ */
+ public static IJarEntryResource[] getJarEntryResources(List<?> elements) {
+ List<IJarEntryResource> resources= new ArrayList<IJarEntryResource>(elements.size());
+ for (Iterator<?> iter= elements.iterator(); iter.hasNext();) {
+ Object element= iter.next();
+ if (element instanceof IJarEntryResource)
+ resources.add((IJarEntryResource) element);
+ }
+ return resources.toArray(new IJarEntryResource[resources.size()]);
+ }
+
+ public static IWorkingSet[] getWorkingSets(List<?> elements) {
+ List<IWorkingSet> result= new ArrayList<IWorkingSet>(1);
+ for (Iterator<?> iter= elements.iterator(); iter.hasNext();) {
+ Object element= iter.next();
+ if (element instanceof IWorkingSet) {
+ result.add((IWorkingSet) element);
+ }
+ }
+ return result.toArray(new IWorkingSet[result.size()]);
+ }
+
+ public static boolean hasSourceAvailable(IMember member) throws JavaModelException{
+ return ! member.isBinary() ||
+ (member.getSourceRange() != null && ! fgUnknownRange.equals(member.getSourceRange()));
+ }
+
+ public static IResource[] setMinus(IResource[] setToRemoveFrom, IResource[] elementsToRemove) {
+ Set<IResource> setMinus= new HashSet<IResource>(setToRemoveFrom.length - setToRemoveFrom.length);
+ setMinus.addAll(Arrays.asList(setToRemoveFrom));
+ setMinus.removeAll(Arrays.asList(elementsToRemove));
+ return setMinus.toArray(new IResource[setMinus.size()]);
+ }
+
+ public static IJavaElement[] setMinus(IJavaElement[] setToRemoveFrom, IJavaElement[] elementsToRemove) {
+ Set<IJavaElement> setMinus= new HashSet<IJavaElement>(setToRemoveFrom.length - setToRemoveFrom.length);
+ setMinus.addAll(Arrays.asList(setToRemoveFrom));
+ setMinus.removeAll(Arrays.asList(elementsToRemove));
+ return setMinus.toArray(new IJavaElement[setMinus.size()]);
+ }
+
+ public static IJavaElement[] union(IJavaElement[] set1, IJavaElement[] set2) {
+ List<IJavaElement> union= new ArrayList<IJavaElement>(set1.length + set2.length);//use lists to avoid sequence problems
+ addAll(set1, union);
+ addAll(set2, union);
+ return union.toArray(new IJavaElement[union.size()]);
+ }
+
+ public static IResource[] union(IResource[] set1, IResource[] set2) {
+ List<IResource> union= new ArrayList<IResource>(set1.length + set2.length);//use lists to avoid sequence problems
+ addAll(ReorgUtils.getNotNulls(set1), union);
+ addAll(ReorgUtils.getNotNulls(set2), union);
+ return union.toArray(new IResource[union.size()]);
+ }
+
+ private static <T> void addAll(T[] array, List<T> list) {
+ for (int i= 0; i < array.length; i++) {
+ if (! list.contains(array[i]))
+ list.add(array[i]);
+ }
+ }
+
+ public static IType[] getMainTypes(IJavaElement[] javaElements) throws JavaModelException {
+ List<IJavaElement> result= new ArrayList<IJavaElement>();
+ for (int i= 0; i < javaElements.length; i++) {
+ IJavaElement element= javaElements[i];
+ if (element instanceof IType && JavaElementUtil.isMainType((IType)element))
+ result.add(element);
+ }
+ return result.toArray(new IType[result.size()]);
+ }
+
+ public static IFolder[] getFolders(IResource[] resources) {
+ Set<IResource> result= getResourcesOfType(resources, IResource.FOLDER);
+ return result.toArray(new IFolder[result.size()]);
+ }
+
+ public static IFile[] getFiles(IResource[] resources) {
+ Set<IResource> result= getResourcesOfType(resources, IResource.FILE);
+ return result.toArray(new IFile[result.size()]);
+ }
+
+ //the result can be cast down to the requested type array
+ public static Set<IResource> getResourcesOfType(IResource[] resources, int typeMask){
+ Set<IResource> result= new HashSet<IResource>(resources.length);
+ for (int i= 0; i < resources.length; i++) {
+ if (isOfType(resources[i], typeMask))
+ result.add(resources[i]);
+ }
+ return result;
+ }
+
+ //the result can be cast down to the requested type array
+ //type is _not_ a mask
+ public static List<?> getElementsOfType(IJavaElement[] javaElements, int type){
+ List<IJavaElement> result= new ArrayList<IJavaElement>(javaElements.length);
+ for (int i= 0; i < javaElements.length; i++) {
+ if (isOfType(javaElements[i], type))
+ result.add(javaElements[i]);
+ }
+ return result;
+ }
+
+ public static boolean hasElementsNotOfType(IResource[] resources, int typeMask) {
+ for (int i= 0; i < resources.length; i++) {
+ IResource resource= resources[i];
+ if (resource != null && ! isOfType(resource, typeMask))
+ return true;
+ }
+ return false;
+ }
+
+ //type is _not_ a mask
+ public static boolean hasElementsNotOfType(IJavaElement[] javaElements, int type) {
+ for (int i= 0; i < javaElements.length; i++) {
+ IJavaElement element= javaElements[i];
+ if (element != null && ! isOfType(element, type))
+ return true;
+ }
+ return false;
+ }
+
+ //type is _not_ a mask
+ public static boolean hasElementsOfType(IJavaElement[] javaElements, int type) {
+ for (int i= 0; i < javaElements.length; i++) {
+ IJavaElement element= javaElements[i];
+ if (element != null && isOfType(element, type))
+ return true;
+ }
+ return false;
+ }
+
+ public static boolean hasElementsOfType(IJavaElement[] javaElements, int[] types) {
+ for (int i= 0; i < types.length; i++) {
+ if (hasElementsOfType(javaElements, types[i])) return true;
+ }
+ return false;
+ }
+
+
+ public static boolean hasOnlyElementsOfType(IJavaElement[] javaElements, int[] types) {
+ for (int i= 0; i < javaElements.length; i++) {
+ IJavaElement element= javaElements[i];
+ boolean found= false;
+ for (int j= 0; j < types.length && !found; j++) {
+ if (isOfType(element, types[j]))
+ found= true;
+ }
+ if (!found)
+ return false;
+ }
+
+ return true;
+ }
+
+ public static boolean hasElementsOfType(IResource[] resources, int typeMask) {
+ for (int i= 0; i < resources.length; i++) {
+ IResource resource= resources[i];
+ if (resource != null && isOfType(resource, typeMask))
+ return true;
+ }
+ return false;
+ }
+
+ private static boolean isOfType(IJavaElement element, int type) {
+ return element.getElementType() == type;//this is _not_ a mask
+ }
+
+ private static boolean isOfType(IResource resource, int type) {
+ return resource != null && isFlagSet(resource.getType(), type);
+ }
+
+ private static boolean isFlagSet(int flags, int flag){
+ return (flags & flag) != 0;
+ }
+
+ public static boolean isSourceFolder(IJavaElement javaElement) throws JavaModelException {
+ return (javaElement instanceof IPackageFragmentRoot) &&
+ ((IPackageFragmentRoot)javaElement).getKind() == IPackageFragmentRoot.K_SOURCE;
+ }
+
+ public static boolean isClassFolder(IJavaElement javaElement) throws JavaModelException {
+ return (javaElement instanceof IPackageFragmentRoot) &&
+ ((IPackageFragmentRoot)javaElement).getKind() == IPackageFragmentRoot.K_BINARY;
+ }
+
+ public static boolean isPackageFragmentRoot(IJavaProject javaProject) throws JavaModelException{
+ return getCorrespondingPackageFragmentRoot(javaProject) != null;
+ }
+
+ private static boolean isPackageFragmentRootCorrespondingToProject(IPackageFragmentRoot root) {
+ return root.getResource() instanceof IProject;
+ }
+
+ public static IPackageFragmentRoot getCorrespondingPackageFragmentRoot(IJavaProject p) throws JavaModelException {
+ IPackageFragmentRoot[] roots= p.getPackageFragmentRoots();
+ for (int i= 0; i < roots.length; i++) {
+ if (isPackageFragmentRootCorrespondingToProject(roots[i]))
+ return roots[i];
+ }
+ return null;
+ }
+
+ public static boolean containsLinkedResources(IResource[] resources){
+ for (int i= 0; i < resources.length; i++) {
+ if (resources[i] != null && resources[i].isLinked()) return true;
+ }
+ return false;
+ }
+
+ public static boolean containsLinkedResources(IJavaElement[] javaElements){
+ for (int i= 0; i < javaElements.length; i++) {
+ IResource res= getResource(javaElements[i]);
+ if (res != null && res.isLinked()) return true;
+ }
+ return false;
+ }
+
+ public static boolean canBeDestinationForLinkedResources(IResource resource) {
+ return resource.isAccessible() && resource instanceof IProject;
+ }
+
+ public static boolean canBeDestinationForLinkedResources(IJavaElement javaElement) {
+ if (javaElement instanceof IPackageFragmentRoot){
+ return isPackageFragmentRootCorrespondingToProject((IPackageFragmentRoot)javaElement);
+ } else if (javaElement instanceof IJavaProject){
+ return true;//XXX ???
+ } else return false;
+ }
+
+ public static boolean isParentInWorkspaceOrOnDisk(IPackageFragment pack, IPackageFragmentRoot root){
+ if (pack == null)
+ return false;
+ IJavaElement packParent= pack.getParent();
+ if (packParent == null)
+ return false;
+ if (packParent.equals(root))
+ return true;
+ IResource packageResource= ResourceUtil.getResource(pack);
+ IResource packageRootResource= ResourceUtil.getResource(root);
+ return isParentInWorkspaceOrOnDisk(packageResource, packageRootResource);
+ }
+
+ public static boolean isParentInWorkspaceOrOnDisk(IPackageFragmentRoot root, IJavaProject javaProject){
+ if (root == null)
+ return false;
+ IJavaElement rootParent= root.getParent();
+ if (rootParent == null)
+ return false;
+ if (rootParent.equals(root))
+ return true;
+ IResource packageResource= ResourceUtil.getResource(root);
+ IResource packageRootResource= ResourceUtil.getResource(javaProject);
+ return isParentInWorkspaceOrOnDisk(packageResource, packageRootResource);
+ }
+
+ public static boolean isParentInWorkspaceOrOnDisk(ICompilationUnit cu, IPackageFragment dest){
+ if (cu == null)
+ return false;
+ IJavaElement cuParent= cu.getParent();
+ if (cuParent == null)
+ return false;
+ if (cuParent.equals(dest))
+ return true;
+ IResource cuResource= cu.getResource();
+ IResource packageResource= ResourceUtil.getResource(dest);
+ return isParentInWorkspaceOrOnDisk(cuResource, packageResource);
+ }
+
+ public static boolean isParentInWorkspaceOrOnDisk(IResource res, IResource maybeParent){
+ if (res == null)
+ return false;
+ return areEqualInWorkspaceOrOnDisk(res.getParent(), maybeParent);
+ }
+
+ public static boolean areEqualInWorkspaceOrOnDisk(IResource r1, IResource r2){
+ if (r1 == null || r2 == null)
+ return false;
+ if (r1.equals(r2))
+ return true;
+ URI r1Location= r1.getLocationURI();
+ URI r2Location= r2.getLocationURI();
+ if (r1Location == null || r2Location == null)
+ return false;
+ return r1Location.equals(r2Location);
+ }
+
+ public static IResource[] getNotNulls(IResource[] resources) {
+ Collection<IResource> result= new ArrayList<IResource>(resources.length);
+ for (int i= 0; i < resources.length; i++) {
+ IResource resource= resources[i];
+ if (resource != null && ! result.contains(resource))
+ result.add(resource);
+ }
+ return result.toArray(new IResource[result.size()]);
+ }
+
+ public static IResource[] getNotLinked(IResource[] resources) {
+ Collection<IResource> result= new ArrayList<IResource>(resources.length);
+ for (int i= 0; i < resources.length; i++) {
+ IResource resource= resources[i];
+ if (resource != null && ! result.contains(resource) && ! resource.isLinked())
+ result.add(resource);
+ }
+ return result.toArray(new IResource[result.size()]);
+ }
+
+ /* List<IJavaElement> javaElements
+ * return ICompilationUnit -> List<IJavaElement>
+ */
+ public static Map<ICompilationUnit, List<IJavaElement>> groupByCompilationUnit(List<IJavaElement> javaElements){
+ Map<ICompilationUnit, List<IJavaElement>> result= new HashMap<ICompilationUnit, List<IJavaElement>>();
+ for (Iterator<IJavaElement> iter= javaElements.iterator(); iter.hasNext();) {
+ IJavaElement element= iter.next();
+ ICompilationUnit cu= ReorgUtils.getCompilationUnit(element);
+ if (cu != null){
+ if (! result.containsKey(cu))
+ result.put(cu, new ArrayList<IJavaElement>(1));
+ result.get(cu).add(element);
+ }
+ }
+ return result;
+ }
+
+ public static void splitIntoJavaElementsAndResources(Object[] elements, List<? super IJavaElement> javaElementResult, List<? super IResource> resourceResult) {
+ for (int i= 0; i < elements.length; i++) {
+ Object element= elements[i];
+ if (element instanceof IJavaElement) {
+ javaElementResult.add((IJavaElement) element);
+ } else if (element instanceof IResource) {
+ IResource resource= (IResource)element;
+ IJavaElement jElement= JavaCore.create(resource);
+ if (jElement != null && jElement.exists())
+ javaElementResult.add(jElement);
+ else
+ resourceResult.add(resource);
+ }
+ }
+ }
+
+ public static boolean containsElementOrParent(Set<IAdaptable> elements, IJavaElement element) {
+ IJavaElement curr= element;
+ do {
+ if (elements.contains(curr))
+ return true;
+ curr= curr.getParent();
+ } while (curr != null);
+ return false;
+ }
+
+ public static boolean containsElementOrParent(Set<IAdaptable> elements, IResource element) {
+ IResource curr= element;
+ do {
+ if (elements.contains(curr))
+ return true;
+ IJavaElement jElement= JavaCore.create(curr);
+ if (jElement != null && jElement.exists()) {
+ return containsElementOrParent(elements, jElement);
+ }
+ curr= curr.getParent();
+ } while (curr != null);
+ return false;
+ }
+}