KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > corext > refactoring > reorg > JavaDeleteProcessor


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 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
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.corext.refactoring.reorg;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Arrays JavaDoc;
15 import java.util.Collections JavaDoc;
16 import java.util.Comparator JavaDoc;
17 import java.util.HashMap JavaDoc;
18 import java.util.HashSet JavaDoc;
19 import java.util.Iterator JavaDoc;
20 import java.util.List JavaDoc;
21 import java.util.Map JavaDoc;
22 import java.util.Set JavaDoc;
23
24 import org.eclipse.core.runtime.Assert;
25 import org.eclipse.core.runtime.CoreException;
26 import org.eclipse.core.runtime.IProgressMonitor;
27 import org.eclipse.core.runtime.OperationCanceledException;
28
29 import org.eclipse.core.filebuffers.FileBuffers;
30 import org.eclipse.core.filebuffers.ITextFileBuffer;
31 import org.eclipse.core.filebuffers.LocationKind;
32
33 import org.eclipse.core.resources.IContainer;
34 import org.eclipse.core.resources.IFile;
35 import org.eclipse.core.resources.IFolder;
36 import org.eclipse.core.resources.IProject;
37 import org.eclipse.core.resources.IResource;
38 import org.eclipse.core.resources.IResourceVisitor;
39 import org.eclipse.core.resources.mapping.IResourceChangeDescriptionFactory;
40
41 import org.eclipse.ltk.core.refactoring.Change;
42 import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
43 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
44 import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
45 import org.eclipse.ltk.core.refactoring.participants.DeleteProcessor;
46 import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments;
47 import org.eclipse.ltk.core.refactoring.participants.RefactoringParticipant;
48 import org.eclipse.ltk.core.refactoring.participants.ResourceChangeChecker;
49 import org.eclipse.ltk.core.refactoring.participants.SharableParticipants;
50
51 import org.eclipse.jdt.core.ICompilationUnit;
52 import org.eclipse.jdt.core.IField;
53 import org.eclipse.jdt.core.IJavaElement;
54 import org.eclipse.jdt.core.IJavaProject;
55 import org.eclipse.jdt.core.IMethod;
56 import org.eclipse.jdt.core.IPackageFragment;
57 import org.eclipse.jdt.core.IPackageFragmentRoot;
58 import org.eclipse.jdt.core.IType;
59 import org.eclipse.jdt.core.JavaCore;
60 import org.eclipse.jdt.core.JavaModelException;
61 import org.eclipse.jdt.core.refactoring.IJavaRefactorings;
62 import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor;
63
64 import org.eclipse.jdt.internal.corext.codemanipulation.GetterSetterUtil;
65 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptor;
66 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment;
67 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments;
68 import org.eclipse.jdt.internal.corext.refactoring.RefactoringAvailabilityTester;
69 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
70 import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange;
71 import org.eclipse.jdt.internal.corext.refactoring.code.ScriptableRefactoring;
72 import org.eclipse.jdt.internal.corext.refactoring.participants.JavaProcessors;
73 import org.eclipse.jdt.internal.corext.refactoring.participants.ResourceProcessors;
74 import org.eclipse.jdt.internal.corext.refactoring.tagging.ICommentProvider;
75 import org.eclipse.jdt.internal.corext.refactoring.tagging.IScriptableRefactoring;
76 import org.eclipse.jdt.internal.corext.refactoring.util.JavaElementUtil;
77 import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
78 import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager;
79 import org.eclipse.jdt.internal.corext.util.Messages;
80 import org.eclipse.jdt.internal.corext.util.Resources;
81
82 import org.eclipse.jdt.internal.ui.JavaPlugin;
83
84 public final class JavaDeleteProcessor extends DeleteProcessor implements IScriptableRefactoring, ICommentProvider {
85
86     private static final String JavaDoc ATTRIBUTE_RESOURCES= "resources"; //$NON-NLS-1$
87
private static final String JavaDoc ATTRIBUTE_ELEMENTS= "elements"; //$NON-NLS-1$
88
private static final String JavaDoc ATTRIBUTE_SUGGEST_ACCESSORS= "accessors"; //$NON-NLS-1$
89
private static final String JavaDoc ATTRIBUTE_DELETE_SUBPACKAGES= "subPackages"; //$NON-NLS-1$
90

91     private boolean fAccessorsDeleted;
92     private boolean fWasCanceled;
93     private boolean fSuggestGetterSetterDeletion;
94     private Object JavaDoc[] fElements;
95     private IResource[] fResources;
96     private IJavaElement[] fJavaElements;
97     private IReorgQueries fDeleteQueries;
98     private DeleteModifications fDeleteModifications;
99     private String JavaDoc fComment;
100
101     private Change fDeleteChange;
102     private boolean fDeleteSubPackages;
103     
104     public static final String JavaDoc IDENTIFIER= "org.eclipse.jdt.ui.DeleteProcessor"; //$NON-NLS-1$
105

106     public JavaDeleteProcessor(Object JavaDoc[] elements) {
107         fElements= elements;
108         if (fElements != null) {
109             fResources= RefactoringAvailabilityTester.getResources(elements);
110             fJavaElements= RefactoringAvailabilityTester.getJavaElements(elements);
111         }
112         fSuggestGetterSetterDeletion= true;
113         fDeleteSubPackages= false;
114         fWasCanceled= false;
115     }
116
117     public String JavaDoc getIdentifier() {
118         return IDENTIFIER;
119     }
120     
121     public boolean isApplicable() throws CoreException {
122         if (fElements.length == 0)
123             return false;
124         if (fElements.length != fResources.length + fJavaElements.length)
125             return false;
126         for (int i= 0; i < fResources.length; i++) {
127             if (!RefactoringAvailabilityTester.isDeleteAvailable(fResources[i]))
128                 return false;
129         }
130         for (int i= 0; i < fJavaElements.length; i++) {
131             if (!RefactoringAvailabilityTester.isDeleteAvailable(fJavaElements[i]))
132                 return false;
133         }
134         return true;
135     }
136     
137     public boolean needsProgressMonitor() {
138         if (fResources != null && fResources.length > 0)
139             return true;
140         if (fJavaElements != null) {
141             for (int i= 0; i < fJavaElements.length; i++) {
142                 int type= fJavaElements[i].getElementType();
143                 if (type <= IJavaElement.CLASS_FILE)
144                     return true;
145             }
146         }
147         return false;
148         
149     }
150
151     public String JavaDoc getProcessorName() {
152         return RefactoringCoreMessages.DeleteRefactoring_7;
153     }
154     
155     public Object JavaDoc[] getElements() {
156         return fElements;
157     }
158     
159     public RefactoringParticipant[] loadParticipants(RefactoringStatus status, SharableParticipants shared) throws CoreException {
160         return fDeleteModifications.loadParticipants(status, this, getAffectedProjectNatures(), shared);
161     }
162     
163     private String JavaDoc[] getAffectedProjectNatures() throws CoreException {
164         String JavaDoc[] jNatures= JavaProcessors.computeAffectedNaturs(fJavaElements);
165         String JavaDoc[] rNatures= ResourceProcessors.computeAffectedNatures(fResources);
166         Set JavaDoc result= new HashSet JavaDoc();
167         result.addAll(Arrays.asList(jNatures));
168         result.addAll(Arrays.asList(rNatures));
169         return (String JavaDoc[])result.toArray(new String JavaDoc[result.size()]);
170     }
171
172     /*
173      * This has to be customizable because when drag and drop is performed on a field,
174      * you don't want to suggest deleting getter/setter if only the field was moved.
175      */

176     public void setSuggestGetterSetterDeletion(boolean suggest){
177         fSuggestGetterSetterDeletion= suggest;
178     }
179     
180     public void setDeleteSubPackages(boolean selection) {
181         fDeleteSubPackages= selection;
182     }
183     
184     public boolean getDeleteSubPackages() {
185         return fDeleteSubPackages;
186     }
187     
188     public boolean hasSubPackagesToDelete() {
189         try {
190             for (int i= 0; i < fJavaElements.length; i++) {
191                 if (fJavaElements[i] instanceof IPackageFragment) {
192                     IPackageFragment packageFragment= (IPackageFragment) fJavaElements[i];
193                     if (packageFragment.isDefaultPackage())
194                         continue; // see bug 132576 (can remove this if(..) continue; statement when bug is fixed)
195
if (packageFragment.hasSubpackages())
196                         return true;
197                 }
198             }
199         } catch (JavaModelException e) {
200             JavaPlugin.log(e);
201         }
202         return false;
203     }
204
205     public void setQueries(IReorgQueries queries){
206         Assert.isNotNull(queries);
207         fDeleteQueries= queries;
208     }
209     
210     public IJavaElement[] getJavaElementsToDelete(){
211         return fJavaElements;
212     }
213
214     public boolean wasCanceled() {
215         return fWasCanceled;
216     }
217     
218     public IResource[] getResourcesToDelete(){
219         return fResources;
220     }
221     
222     /* (non-Javadoc)
223      * @see org.eclipse.jdt.internal.corext.refactoring.base.Refactoring#checkActivation(org.eclipse.core.runtime.IProgressMonitor)
224      */

225     public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException {
226         Assert.isNotNull(fDeleteQueries);//must be set before checking activation
227
RefactoringStatus result= new RefactoringStatus();
228         result.merge(RefactoringStatus.create(Resources.checkInSync(ReorgUtils.getNotLinked(fResources))));
229         IResource[] javaResources= ReorgUtils.getResources(fJavaElements);
230         result.merge(RefactoringStatus.create(Resources.checkInSync(ReorgUtils.getNotNulls(javaResources))));
231         for (int i= 0; i < fJavaElements.length; i++) {
232             IJavaElement element= fJavaElements[i];
233             if (element instanceof IType && ((IType)element).isAnonymous()) {
234                 // work around for bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=44450
235
// result.addFatalError("Currently, there isn't any support to delete an anonymous type.");
236
}
237         }
238         return result;
239     }
240
241     /* (non-Javadoc)
242      * @see org.eclipse.jdt.internal.corext.refactoring.base.Refactoring#checkInput(org.eclipse.core.runtime.IProgressMonitor)
243      */

244     public RefactoringStatus checkFinalConditions(IProgressMonitor pm, CheckConditionsContext context) throws CoreException {
245         pm.beginTask(RefactoringCoreMessages.DeleteRefactoring_1, 1);
246         try{
247             fWasCanceled= false;
248             RefactoringStatus result= new RefactoringStatus();
249
250             recalculateElementsToDelete();
251
252             checkDirtyCompilationUnits(result);
253             checkDirtyResources(result);
254             fDeleteModifications= new DeleteModifications();
255             fDeleteModifications.delete(fResources);
256             fDeleteModifications.delete(fJavaElements);
257             List JavaDoc/*<IResource>*/ packageDeletes= fDeleteModifications.postProcess();
258             
259             TextChangeManager manager= new TextChangeManager();
260             fDeleteChange= DeleteChangeCreator.createDeleteChange(manager, fResources, fJavaElements, getProcessorName(), packageDeletes);
261             
262             ResourceChangeChecker checker= (ResourceChangeChecker) context.getChecker(ResourceChangeChecker.class);
263             IResourceChangeDescriptionFactory deltaFactory= checker.getDeltaFactory();
264             fDeleteModifications.buildDelta(deltaFactory);
265             IFile[] files= ResourceUtil.getFiles(manager.getAllCompilationUnits());
266             for (int i= 0; i < files.length; i++) {
267                 deltaFactory.change(files[i]);
268             }
269             return result;
270         } catch (OperationCanceledException e) {
271             fWasCanceled= true;
272             throw e;
273         } catch (JavaModelException e){
274             throw e;
275         } catch (CoreException e) {
276             throw new JavaModelException(e);
277         } finally{
278             pm.done();
279         }
280     }
281     
282     private void checkDirtyCompilationUnits(RefactoringStatus result) throws CoreException {
283         if (fJavaElements == null || fJavaElements.length == 0)
284             return;
285         for (int je= 0; je < fJavaElements.length; je++) {
286             IJavaElement element= fJavaElements[je];
287             if (element instanceof ICompilationUnit) {
288                 checkDirtyCompilationUnit(result, (ICompilationUnit)element);
289             } else if (element instanceof IPackageFragment) {
290                 ICompilationUnit[] units= ((IPackageFragment)element).getCompilationUnits();
291                 for (int u = 0; u < units.length; u++) {
292                     checkDirtyCompilationUnit(result, units[u]);
293                 }
294             }
295         }
296     }
297     
298     private void checkDirtyCompilationUnit(RefactoringStatus result, ICompilationUnit cunit) {
299         IResource resource= cunit.getResource();
300         if (resource == null || resource.getType() != IResource.FILE)
301             return;
302         checkDirtyFile(result, (IFile)resource);
303     }
304
305     private void checkDirtyResources(final RefactoringStatus result) throws CoreException {
306         for (int i= 0; i < fResources.length; i++) {
307             IResource resource= fResources[i];
308             resource.accept(new IResourceVisitor() {
309                 public boolean visit(IResource visitedResource) throws CoreException {
310                     if (visitedResource instanceof IFile) {
311                         checkDirtyFile(result, (IFile)visitedResource);
312                     }
313                     return true;
314                 }
315             }, IResource.DEPTH_INFINITE, false);
316         }
317     }
318     
319     private void checkDirtyFile(RefactoringStatus result, IFile file) {
320         if (file == null || !file.exists())
321             return;
322         ITextFileBuffer buffer= FileBuffers.getTextFileBufferManager().getTextFileBuffer(file.getFullPath(), LocationKind.IFILE);
323         if (buffer != null && buffer.isDirty()) {
324             if (buffer.isStateValidated() && buffer.isSynchronized()) {
325                 result.addWarning(Messages.format(
326                     RefactoringCoreMessages.JavaDeleteProcessor_unsaved_changes,
327                     file.getFullPath().toString()));
328             } else {
329                 result.addFatalError(Messages.format(
330                     RefactoringCoreMessages.JavaDeleteProcessor_unsaved_changes,
331                     file.getFullPath().toString()));
332             }
333         }
334     }
335
336     /*
337      * The set of elements that will eventually be deleted may be very different from the set
338      * originally selected - there may be fewer, more or different elements.
339      * This method is used to calculate the set of elements that will be deleted - if necessary,
340      * it asks the user.
341      */

342     private void recalculateElementsToDelete() throws CoreException {
343         //the sequence is critical here
344
fAccessorsDeleted= false;
345         if (fDeleteSubPackages) /* add subpackages first, to allow removing elements with parents in selection etc. */
346             addSubPackages();
347         
348         removeElementsWithParentsInSelection(); /*ask before adding empty cus - you don't want to ask if you, for example delete
349                                                  *the package, in which the cus live*/

350         removeUnconfirmedFoldersThatContainSourceFolders(); /* a selected folder may be a parent of a source folder
351                                                              * we must inform the user about it and ask if ok to delete the folder*/

352         removeUnconfirmedReferencedArchives();
353         addEmptyCusToDelete();
354         removeJavaElementsChildrenOfJavaElements();/*because adding cus may create elements (types in cus)
355                                                     *whose parents are in selection*/

356         confirmDeletingReadOnly(); /*after empty cus - you want to ask for all cus that are to be deleted*/
357     
358         if (fSuggestGetterSetterDeletion)
359             addGettersSetters();/*at the end - this cannot invalidate anything*/
360         
361         addDeletableParentPackagesOnPackageDeletion(); /* do not change the sequence in fJavaElements after this method */
362     }
363
364     /**
365      * Adds all subpackages of the selected packages to the list of items to be
366      * deleted.
367      *
368      * @throws JavaModelException
369      */

370     private void addSubPackages() throws JavaModelException {
371
372         final Set JavaDoc javaElements= new HashSet JavaDoc();
373         for (int i= 0; i < fJavaElements.length; i++) {
374             if (fJavaElements[i] instanceof IPackageFragment) {
375                 javaElements.addAll(Arrays.asList(JavaElementUtil.getPackageAndSubpackages((IPackageFragment) fJavaElements[i])));
376             } else {
377                 javaElements.add(fJavaElements[i]);
378             }
379         }
380
381         fJavaElements= (IJavaElement[]) javaElements.toArray(new IJavaElement[javaElements.size()]);
382     }
383
384     /**
385      * Add deletable parent packages to the list of items to delete.
386      *
387      * @throws CoreException
388      */

389     private void addDeletableParentPackagesOnPackageDeletion() throws CoreException {
390
391         final List JavaDoc/* <IPackageFragment */initialPackagesToDelete= ReorgUtils.getElementsOfType(fJavaElements, IJavaElement.PACKAGE_FRAGMENT);
392
393         if (initialPackagesToDelete.size() == 0)
394             return;
395
396         // Move from inner to outer packages
397
Collections.sort(initialPackagesToDelete, new Comparator JavaDoc() {
398             public int compare(Object JavaDoc arg0, Object JavaDoc arg1) {
399                 IPackageFragment one= (IPackageFragment) arg0;
400                 IPackageFragment two= (IPackageFragment) arg1;
401                 return two.getElementName().compareTo(one.getElementName());
402             }
403         });
404
405         // Get resources and java elements which will be deleted as well
406
final Set JavaDoc/* <IResource> */deletedChildren= new HashSet JavaDoc();
407         deletedChildren.addAll(Arrays.asList(fResources));
408         for (int i= 0; i < fJavaElements.length; i++) {
409             if (!ReorgUtils.isInsideCompilationUnit(fJavaElements[i]))
410                 deletedChildren.add(fJavaElements[i].getResource());
411         }
412
413         // new package list in the right sequence
414
final List JavaDoc/* <IPackageFragment */allFragmentsToDelete= new ArrayList JavaDoc();
415
416         for (Iterator JavaDoc outerIter= initialPackagesToDelete.iterator(); outerIter.hasNext();) {
417             final IPackageFragment currentPackageFragment= (IPackageFragment) outerIter.next();
418             
419             // The package will at least be cleared
420
allFragmentsToDelete.add(currentPackageFragment);
421
422             if (canRemoveCompletely(currentPackageFragment, initialPackagesToDelete)) {
423                 
424                 final IPackageFragment parent= JavaElementUtil.getParentSubpackage(currentPackageFragment);
425                 if (parent != null && !initialPackagesToDelete.contains(parent)) {
426
427                     final List JavaDoc/* <IPackageFragment> */emptyParents= new ArrayList JavaDoc();
428                     addDeletableParentPackages(parent, initialPackagesToDelete, deletedChildren, emptyParents);
429
430                     // Add parents in the right sequence (inner to outer)
431
allFragmentsToDelete.addAll(emptyParents);
432                 }
433             }
434         }
435
436         // Remove resources in deleted packages; and the packages as well
437
final List JavaDoc/* <IJavaElement> */javaElements= new ArrayList JavaDoc();
438         for (int i= 0; i < fJavaElements.length; i++) {
439             if (!(fJavaElements[i] instanceof IPackageFragment)) {
440                 // remove children of deleted packages
441
final IPackageFragment frag= (IPackageFragment) fJavaElements[i].getAncestor(IJavaElement.PACKAGE_FRAGMENT);
442                 if (!allFragmentsToDelete.contains(frag))
443                     javaElements.add(fJavaElements[i]);
444             }
445         }
446         // Re-add deleted packages - note the (new) sequence
447
javaElements.addAll(allFragmentsToDelete);
448
449         // Remove resources in deleted folders
450
final List JavaDoc/* <IResource> */resources= new ArrayList JavaDoc();
451         for (int i= 0; i < fResources.length; i++) {
452             IResource parent= fResources[i];
453             if (parent.getType() == IResource.FILE)
454                 parent= parent.getParent();
455             if (!deletedChildren.contains(parent))
456                 resources.add(fResources[i]);
457         }
458
459         fJavaElements= (IJavaElement[]) javaElements.toArray(new IJavaElement[javaElements.size()]);
460         fResources= (IResource[]) resources.toArray(new IResource[resources.size()]);
461     }
462
463     /**
464      * Returns true if this initially selected package is really deletable
465      * (if it has non-selected subpackages, it may only be cleared).
466      *
467      */

468     private boolean canRemoveCompletely(IPackageFragment pack, List JavaDoc packagesToDelete) throws JavaModelException {
469         final IPackageFragment[] subPackages= JavaElementUtil.getPackageAndSubpackages(pack);
470         for (int i= 0; i < subPackages.length; i++) {
471             if (!(subPackages[i].equals(pack)) && !(packagesToDelete.contains(subPackages[i])))
472                 return false;
473         }
474         return true;
475     }
476
477     /**
478      * Adds deletable parent packages of the fragment "frag" to the list
479      * "deletableParentPackages"; also adds the resources of those packages to the
480      * set "resourcesToDelete".
481      *
482      */

483     private void addDeletableParentPackages(IPackageFragment frag, List JavaDoc initialPackagesToDelete, Set JavaDoc resourcesToDelete, List JavaDoc deletableParentPackages)
484             throws CoreException {
485
486         if (frag.getResource().isLinked()) {
487             final IConfirmQuery query= fDeleteQueries.createYesNoQuery(RefactoringCoreMessages.JavaDeleteProcessor_confirm_linked_folder_delete, false, IReorgQueries.CONFIRM_DELETE_LINKED_PARENT);
488             if (!query.confirm(Messages.format(RefactoringCoreMessages.JavaDeleteProcessor_delete_linked_folder_question, new String JavaDoc[] { frag.getResource().getName() })))
489                     return;
490         }
491         
492         final IResource[] children= (((IContainer) frag.getResource())).members();
493         for (int i= 0; i < children.length; i++) {
494             // Child must be a package fragment already in the list,
495
// or a resource which is deleted as well.
496
if (!resourcesToDelete.contains(children[i]))
497                 return;
498         }
499         resourcesToDelete.add(frag.getResource());
500         deletableParentPackages.add(frag);
501
502         final IPackageFragment parent= JavaElementUtil.getParentSubpackage(frag);
503         if (parent != null && !initialPackagesToDelete.contains(parent))
504             addDeletableParentPackages(parent, initialPackagesToDelete, resourcesToDelete, deletableParentPackages);
505     }
506
507     // ask for confirmation of deletion of all package fragment roots that are
508
// on classpaths of other projects
509
private void removeUnconfirmedReferencedArchives() throws JavaModelException {
510         String JavaDoc queryTitle= RefactoringCoreMessages.DeleteRefactoring_2;
511         IConfirmQuery query= fDeleteQueries.createYesYesToAllNoNoToAllQuery(queryTitle, true, IReorgQueries.CONFIRM_DELETE_REFERENCED_ARCHIVES);
512         removeUnconfirmedReferencedPackageFragmentRoots(query);
513         removeUnconfirmedReferencedArchiveFiles(query);
514     }
515
516     private void removeUnconfirmedReferencedArchiveFiles(IConfirmQuery query) throws JavaModelException, OperationCanceledException {
517         List JavaDoc filesToSkip= new ArrayList JavaDoc(0);
518         for (int i= 0; i < fResources.length; i++) {
519             IResource resource= fResources[i];
520             if (! (resource instanceof IFile))
521                 continue;
522         
523             IJavaProject project= JavaCore.create(resource.getProject());
524             if (project == null || ! project.exists())
525                 continue;
526             IPackageFragmentRoot root= project.findPackageFragmentRoot(resource.getFullPath());
527             if (root == null)
528                 continue;
529             List JavaDoc referencingProjects= Arrays.asList(JavaElementUtil.getReferencingProjects(root));
530             if (skipDeletingReferencedRoot(query, root, referencingProjects))
531                 filesToSkip.add(resource);
532         }
533         removeFromSetToDelete((IFile[]) filesToSkip.toArray(new IFile[filesToSkip.size()]));
534     }
535
536     private void removeUnconfirmedReferencedPackageFragmentRoots(IConfirmQuery query) throws JavaModelException, OperationCanceledException {
537         List JavaDoc rootsToSkip= new ArrayList JavaDoc(0);
538         for (int i= 0; i < fJavaElements.length; i++) {
539             IJavaElement element= fJavaElements[i];
540             if (! (element instanceof IPackageFragmentRoot))
541                 continue;
542             IPackageFragmentRoot root= (IPackageFragmentRoot)element;
543             ArrayList JavaDoc referencingProjects= new ArrayList JavaDoc(Arrays.asList(JavaElementUtil.getReferencingProjects(root)));
544             referencingProjects.remove(root.getJavaProject());
545             if (skipDeletingReferencedRoot(query, root, referencingProjects))
546                 rootsToSkip.add(root);
547         }
548         removeFromSetToDelete((IJavaElement[]) rootsToSkip.toArray(new IJavaElement[rootsToSkip.size()]));
549     }
550
551     private static boolean skipDeletingReferencedRoot(IConfirmQuery query, IPackageFragmentRoot root, List JavaDoc referencingProjects) throws OperationCanceledException {
552         if (referencingProjects.isEmpty() || root == null || ! root.exists() ||! root.isArchive())
553             return false;
554         String JavaDoc question= Messages.format(RefactoringCoreMessages.DeleteRefactoring_3, root.getElementName());
555         return ! query.confirm(question, referencingProjects.toArray());
556     }
557
558     private void removeUnconfirmedFoldersThatContainSourceFolders() throws CoreException {
559         String JavaDoc queryTitle= RefactoringCoreMessages.DeleteRefactoring_4;
560         IConfirmQuery query= fDeleteQueries.createYesYesToAllNoNoToAllQuery(queryTitle, true, IReorgQueries.CONFIRM_DELETE_FOLDERS_CONTAINING_SOURCE_FOLDERS);
561         List JavaDoc foldersToSkip= new ArrayList JavaDoc(0);
562         for (int i= 0; i < fResources.length; i++) {
563             IResource resource= fResources[i];
564             if (resource instanceof IFolder){
565                 IFolder folder= (IFolder)resource;
566                 if (containsSourceFolder(folder)){
567                     String JavaDoc question= Messages.format(RefactoringCoreMessages.DeleteRefactoring_5, folder.getName());
568                     if (! query.confirm(question))
569                         foldersToSkip.add(folder);
570                 }
571             }
572         }
573         removeFromSetToDelete((IResource[]) foldersToSkip.toArray(new IResource[foldersToSkip.size()]));
574     }
575
576     private static boolean containsSourceFolder(IFolder folder) throws CoreException {
577         IResource[] subFolders= folder.members();
578         for (int i = 0; i < subFolders.length; i++) {
579             if (! (subFolders[i] instanceof IFolder))
580                 continue;
581             IJavaElement element= JavaCore.create(folder);
582             if (element instanceof IPackageFragmentRoot)
583                 return true;
584             if (element instanceof IPackageFragment)
585                 continue;
586             if (containsSourceFolder((IFolder)subFolders[i]))
587                 return true;
588         }
589         return false;
590     }
591
592     private void removeElementsWithParentsInSelection() {
593         ParentChecker parentUtil= new ParentChecker(fResources, fJavaElements);
594         parentUtil.removeElementsWithAncestorsOnList(false);
595         fJavaElements= parentUtil.getJavaElements();
596         fResources= parentUtil.getResources();
597     }
598
599     private void removeJavaElementsChildrenOfJavaElements(){
600         ParentChecker parentUtil= new ParentChecker(fResources, fJavaElements);
601         parentUtil.removeElementsWithAncestorsOnList(true);
602         fJavaElements= parentUtil.getJavaElements();
603     }
604     
605     public Change createChange(IProgressMonitor monitor) throws CoreException {
606         try {
607             monitor.beginTask(RefactoringCoreMessages.JavaDeleteProcessor_creating_change, 1);
608             final Map JavaDoc arguments= new HashMap JavaDoc();
609             final String JavaDoc description= fElements.length == 1 ? RefactoringCoreMessages.JavaDeleteProcessor_description_singular : RefactoringCoreMessages.JavaDeleteProcessor_description_plural;
610             final IProject resource= getSingleProject();
611             final String JavaDoc project= resource != null ? resource.getName() : null;
612             final String JavaDoc source= project != null ? Messages.format(RefactoringCoreMessages.JavaDeleteProcessor_project_pattern, project) : RefactoringCoreMessages.JavaDeleteProcessor_workspace;
613             final String JavaDoc header= Messages.format(RefactoringCoreMessages.JavaDeleteProcessor_header, new String JavaDoc[] { String.valueOf(fElements.length), source});
614             int flags= JavaRefactoringDescriptor.JAR_MIGRATION | JavaRefactoringDescriptor.JAR_REFACTORING | RefactoringDescriptor.STRUCTURAL_CHANGE | RefactoringDescriptor.MULTI_CHANGE;
615             final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(project, this, header);
616             if (fDeleteSubPackages)
617                 comment.addSetting(RefactoringCoreMessages.JavaDeleteProcessor_delete_subpackages);
618             if (fAccessorsDeleted)
619                 comment.addSetting(RefactoringCoreMessages.JavaDeleteProcessor_delete_accessors);
620             final JDTRefactoringDescriptor descriptor= new JDTRefactoringDescriptor(IJavaRefactorings.DELETE, project, description, comment.asString(), arguments, flags);
621             arguments.put(ATTRIBUTE_DELETE_SUBPACKAGES, Boolean.valueOf(fDeleteSubPackages).toString());
622             arguments.put(ATTRIBUTE_SUGGEST_ACCESSORS, Boolean.valueOf(fSuggestGetterSetterDeletion).toString());
623             arguments.put(ATTRIBUTE_RESOURCES, new Integer JavaDoc(fResources.length).toString());
624             for (int offset= 0; offset < fResources.length; offset++)
625                 arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_ELEMENT + (offset + 1), descriptor.resourceToHandle(fResources[offset]));
626             arguments.put(ATTRIBUTE_ELEMENTS, new Integer JavaDoc(fJavaElements.length).toString());
627             for (int offset= 0; offset < fJavaElements.length; offset++)
628                 arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_ELEMENT + (offset + fResources.length + 1), descriptor.elementToHandle(fJavaElements[offset]));
629             return new DynamicValidationRefactoringChange(descriptor, RefactoringCoreMessages.DeleteRefactoring_7, new Change[] { fDeleteChange});
630         } finally {
631             monitor.done();
632         }
633     }
634
635     private IProject getSingleProject() {
636         IProject first= null;
637         for (int index= 0; index < fElements.length; index++) {
638             IProject project= null;
639             if (fElements[index] instanceof IJavaElement)
640                 project= ((IJavaElement) fElements[index]).getJavaProject().getProject();
641             else if (fElements[index] instanceof IResource)
642                 project= ((IResource) fElements[index]).getProject();
643             if (project != null) {
644                 if (first == null)
645                     first= project;
646                 else if (!project.equals(first))
647                     return null;
648             }
649         }
650         return first;
651     }
652
653     private void addToSetToDelete(IJavaElement[] newElements){
654         fJavaElements= ReorgUtils.union(fJavaElements, newElements);
655     }
656     
657     private void removeFromSetToDelete(IResource[] resourcesToNotDelete) {
658         fResources= ReorgUtils.setMinus(fResources, resourcesToNotDelete);
659     }
660     
661     private void removeFromSetToDelete(IJavaElement[] elementsToNotDelete) {
662         fJavaElements= ReorgUtils.setMinus(fJavaElements, elementsToNotDelete);
663     }
664
665     private void addGettersSetters() throws JavaModelException {
666         IField[] fields= getFields(fJavaElements);
667         if (fields.length == 0)
668             return;
669         //IField -> IMethod[]
670
Map JavaDoc getterSetterMapping= createGetterSetterMapping(fields);
671         if (getterSetterMapping.isEmpty())
672             return;
673         removeAlreadySelectedMethods(getterSetterMapping);
674         if (getterSetterMapping.isEmpty())
675             return;
676         fAccessorsDeleted= true;
677         List JavaDoc gettersSettersToAdd= getGettersSettersToDelete(getterSetterMapping);
678         addToSetToDelete((IMethod[]) gettersSettersToAdd.toArray(new IMethod[gettersSettersToAdd.size()]));
679     }
680
681     private List JavaDoc getGettersSettersToDelete(Map JavaDoc getterSetterMapping) {
682         List JavaDoc gettersSettersToAdd= new ArrayList JavaDoc(getterSetterMapping.size());
683         String JavaDoc queryTitle= RefactoringCoreMessages.DeleteRefactoring_8;
684         IConfirmQuery getterSetterQuery= fDeleteQueries.createYesYesToAllNoNoToAllQuery(queryTitle, true, IReorgQueries.CONFIRM_DELETE_GETTER_SETTER);
685         for (Iterator JavaDoc iter= getterSetterMapping.keySet().iterator(); iter.hasNext();) {
686             IField field= (IField) iter.next();
687             Assert.isTrue(hasGetter(getterSetterMapping, field) || hasSetter(getterSetterMapping, field));
688             String JavaDoc deleteGetterSetter= Messages.format(RefactoringCoreMessages.DeleteRefactoring_9, JavaElementUtil.createFieldSignature(field));
689             if (getterSetterQuery.confirm(deleteGetterSetter)){
690                 if (hasGetter(getterSetterMapping, field))
691                     gettersSettersToAdd.add(getGetter(getterSetterMapping, field));
692                 if (hasSetter(getterSetterMapping, field))
693                     gettersSettersToAdd.add(getSetter(getterSetterMapping, field));
694             }
695         }
696         return gettersSettersToAdd;
697     }
698
699     //note: modifies the mapping
700
private void removeAlreadySelectedMethods(Map JavaDoc getterSetterMapping) {
701         List JavaDoc elementsToDelete= Arrays.asList(fJavaElements);
702         for (Iterator JavaDoc iter= getterSetterMapping.keySet().iterator(); iter.hasNext();) {
703             IField field= (IField) iter.next();
704             //remove getter
705
IMethod getter= getGetter(getterSetterMapping, field);
706             if (getter != null && elementsToDelete.contains(getter))
707                 removeGetterFromMapping(getterSetterMapping, field);
708
709             //remove setter
710
IMethod setter= getSetter(getterSetterMapping, field);
711             if (setter != null && elementsToDelete.contains(setter))
712                 removeSetterFromMapping(getterSetterMapping, field);
713
714             //both getter and setter already included
715
if (! hasGetter(getterSetterMapping, field) && ! hasSetter(getterSetterMapping, field))
716                 iter.remove();
717         }
718     }
719
720     /*
721      * IField -> IMethod[] (array of 2 - [getter, setter], one of which can be null)
722      */

