1 /*******************************************************************************
2 * Copyright (c) 2000, 2011 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package org.eclipse.jdt.internal.corext.refactoring.reorg;
13 import java.util.ArrayList;
14 import java.util.Arrays;
15 import java.util.Iterator;
16 import java.util.List;
18 import org.eclipse.core.runtime.CoreException;
20 import org.eclipse.core.resources.IContainer;
21 import org.eclipse.core.resources.IFile;
22 import org.eclipse.core.resources.IFolder;
23 import org.eclipse.core.resources.IResource;
24 import org.eclipse.core.resources.mapping.IResourceChangeDescriptionFactory;
26 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
27 import org.eclipse.ltk.core.refactoring.participants.DeleteArguments;
28 import org.eclipse.ltk.core.refactoring.participants.ParticipantManager;
29 import org.eclipse.ltk.core.refactoring.participants.RefactoringParticipant;
30 import org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor;
31 import org.eclipse.ltk.core.refactoring.participants.SharableParticipants;
33 import org.eclipse.jdt.core.ICompilationUnit;
34 import org.eclipse.jdt.core.IJavaElement;
35 import org.eclipse.jdt.core.IJavaProject;
36 import org.eclipse.jdt.core.IPackageFragment;
37 import org.eclipse.jdt.core.IPackageFragmentRoot;
38 import org.eclipse.jdt.core.IType;
39 import org.eclipse.jdt.core.JavaCore;
40 import org.eclipse.jdt.core.JavaModelException;
42 import org.eclipse.jdt.internal.corext.refactoring.util.JavaElementUtil;
45 * A modification collector for Java element delete operations.
47 public class DeleteModifications extends RefactoringModifications {
49 private List<IJavaElement> fDelete;
52 * Contains the actual packages when executing
53 * <code>handlePackageFragmentDelete</code>. This is part of the
54 * algorithm to check if a parent folder can be deleted.
56 private List<IPackageFragment> fPackagesToDelete;
58 public DeleteModifications() {
59 fDelete= new ArrayList<IJavaElement>();
60 fPackagesToDelete= new ArrayList<IPackageFragment>();
63 public void delete(IResource resource) {
64 getResourceModifications().addDelete(resource);
67 public void delete(IResource[] resources) {
68 for (int i= 0; i < resources.length; i++) {
73 public void delete(IJavaElement[] elements) throws CoreException {
74 for (int i= 0; i < elements.length; i++) {
79 public void delete(IJavaElement element) throws CoreException {
80 switch(element.getElementType()) {
81 case IJavaElement.JAVA_MODEL:
83 case IJavaElement.JAVA_PROJECT:
85 if (element.getResource() != null)
86 getResourceModifications().addDelete(element.getResource());
88 case IJavaElement.PACKAGE_FRAGMENT_ROOT:
90 IResource resource= element.getResource();
91 // Flag an resource change even if we have an archive. If it is
92 // internal (we have a underlying resource then we have a resource
95 getResourceModifications().addDelete(resource);
96 IJavaProject[] referencingProjects= JavaElementUtil.getReferencingProjects((IPackageFragmentRoot) element);
97 for (int i= 0; i < referencingProjects.length; i++) {
98 IFile classpath= referencingProjects[i].getProject().getFile(".classpath"); //$NON-NLS-1$
99 getResourceModifications().addChanged(classpath);
102 case IJavaElement.PACKAGE_FRAGMENT:
103 fDelete.add(element);
104 fPackagesToDelete.add((IPackageFragment) element);
106 case IJavaElement.COMPILATION_UNIT:
107 fDelete.add(element);
108 IType[] types= ((ICompilationUnit)element).getTypes();
109 fDelete.addAll(Arrays.asList(types));
110 if (element.getResource() != null)
111 getResourceModifications().addDelete(element.getResource());
114 fDelete.add(element);
120 * @return a List of IResources that are removed by package deletes
121 * @throws CoreException
123 public List<IResource> postProcess() throws CoreException {
124 ArrayList<IResource> resourcesCollector= new ArrayList<IResource>();
125 for (Iterator<IPackageFragment> iter= fPackagesToDelete.iterator(); iter.hasNext();) {
126 IPackageFragment pack= iter.next();
127 handlePackageFragmentDelete(pack, resourcesCollector);
129 return resourcesCollector;
133 public void buildDelta(IResourceChangeDescriptionFactory deltaFactory) {
134 getResourceModifications().buildDelta(deltaFactory);
138 public RefactoringParticipant[] loadParticipants(RefactoringStatus status, RefactoringProcessor owner, String[] natures, SharableParticipants shared) {
139 List<RefactoringParticipant> result= new ArrayList<RefactoringParticipant>();
140 for (Iterator<IJavaElement> iter= fDelete.iterator(); iter.hasNext();) {
141 result.addAll(Arrays.asList(ParticipantManager.loadDeleteParticipants(status,
143 new DeleteArguments(), natures, shared)));
145 result.addAll(Arrays.asList(getResourceModifications().getParticipants(status, owner, natures, shared)));
146 return result.toArray(new RefactoringParticipant[result.size()]);
150 * This method collects file and folder deletion for notifying
151 * participants. Participants will get notified of
153 * * deletion of the package (in any case)
154 * * deletion of files within the package if only the files are deleted without
155 * the package folder ("package cleaning")
156 * * deletion of the package folder if it is not only cleared and if its parent
157 * is not removed as well.
159 * All deleted resources are added to <code>resourcesCollector</code>
160 * @param pack the package
162 * @param resourcesCollector a collector for IResources to be deleted
163 * @throws CoreException
165 private void handlePackageFragmentDelete(IPackageFragment pack, ArrayList<IResource> resourcesCollector) throws CoreException {
166 final IContainer container= (IContainer)pack.getResource();
167 if (container == null)
170 final IResource[] members= container.members();
173 * Check whether this package is removed completely or only cleared.
174 * The default package can never be removed completely.
176 if (!pack.isDefaultPackage() && canRemoveCompletely(pack)) {
177 // This package is removed completely, which means its folder will be
178 // deleted as well. We only notify participants of the folder deletion
179 // if the parent folder of this folder will not be deleted as well:
180 boolean parentIsMarked= false;
181 final IPackageFragment parent= JavaElementUtil.getParentSubpackage(pack);
182 if (parent == null) {
183 // "Parent" is the default package which will never be
184 // deleted physically
185 parentIsMarked= false;
187 // Parent is marked if it is in the list
188 parentIsMarked= fPackagesToDelete.contains(parent);
191 if (parentIsMarked) {
192 // Parent is marked, but is it really deleted or only cleared?
193 if (canRemoveCompletely(parent)) {
194 // Parent can be removed completely, so we do not add
195 // this folder to the list.
197 // Parent cannot be removed completely, but as this folder
198 // can be removed, we notify the participant
199 resourcesCollector.add(container);
200 getResourceModifications().addDelete(container);
203 // Parent will not be removed, but we will
204 resourcesCollector.add(container);
205 getResourceModifications().addDelete(container);
208 // This package is only cleared because it has subpackages (=subfolders)
209 // which are not deleted. As the package is only cleared, its folder
210 // will not be removed and so we must notify the participant of the deleted children.
211 for (int m= 0; m < members.length; m++) {
212 IResource member= members[m];
213 if (member instanceof IFile) {
214 IFile file= (IFile)member;
215 if ("class".equals(file.getFileExtension()) && file.isDerived()) //$NON-NLS-1$
217 if (pack.isDefaultPackage() && ! JavaCore.isJavaLikeFileName(file.getName()))
219 resourcesCollector.add(member);
220 getResourceModifications().addDelete(member);
222 if (!pack.isDefaultPackage() && member instanceof IFolder) {
223 // Normally, folder children of packages are packages
224 // as well, but in case they have been removed from the build
225 // path, notify the participant
226 IPackageFragment frag= (IPackageFragment) JavaCore.create(member);
228 resourcesCollector.add(member);
229 getResourceModifications().addDelete(member);
237 * Returns true if this initially selected package is really deletable
238 * (if it has non-selected sub packages, it may only be cleared).
239 * @param pack the package
240 * @return true if this initially selected package is really deletable
241 * @throws JavaModelException
243 private boolean canRemoveCompletely(IPackageFragment pack) throws JavaModelException {
244 final IPackageFragment[] subPackages= JavaElementUtil.getPackageAndSubpackages(pack);
245 for (int i= 0; i < subPackages.length; i++) {
246 if (!(subPackages[i].equals(pack)) && !(fPackagesToDelete.contains(subPackages[i])))