723     private static Map JavaDoc createGetterSetterMapping(IField[] fields) throws JavaModelException {
724         Map JavaDoc result= new HashMap JavaDoc();
725         for (int i= 0; i < fields.length; i++) {
726             IField field= fields[i];
727             IMethod[] getterSetter= getGetterSetter(field);
728             if (getterSetter != null)
729                 result.put(field, getterSetter);
730         }
731         return result;
732     }
733     private static boolean hasSetter(Map JavaDoc getterSetterMapping, IField field){
734         return getterSetterMapping.containsKey(field) &&
735                getSetter(getterSetterMapping, field) != null;
736     }
737     private static boolean hasGetter(Map JavaDoc getterSetterMapping, IField field){
738         return getterSetterMapping.containsKey(field) &&
739                getGetter(getterSetterMapping, field) != null;
740     }
741     private static void removeGetterFromMapping(Map JavaDoc getterSetterMapping, IField field){
742         ((IMethod[])getterSetterMapping.get(field))[0]= null;
743     }
744     private static void removeSetterFromMapping(Map JavaDoc getterSetterMapping, IField field){
745         ((IMethod[])getterSetterMapping.get(field))[1]= null;
746     }
747     private static IMethod getGetter(Map JavaDoc getterSetterMapping, IField field){
748         return ((IMethod[])getterSetterMapping.get(field))[0];
749     }
750     private static IMethod getSetter(Map JavaDoc getterSetterMapping, IField field){
751         return ((IMethod[])getterSetterMapping.get(field))[1];
752     }
753     private static IField[] getFields(IJavaElement[] elements){
754         List JavaDoc fields= new ArrayList JavaDoc(3);
755         for (int i= 0; i < elements.length; i++) {
756             if (elements[i] instanceof IField)
757                 fields.add(elements[i]);
758         }
759         return (IField[]) fields.toArray(new IField[fields.size()]);
760     }
761
762     /*
763      * returns an array of 2 [getter, setter] or null if no getter or setter exists
764      */

765     private static IMethod[] getGetterSetter(IField field) throws JavaModelException {
766         IMethod getter= GetterSetterUtil.getGetter(field);
767         IMethod setter= GetterSetterUtil.getSetter(field);
768         if ((getter != null && getter.exists()) || (setter != null && setter.exists()))
769             return new IMethod[]{getter, setter};
770         else
771             return null;
772     }
773
774     //----------- read-only confirmation business ------
775
private void confirmDeletingReadOnly() throws CoreException {
776         if (! ReadOnlyResourceFinder.confirmDeleteOfReadOnlyElements(fJavaElements, fResources, fDeleteQueries))
777             throw new OperationCanceledException(); //saying 'no' to this one is like cancelling the whole operation
778
}
779
780     //----------- empty CUs related method
781
private void addEmptyCusToDelete() throws JavaModelException {
782         Set JavaDoc cusToEmpty= getCusToEmpty();
783         addToSetToDelete((ICompilationUnit[]) cusToEmpty.toArray(new ICompilationUnit[cusToEmpty.size()]));
784     }
785
786     private Set JavaDoc getCusToEmpty() throws JavaModelException {
787         Set JavaDoc result= new HashSet JavaDoc();
788         for (int i= 0; i < fJavaElements.length; i++) {
789             IJavaElement element= fJavaElements[i];
790             ICompilationUnit cu= ReorgUtils.getCompilationUnit(element);
791             if (cu != null && ! result.contains(cu) && willHaveAllTopLevelTypesDeleted(cu))
792                 result.add(cu);
793         }
794         return result;
795     }
796
797     private boolean willHaveAllTopLevelTypesDeleted(ICompilationUnit cu) throws JavaModelException {
798         Set JavaDoc elementSet= new HashSet JavaDoc(Arrays.asList(fJavaElements));
799         IType[] topLevelTypes= cu.getTypes();
800         for (int i= 0; i < topLevelTypes.length; i++) {
801             if (! elementSet.contains(topLevelTypes[i]))
802                 return false;
803         }
804         return true;
805     }
806
807     public boolean canEnableComment() {
808         return true;
809     }
810
811     public String JavaDoc getComment() {
812         return fComment;
813     }
814
815     public void setComment(String JavaDoc comment) {
816         fComment= comment;
817     }
818
819     public RefactoringStatus initialize(RefactoringArguments arguments) {
820         setQueries(new NullReorgQueries());
821         final RefactoringStatus status= new RefactoringStatus();
822         if (arguments instanceof JavaRefactoringArguments) {
823             final JavaRefactoringArguments extended= (JavaRefactoringArguments) arguments;
824             final String JavaDoc subPackages= extended.getAttribute(ATTRIBUTE_DELETE_SUBPACKAGES);
825             if (subPackages != null) {
826                 fDeleteSubPackages= Boolean.valueOf(subPackages).booleanValue();
827             } else
828                 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_DELETE_SUBPACKAGES));
829             final String JavaDoc suggest= extended.getAttribute(ATTRIBUTE_SUGGEST_ACCESSORS);
830             if (suggest != null) {
831                 fSuggestGetterSetterDeletion= Boolean.valueOf(suggest).booleanValue();
832             } else
833                 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_SUGGEST_ACCESSORS));
834             int resourceCount= 0;
835             int elementCount= 0;
836             String JavaDoc value= extended.getAttribute(ATTRIBUTE_RESOURCES);
837             if (value != null && !"".equals(value)) {//$NON-NLS-1$
838
try {
839                     resourceCount= Integer.parseInt(value);
840                 } catch (NumberFormatException JavaDoc exception) {
841                     return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_RESOURCES));
842                 }
843             } else
844                 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_RESOURCES));
845             value= extended.getAttribute(ATTRIBUTE_ELEMENTS);
846             if (value != null && !"".equals(value)) {//$NON-NLS-1$
847
try {
848                     elementCount= Integer.parseInt(value);
849                 } catch (NumberFormatException JavaDoc exception) {
850                     return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_ELEMENTS));
851                 }
852             } else
853                 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_ELEMENTS));
854             String JavaDoc handle= null;
855             List JavaDoc elements= new ArrayList JavaDoc();
856             for (int index= 0; index < resourceCount; index++) {
857                 final String JavaDoc attribute= JDTRefactoringDescriptor.ATTRIBUTE_ELEMENT + (index + 1);
858                 handle= extended.getAttribute(attribute);
859                 if (handle != null && !"".equals(handle)) { //$NON-NLS-1$
860
final IResource resource= JDTRefactoringDescriptor.handleToResource(extended.getProject(), handle);
861                     if (resource == null || !resource.exists())
862                         status.merge(ScriptableRefactoring.createInputWarningStatus(resource, getRefactoring().getName(), IJavaRefactorings.DELETE));
863                     else
864                         elements.add(resource);
865                 } else
866                     return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, attribute));
867             }
868             fResources= (IResource[]) elements.toArray(new IResource[elements.size()]);
869             elements= new ArrayList JavaDoc();
870             for (int index= 0; index < elementCount; index++) {
871                 final String JavaDoc attribute= JDTRefactoringDescriptor.ATTRIBUTE_ELEMENT + (resourceCount + index + 1);
872                 handle= extended.getAttribute(attribute);
873                 if (handle != null && !"".equals(handle)) { //$NON-NLS-1$
874
final IJavaElement element= JDTRefactoringDescriptor.handleToElement(extended.getProject(), handle, false);
875                     if (element == null || !element.exists())
876                         status.merge(ScriptableRefactoring.createInputWarningStatus(element, getRefactoring().getName(), IJavaRefactorings.DELETE));
877                     else
878                         elements.add(element);
879                 } else
880                     return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, attribute));
881             }
882             fJavaElements= (IJavaElement[]) elements.toArray(new IJavaElement[elements.size()]);
883             fElements= new Object JavaDoc[fResources.length + fJavaElements.length];
884             System.arraycopy(fResources, 0, fElements, 0, fResources.length);
885             System.arraycopy(fJavaElements, 0, fElements, fResources.length, fJavaElements.length);
886         } else
887             return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments);
888         return status;
889     }
890 }
891
Popular Tags