KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > corext > refactoring > rename > RenameTypeProcessor


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  * Matt Chapman, mpchapman@gmail.com - 89977 Make JDT .java agnostic
11  *******************************************************************************/

12 package org.eclipse.jdt.internal.corext.refactoring.rename;
13
14 import java.util.ArrayList JavaDoc;
15 import java.util.Arrays JavaDoc;
16 import java.util.HashMap JavaDoc;
17 import java.util.HashSet JavaDoc;
18 import java.util.Iterator JavaDoc;
19 import java.util.LinkedHashMap JavaDoc;
20 import java.util.List JavaDoc;
21 import java.util.Map JavaDoc;
22 import java.util.Set JavaDoc;
23
24 import org.eclipse.text.edits.ReplaceEdit;
25
26 import org.eclipse.core.runtime.Assert;
27 import org.eclipse.core.runtime.CoreException;
28 import org.eclipse.core.runtime.IConfigurationElement;
29 import org.eclipse.core.runtime.IProduct;
30 import org.eclipse.core.runtime.IProgressMonitor;
31 import org.eclipse.core.runtime.IStatus;
32 import org.eclipse.core.runtime.NullProgressMonitor;
33 import org.eclipse.core.runtime.OperationCanceledException;
34 import org.eclipse.core.runtime.Platform;
35 import org.eclipse.core.runtime.SubProgressMonitor;
36
37 import org.eclipse.core.resources.IContainer;
38 import org.eclipse.core.resources.IFile;
39 import org.eclipse.core.resources.IResource;
40
41 import org.eclipse.ltk.core.refactoring.Change;
42 import org.eclipse.ltk.core.refactoring.GroupCategory;
43 import org.eclipse.ltk.core.refactoring.GroupCategorySet;
44 import org.eclipse.ltk.core.refactoring.IResourceMapper;
45 import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
46 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
47 import org.eclipse.ltk.core.refactoring.RefactoringStatusContext;
48 import org.eclipse.ltk.core.refactoring.TextChange;
49 import org.eclipse.ltk.core.refactoring.TextFileChange;
50 import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
51 import org.eclipse.ltk.core.refactoring.participants.IParticipantDescriptorFilter;
52 import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments;
53 import org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor;
54 import org.eclipse.ltk.core.refactoring.participants.RenameArguments;
55
56 import org.eclipse.jdt.core.Flags;
57 import org.eclipse.jdt.core.ICompilationUnit;
58 import org.eclipse.jdt.core.IField;
59 import org.eclipse.jdt.core.IImportDeclaration;
60 import org.eclipse.jdt.core.IJavaElement;
61 import org.eclipse.jdt.core.IJavaProject;
62 import org.eclipse.jdt.core.ILocalVariable;
63 import org.eclipse.jdt.core.IMember;
64 import org.eclipse.jdt.core.IMethod;
65 import org.eclipse.jdt.core.IPackageFragment;
66 import org.eclipse.jdt.core.ISourceRange;
67 import org.eclipse.jdt.core.IType;
68 import org.eclipse.jdt.core.ITypeHierarchy;
69 import org.eclipse.jdt.core.JavaCore;
70 import org.eclipse.jdt.core.JavaModelException;
71 import org.eclipse.jdt.core.Signature;
72 import org.eclipse.jdt.core.dom.AST;
73 import org.eclipse.jdt.core.dom.ASTVisitor;
74 import org.eclipse.jdt.core.dom.CompilationUnit;
75 import org.eclipse.jdt.core.dom.MethodDeclaration;
76 import org.eclipse.jdt.core.dom.Modifier;
77 import org.eclipse.jdt.core.dom.TypeDeclaration;
78 import org.eclipse.jdt.core.refactoring.IJavaElementMapper;
79 import org.eclipse.jdt.core.refactoring.IJavaRefactorings;
80 import org.eclipse.jdt.core.refactoring.RenameTypeArguments;
81 import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor;
82 import org.eclipse.jdt.core.refactoring.descriptors.RenameJavaElementDescriptor;
83 import org.eclipse.jdt.core.search.IJavaSearchConstants;
84 import org.eclipse.jdt.core.search.IJavaSearchScope;
85 import org.eclipse.jdt.core.search.SearchMatch;
86 import org.eclipse.jdt.core.search.SearchPattern;
87 import org.eclipse.jdt.core.search.TypeReferenceMatch;
88
89 import org.eclipse.jdt.internal.corext.refactoring.Checks;
90 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptor;
91 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment;
92 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments;
93 import org.eclipse.jdt.internal.corext.refactoring.RefactoringAvailabilityTester;
94 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
95 import org.eclipse.jdt.internal.corext.refactoring.RefactoringScopeFactory;
96 import org.eclipse.jdt.internal.corext.refactoring.RefactoringSearchEngine;
97 import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup;
98 import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext;
99 import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange;
100 import org.eclipse.jdt.internal.corext.refactoring.changes.RenameCompilationUnitChange;
101 import org.eclipse.jdt.internal.corext.refactoring.changes.RenameResourceChange;
102 import org.eclipse.jdt.internal.corext.refactoring.changes.TextChangeCompatibility;
103 import org.eclipse.jdt.internal.corext.refactoring.code.ScriptableRefactoring;
104 import org.eclipse.jdt.internal.corext.refactoring.participants.JavaProcessors;
105 import org.eclipse.jdt.internal.corext.refactoring.tagging.IQualifiedNameUpdating;
106 import org.eclipse.jdt.internal.corext.refactoring.tagging.IReferenceUpdating;
107 import org.eclipse.jdt.internal.corext.refactoring.tagging.ISimilarDeclarationUpdating;
108 import org.eclipse.jdt.internal.corext.refactoring.tagging.ITextUpdating;
109 import org.eclipse.jdt.internal.corext.refactoring.util.Changes;
110 import org.eclipse.jdt.internal.corext.refactoring.util.JavaElementUtil;
111 import org.eclipse.jdt.internal.corext.refactoring.util.QualifiedNameFinder;
112 import org.eclipse.jdt.internal.corext.refactoring.util.QualifiedNameSearchResult;
113 import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
114 import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
115 import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager;
116 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
117 import org.eclipse.jdt.internal.corext.util.JdtFlags;
118 import org.eclipse.jdt.internal.corext.util.Messages;
119 import org.eclipse.jdt.internal.corext.util.SearchUtils;
120
121 import org.eclipse.jdt.ui.JavaElementLabels;
122
123 import org.eclipse.jdt.internal.ui.JavaPlugin;
124 import org.eclipse.jdt.internal.ui.refactoring.RefactoringSaveHelper;
125
126 public class RenameTypeProcessor extends JavaRenameProcessor implements ITextUpdating, IReferenceUpdating, IQualifiedNameUpdating, ISimilarDeclarationUpdating, IResourceMapper, IJavaElementMapper {
127
128     private static final String JavaDoc ATTRIBUTE_QUALIFIED= "qualified"; //$NON-NLS-1$
129
private static final String JavaDoc ATTRIBUTE_TEXTUAL_MATCHES= "textual"; //$NON-NLS-1$
130
private static final String JavaDoc ATTRIBUTE_PATTERNS= "patterns"; //$NON-NLS-1$
131
private static final String JavaDoc ATTRIBUTE_SIMILAR_DECLARATIONS= "similarDeclarations"; //$NON-NLS-1$
132
private static final String JavaDoc ATTRIBUTE_MATCHING_STRATEGY= "matchStrategy"; //$NON-NLS-1$
133

134     private static final GroupCategorySet CATEGORY_TYPE_RENAME= new GroupCategorySet(new GroupCategory("org.eclipse.jdt.internal.corext.refactoring.rename.renameType.type", RefactoringCoreMessages.RenameTypeProcessor_changeCategory_type, RefactoringCoreMessages.RenameTypeProcessor_changeCategory_type_description)); //$NON-NLS-1$
135
private static final GroupCategorySet CATEGORY_METHOD_RENAME= new GroupCategorySet(new GroupCategory("org.eclipse.jdt.internal.corext.refactoring.rename.renameType.method", RefactoringCoreMessages.RenameTypeProcessor_changeCategory_method, RefactoringCoreMessages.RenameTypeProcessor_changeCategory_method_description)); //$NON-NLS-1$
136
private static final GroupCategorySet CATEGORY_FIELD_RENAME= new GroupCategorySet(new GroupCategory("org.eclipse.jdt.internal.corext.refactoring.rename.renameType.field", RefactoringCoreMessages.RenameTypeProcessor_changeCategory_fields, RefactoringCoreMessages.RenameTypeProcessor_changeCategory_fields_description)); //$NON-NLS-1$
137
private static final GroupCategorySet CATEGORY_LOCAL_RENAME= new GroupCategorySet(new GroupCategory("org.eclipse.jdt.internal.corext.refactoring.rename.renameType.local", RefactoringCoreMessages.RenameTypeProcessor_changeCategory_local_variables, RefactoringCoreMessages.RenameTypeProcessor_changeCategory_local_variables_description)); //$NON-NLS-1$
138

139     private IType fType;
140     private SearchResultGroup[] fReferences;
141     private TextChangeManager fChangeManager;
142     private QualifiedNameSearchResult fQualifiedNameSearchResult;
143     
144     private boolean fUpdateReferences;
145     
146     private boolean fUpdateTextualMatches;
147
148     private boolean fUpdateQualifiedNames;
149     private String JavaDoc fFilePatterns;
150
151     public static final String JavaDoc IDENTIFIER= "org.eclipse.jdt.ui.renameTypeProcessor"; //$NON-NLS-1$
152

153     // --- similar elements
154

155     private boolean fUpdateSimilarElements;
156     private Map JavaDoc/* <IJavaElement, String> */fFinalSimilarElementToName= null;
157     private int fRenamingStrategy;
158
159     // Preloaded information for the UI.
160
private LinkedHashMap JavaDoc/* <IJavaElement, String> */fPreloadedElementToName= null;
161     private Map JavaDoc/* <IJavaElement, Boolean> */fPreloadedElementToSelection= null;
162     private LinkedHashMap JavaDoc/* <IJavaElement, String> */fPreloadedElementToNameDefault= null;
163
164     // Cache information to decide whether to
165
// re-update references and preload info
166
private String JavaDoc fCachedNewName= null;
167     private boolean fCachedRenameSimilarElements= false;
168     private int fCachedRenamingStrategy= -1;
169     private RefactoringStatus fCachedRefactoringStatus= null;
170
171     public static final class ParticipantDescriptorFilter implements IParticipantDescriptorFilter {
172
173         public boolean select(IConfigurationElement element, RefactoringStatus status) {
174             IConfigurationElement[] params= element.getChildren(PARAM);
175             for (int i= 0; i < params.length; i++) {
176                 IConfigurationElement param= params[i];
177                 if ("handlesSimilarDeclarations".equals(param.getAttribute(NAME)) && //$NON-NLS-1$
178
"false".equals(param.getAttribute(VALUE))) { //$NON-NLS-1$
179
return false;
180                 }
181             }
182             return true;
183         }
184     }
185
186     private class NoOverrideProgressMonitor extends SubProgressMonitor {
187         public NoOverrideProgressMonitor(IProgressMonitor monitor, int ticks) {
188             super(monitor, ticks, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL);
189         }
190         public void setTaskName(String JavaDoc name) {
191             // do nothing
192
}
193     }
194
195     /**
196      * Creates a new rename type processor.
197      * @param type the type, or <code>null</code> if invoked by scripting
198      */

199     public RenameTypeProcessor(IType type) {
200         fType= type;
201         if (type != null)
202             setNewElementName(type.getElementName());
203         fUpdateReferences= true; //default is yes
204
fUpdateTextualMatches= false;
205         fUpdateSimilarElements= false; // default is no
206
fRenamingStrategy= RenamingNameSuggestor.STRATEGY_EXACT;
207     }
208     
209     public IType getType() {
210         return fType;
211     }
212
213     public String JavaDoc getIdentifier() {
214         return IDENTIFIER;
215     }
216     
217     public boolean isApplicable() throws CoreException {
218         return RefactoringAvailabilityTester.isRenameAvailable(fType);
219     }
220      
221     public String JavaDoc getProcessorName() {
222         return RefactoringCoreMessages.RenameTypeRefactoring_name;
223     }
224     
225     protected String JavaDoc[] getAffectedProjectNatures() throws CoreException {
226         return JavaProcessors.computeAffectedNatures(fType);
227     }
228
229     public Object JavaDoc[] getElements() {
230         return new Object JavaDoc[] {fType};
231     }
232     
233     protected RenameModifications computeRenameModifications() {
234         RenameModifications result= new RenameModifications();
235         result.rename(fType, new RenameTypeArguments(getNewElementName(), getUpdateReferences(),
236             getUpdateSimilarDeclarations(), getSimilarElements()), createParticipantDescriptorFilter());
237         if (isPrimaryType()) {
238             ICompilationUnit cu= fType.getCompilationUnit();
239             String JavaDoc newCUName= getNewCompilationUnit().getElementName();
240             result.rename(cu, new RenameArguments(newCUName, getUpdateReferences()));
241         }
242         return result;
243     }
244         
245     /*
246      * Note: this is a handle-only method!
247      */

248     private boolean isPrimaryType() {
249         String JavaDoc cuName= fType.getCompilationUnit().getElementName();
250         String JavaDoc typeName= fType.getElementName();
251         return Checks.isTopLevel(fType) && JavaCore.removeJavaLikeExtension(cuName).equals(typeName);
252     }
253     
254     //---- IRenameProcessor ----------------------------------------------
255

256     public String JavaDoc getCurrentElementName(){
257         return fType.getElementName();
258     }
259     
260     public String JavaDoc getCurrentElementQualifier(){
261         return JavaModelUtil.getTypeContainerName(fType);
262     }
263     
264     public RefactoringStatus checkNewElementName(String JavaDoc newName){
265         Assert.isNotNull(newName, "new name"); //$NON-NLS-1$
266
RefactoringStatus result= Checks.checkTypeName(newName);
267         if (Checks.isAlreadyNamed(fType, newName))
268             result.addFatalError(RefactoringCoreMessages.RenameTypeRefactoring_choose_another_name);
269         return result;
270     }
271     
272     public Object JavaDoc getNewElement() {
273         if (Checks.isTopLevel(fType)) {
274             return getNewCompilationUnit().getType(getNewElementName());
275         } else {
276             return fType.getDeclaringType().getType(getNewElementName());
277         }
278     }
279
280     private ICompilationUnit getNewCompilationUnit() {
281         ICompilationUnit cu= fType.getCompilationUnit();
282         if (isPrimaryType()) {
283             IPackageFragment parent= fType.getPackageFragment();
284             String JavaDoc renamedCUName= JavaModelUtil.getRenamedCUName(cu, getNewElementName());
285             return parent.getCompilationUnit(renamedCUName);
286         } else {
287             return cu;
288         }
289     }
290
291     //---- JavaRenameProcessor -------------------------------------------
292

293     protected RenameArguments createRenameArguments() {
294         return new RenameTypeArguments(getNewElementName(), getUpdateReferences(),
295             getUpdateSimilarDeclarations(), getSimilarElements());
296     }
297     
298     protected IParticipantDescriptorFilter createParticipantDescriptorFilter() {
299         if (!getUpdateSimilarDeclarations())
300             return null;
301         return new ParticipantDescriptorFilter();
302     }
303     
304     protected IFile[] getChangedFiles() throws CoreException {
305         List JavaDoc result= new ArrayList JavaDoc();
306         result.addAll(Arrays.asList(ResourceUtil.getFiles(fChangeManager.getAllCompilationUnits())));
307         if (fQualifiedNameSearchResult != null)
308             result.addAll(Arrays.asList(fQualifiedNameSearchResult.getAllFiles()));
309         if (willRenameCU())
310             result.add(ResourceUtil.getFile(fType.getCompilationUnit()));
311         return (IFile[]) result.toArray(new IFile[result.size()]);
312     }
313     
314     public int getSaveMode() {
315         return RefactoringSaveHelper.SAVE_NON_JAVA_UPDATES;
316     }
317     
318     //---- ITextUpdating -------------------------------------------------
319

320     public boolean canEnableTextUpdating() {
321         return true;
322     }
323     
324     public boolean getUpdateTextualMatches() {
325         return fUpdateTextualMatches;
326     }
327     public void setUpdateTextualMatches(boolean update) {
328         fUpdateTextualMatches= update;
329     }
330
331     //---- IReferenceUpdating --------------------------------------
332

333     public void setUpdateReferences(boolean update){
334         fUpdateReferences= update;
335     }
336     
337     public boolean canEnableUpdateReferences(){
338         return true;
339     }
340     
341     public boolean getUpdateReferences(){
342         return fUpdateReferences;
343     }
344
345     //---- IQualifiedNameUpdating ----------------------------------
346

347     public boolean canEnableQualifiedNameUpdating() {
348         return !fType.getPackageFragment().isDefaultPackage() && !(fType.getParent() instanceof IType);
349     }
350     
351     public boolean getUpdateQualifiedNames() {
352         return fUpdateQualifiedNames;
353     }
354     
355     public void setUpdateQualifiedNames(boolean update) {
356         fUpdateQualifiedNames= update;
357     }
358     
359     public String JavaDoc getFilePatterns() {
360         return fFilePatterns;
361     }
362     
363     public void setFilePatterns(String JavaDoc patterns) {
364         Assert.isNotNull(patterns);
365         fFilePatterns= patterns;
366     }
367     
368     // ---- ISimilarDeclarationUpdating
369

370     public boolean canEnableSimilarDeclarationUpdating() {
371         
372         IProduct product= Platform.getProduct();
373         if (product != null) {
374             String JavaDoc property= product.getProperty("org.eclipse.jdt.ui.refactoring.handlesSimilarDeclarations"); //$NON-NLS-1$
375
if ("false".equalsIgnoreCase(property)) //$NON-NLS-1$
376
return false;
377         }
378
379         return true;
380     }
381
382     public void setUpdateSimilarDeclarations(boolean update) {
383         fUpdateSimilarElements= update;
384     }
385
386     public boolean getUpdateSimilarDeclarations() {
387         return fUpdateSimilarElements;
388     }
389
390     public int getMatchStrategy() {
391         return fRenamingStrategy;
392
393     }
394
395     public void setMatchStrategy(int selectedStrategy) {
396         fRenamingStrategy= selectedStrategy;
397     }
398
399     /**
400      * @return the similar elements of the type, i.e. IFields, IMethods, and
401      * ILocalVariables. Returns <code>null</code> iff similar declaration updating
402      * is not requested.
403      */

404     public IJavaElement[] getSimilarElements() {
405         if (fFinalSimilarElementToName == null)
406             return null;
407         Set JavaDoc keys= fFinalSimilarElementToName.keySet();
408         return (IJavaElement[])keys.toArray(new IJavaElement[keys.size()]);
409     }
410
411     /**
412      * {@inheritDoc}
413      */

414     public IResource getRefactoredResource(IResource element) {
415         if (element instanceof IFile) {
416             if (Checks.isTopLevel(fType) && element.equals(fType.getResource()))
417                 return getNewCompilationUnit().getResource();
418         }
419         return element;
420     }
421     
422     /**
423      * {@inheritDoc}
424      */

425     public IJavaElement getRefactoredJavaElement(IJavaElement element) {
426         if (element instanceof ICompilationUnit) {
427             if (Checks.isTopLevel(fType) && element.equals(fType.getCompilationUnit()))
428                 return getNewCompilationUnit();
429         } else if (element instanceof IMember) {
430             final IType newType= (IType) getNewElement();
431             final RefactoringHandleTransplanter transplanter= new RefactoringHandleTransplanter(fType, newType, fFinalSimilarElementToName);
432             return transplanter.transplantHandle((IMember) element);
433         }
434         return element;
435     }
436
437     public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException {
438         IType primary= (IType) fType.getPrimaryElement();
439         if (primary == null || !primary.exists()) {
440             String JavaDoc message= Messages.format(RefactoringCoreMessages.RenameTypeRefactoring_does_not_exist, new String JavaDoc[] { JavaModelUtil.getFullyQualifiedName(fType), fType.getCompilationUnit().getElementName()});
441             return RefactoringStatus.createFatalErrorStatus(message);
442         }
443         fType= primary;
444         return Checks.checkIfCuBroken(fType);
445     }
446
447     protected RefactoringStatus doCheckFinalConditions(IProgressMonitor pm, CheckConditionsContext context) throws CoreException {
448         Assert.isNotNull(fType, "type"); //$NON-NLS-1$
449
Assert.isNotNull(getNewElementName(), "newName"); //$NON-NLS-1$
450
RefactoringStatus result= new RefactoringStatus();
451         
452         int referenceSearchTicks= fUpdateReferences || fUpdateSimilarElements ? 15 : 0;
453         int affectedCusTicks= fUpdateReferences || fUpdateSimilarElements ? 10 : 1;
454         int similarElementTicks= fUpdateSimilarElements ? 85 : 0;
455         int createChangeTicks = 5;
456         int qualifiedNamesTicks= fUpdateQualifiedNames ? 50 : 0;
457         
458         try{
459             pm.beginTask("", 12 + referenceSearchTicks + affectedCusTicks + similarElementTicks + createChangeTicks + qualifiedNamesTicks); //$NON-NLS-1$
460
pm.setTaskName(RefactoringCoreMessages.RenameTypeRefactoring_checking);
461
462             fChangeManager= new TextChangeManager(true);
463             
464             result.merge(checkNewElementName(getNewElementName()));
465             if (result.hasFatalError())
466                 return result;
467             result.merge(Checks.checkIfCuBroken(fType));
468             if (result.hasFatalError())
469                 return result;
470             pm.worked(1);
471         
472             result.merge(checkTypesInCompilationUnit());
473             pm.worked(1);
474         
475             result.merge(checkForMethodsWithConstructorNames());
476             pm.worked(1);
477         
478             result.merge(checkImportedTypes());
479             pm.worked(1);
480         
481             if (Checks.isTopLevel(fType) && (JdtFlags.isPublic(fType)))
482                 result.merge(Checks.checkCompilationUnitNewName(fType.getCompilationUnit(), getNewElementName()));
483             pm.worked(1);
484             
485             if (isPrimaryType())
486                 result.merge(checkNewPathValidity());
487             pm.worked(1);
488             
489             result.merge(checkEnclosingTypes());
490             pm.worked(1);
491             
492             result.merge(checkEnclosedTypes());
493             pm.worked(1);
494             
495             result.merge(checkTypesInPackage());
496             pm.worked(1);
497             
498             result.merge(checkTypesImportedInCu());
499             pm.worked(1);
500         
501             result.merge(Checks.checkForMainAndNativeMethods(fType));
502             pm.worked(1);
503         
504             // before doing any expensive analysis
505
if (result.hasFatalError())
506                 return result;
507                             
508             result.merge(analyseEnclosedTypes());
509             pm.worked(1);
510             // before doing _the really_ expensive analysis
511
if (result.hasFatalError())
512                 return result;
513             
514             // Load references, including similarly named elements
515
if (fUpdateReferences || fUpdateSimilarElements) {
516                 pm.setTaskName(RefactoringCoreMessages.RenameTypeRefactoring_searching);
517                 result.merge(initializeReferences(new SubProgressMonitor(pm, referenceSearchTicks)));
518             } else {
519                 fReferences= new SearchResultGroup[0];
520             }
521     
522             pm.setTaskName(RefactoringCoreMessages.RenameTypeRefactoring_checking);
523             if (pm.isCanceled())
524                 throw new OperationCanceledException();
525             
526             if (fUpdateReferences || fUpdateSimilarElements) {
527                 result.merge(analyzeAffectedCompilationUnits(new SubProgressMonitor(pm, affectedCusTicks)));
528             } else {
529                 Checks.checkCompileErrorsInAffectedFile(result, fType.getResource());
530                 pm.worked(affectedCusTicks);
531             }
532             
533             if (result.hasFatalError())
534                 return result;
535             
536             if (fUpdateSimilarElements) {
537                 result.merge(initializeSimilarElementsRenameProcessors(new SubProgressMonitor(pm, similarElementTicks), context));
538                 if (result.hasFatalError())
539                     return result;
540             }
541
542             createChanges(new SubProgressMonitor(pm, createChangeTicks));
543     
544             if (fUpdateQualifiedNames)
545                 computeQualifiedNameMatches(new SubProgressMonitor(pm, qualifiedNamesTicks));
546     
547             return result;
548         } finally {
549             pm.done();
550         }
551     }
552     
553     /**
554      * Initializes the references to the type and the similarly named elements. This
555      * method creates both the fReferences and the fPreloadedElementToName
556      * fields.
557      *
558      * May be called from the UI.
559      * @param monitor
560      * @return initialization status
561      * @throws JavaModelException some fundamental error with the underlying model
562      * @throws OperationCanceledException if user canceled the task
563      *
564      */

565     public RefactoringStatus initializeReferences(IProgressMonitor monitor) throws JavaModelException, OperationCanceledException {
566
567         Assert.isNotNull(fType);
568         Assert.isNotNull(getNewElementName());
569
570         // Do not search again if the preconditions have not changed.
571
// Search depends on the type, the new name, the similarly named elements, and
572
// the strategy
573

574         if (fReferences != null && (getNewElementName().equals(fCachedNewName)) && (fCachedRenameSimilarElements == getUpdateSimilarDeclarations()) && (fCachedRenamingStrategy == fRenamingStrategy))
575             return fCachedRefactoringStatus;
576
577         fCachedNewName= getNewElementName();
578         fCachedRenameSimilarElements= fUpdateSimilarElements;
579         fCachedRenamingStrategy= fRenamingStrategy;
580         fCachedRefactoringStatus= new RefactoringStatus();
581
582         
583         try {
584             SearchPattern pattern= SearchPattern.createPattern(fType, IJavaSearchConstants.REFERENCES, SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE);
585             fReferences= RefactoringSearchEngine.search(
586                     pattern,
587                     RefactoringScopeFactory.create(fType),
588                     new TypeOccurrenceCollector(fType),
589                     monitor,
590                     fCachedRefactoringStatus);
591             fReferences= Checks.excludeCompilationUnits(fReferences, fCachedRefactoringStatus);
592
593             fPreloadedElementToName= new LinkedHashMap JavaDoc();
594             fPreloadedElementToSelection= new HashMap JavaDoc();
595
596             final String JavaDoc unQualifiedTypeName= fType.getElementName();
597
598             monitor.beginTask("", fReferences.length); //$NON-NLS-1$
599

600             if (getUpdateSimilarDeclarations()) {
601
602                 RenamingNameSuggestor sugg= new RenamingNameSuggestor(fRenamingStrategy);
603
604                 for (int i= 0; i < fReferences.length; i++) {
605                     final ICompilationUnit cu= fReferences[i].getCompilationUnit();
606                     if (cu == null)
607                         continue;
608
609                     final SearchMatch[] results= fReferences[i].getSearchResults();
610
611                     for (int j= 0; j < results.length; j++) {
612
613                         if (! (results[j] instanceof TypeReferenceMatch))
614                             continue;
615
616                         final TypeReferenceMatch match= (TypeReferenceMatch) results[j];
617                         final List JavaDoc matches= new ArrayList JavaDoc();
618
619                         if (match.getLocalElement() != null)
620                             matches.add(match.getLocalElement());
621                         else
622                             matches.add(match.getElement());
623
624                         final IJavaElement[] others= match.getOtherElements();
625                         if (others != null)
626                             matches.addAll(Arrays.asList(others));
627
628                         for (Iterator JavaDoc iter= matches.iterator(); iter.hasNext();) {
629                             final IJavaElement element= (IJavaElement) iter.next();
630
631                             if (! (element instanceof IMethod) && ! (element instanceof IField) && ! (element instanceof ILocalVariable))
632                                 continue;
633                             
634                             if (!isInDeclaredType(match.getOffset(), element))
635                                 continue;
636
637                             if (element instanceof IField) {
638                                 final IField currentField= (IField) element;
639                                 final String JavaDoc newFieldName= sugg.suggestNewFieldName(currentField.getJavaProject(), currentField.getElementName(), Flags.isStatic(currentField.getFlags()),
640                                         unQualifiedTypeName, getNewElementName());
641
642                                 if (newFieldName != null)
643                                     fPreloadedElementToName.put(currentField, newFieldName);
644                             }
645
646                             if (element instanceof IMethod) {
647                                 final IMethod currentMethod= (IMethod) element;
648                                 addMethodRename(unQualifiedTypeName, sugg, currentMethod);
649                             }
650
651                             if (element instanceof ILocalVariable) {
652                                 final ILocalVariable currentLocal= (ILocalVariable) element;
653                                 final boolean isParameter;
654                                 
655                                 if (JavaModelUtil.isParameter(currentLocal)) {
656                                     addMethodRename(unQualifiedTypeName, sugg, (IMethod) currentLocal.getParent());
657                                     isParameter= true;
658                                 } else
659                                     isParameter= false;
660
661                                 final String JavaDoc newLocalName= sugg
662                                         .suggestNewLocalName(currentLocal.getJavaProject(), currentLocal.getElementName(), isParameter, unQualifiedTypeName, getNewElementName());
663
664                                 if (newLocalName != null)
665                                     fPreloadedElementToName.put(currentLocal, newLocalName);
666                             }
667                         }
668                     }
669                     if (monitor.isCanceled())
670                         throw new OperationCanceledException();
671                 }
672             }
673
674             for (Iterator JavaDoc iter= fPreloadedElementToName.keySet().iterator(); iter.hasNext();) {
675                 IJavaElement element= (IJavaElement) iter.next();
676                 fPreloadedElementToSelection.put(element, Boolean.TRUE);
677             }
678             fPreloadedElementToNameDefault= (LinkedHashMap JavaDoc) fPreloadedElementToName.clone();
679
680         } catch (OperationCanceledException e) {
681             fReferences= null;
682             fPreloadedElementToName= null;
683             throw new OperationCanceledException();
684         }
685         return fCachedRefactoringStatus;
686     }
687
688     /**
689      * @param matchOffset
690      * @param parentElement
691      * @return true iff the given search match offset (must be a match of a type
692      * reference) lies before the element name of its enclosing java element,
693      * false if not. In other words: If this method returns true, the match is
694      * the declared type (or return type) of the enclosing element.
695      * @throws JavaModelException
696      *
697      */

698     private boolean isInDeclaredType(int matchOffset, IJavaElement parentElement) throws JavaModelException {
699         if (parentElement != null) {
700             int enclosingNameOffset= 0;
701             if (parentElement instanceof IMethod || parentElement instanceof IField)
702                 enclosingNameOffset= ((IMember) parentElement).getNameRange().getOffset();
703             else if (parentElement instanceof ILocalVariable)
704                 enclosingNameOffset= ((ILocalVariable) parentElement).getNameRange().getOffset();
705
706             return (matchOffset < enclosingNameOffset);
707         }
708         return false;
709     }
710     
711     private void addMethodRename(final String JavaDoc unQualifiedTypeName, RenamingNameSuggestor sugg, final IMethod currentMethod) throws JavaModelException {
712         if (!currentMethod.isConstructor()) {
713             final String JavaDoc newMethodName= sugg.suggestNewMethodName(currentMethod.getElementName(), unQualifiedTypeName, getNewElementName());
714
715             if (newMethodName != null)
716                 fPreloadedElementToName.put(currentMethod, newMethodName);
717         }
718     }
719
720     private RefactoringStatus checkNewPathValidity() {
721         IContainer c= fType.getCompilationUnit().getResource().getParent();
722         
723         String JavaDoc notRename= RefactoringCoreMessages.RenameTypeRefactoring_will_not_rename;
724         IStatus status= c.getWorkspace().validateName(getNewElementName(), IResource.FILE);
725         if (status.getSeverity() == IStatus.ERROR)
726             return RefactoringStatus.createWarningStatus(status.getMessage() + ". " + notRename); //$NON-NLS-1$
727

728         status= c.getWorkspace().validatePath(createNewPath(getNewElementName()), IResource.FILE);
729         if (status.getSeverity() == IStatus.ERROR)
730             return RefactoringStatus.createWarningStatus(status.getMessage() + ". " + notRename); //$NON-NLS-1$
731

732         return new RefactoringStatus();
733     }
734     
735     private String JavaDoc createNewPath(String JavaDoc newName) {
736         return fType.getCompilationUnit().getResource().getFullPath().removeLastSegments(1).append(newName).toString();
737     }
738     
739     private RefactoringStatus checkTypesImportedInCu() throws CoreException {
740         IImportDeclaration imp= getImportedType(fType.getCompilationUnit(), getNewElementName());
741         
742         if (imp == null)
743             return null;
744             
745         String JavaDoc msg= Messages.format(RefactoringCoreMessages.RenameTypeRefactoring_imported,
746                                             new Object JavaDoc[]{getNewElementName(), fType.getCompilationUnit().getResource().getFullPath()});
747         IJavaElement grandParent= imp.getParent().getParent();
748         if (grandParent instanceof ICompilationUnit)
749             return RefactoringStatus.createErrorStatus(msg, JavaStatusContext.create(imp));
750
751         return null;
752     }
753     
754     private RefactoringStatus checkTypesInPackage() throws CoreException {
755         IType type= Checks.findTypeInPackage(fType.getPackageFragment(), getNewElementName());
756         if (type == null || ! type.exists())
757             return null;
758         String JavaDoc msg= Messages.format(RefactoringCoreMessages.RenameTypeRefactoring_exists,
759                                                                     new String JavaDoc[]{getNewElementName(), fType.getPackageFragment().getElementName()});
760         return RefactoringStatus.createErrorStatus(msg, JavaStatusContext.create(type));
761     }
762     
763     private RefactoringStatus checkEnclosedTypes() throws CoreException {
764         IType enclosedType= findEnclosedType(fType, getNewElementName());
765         if (enclosedType == null)
766             return null;
767         String JavaDoc msg= Messages.format(RefactoringCoreMessages.RenameTypeRefactoring_encloses,
768                                                                         new String JavaDoc[]{JavaModelUtil.getFullyQualifiedName(fType), getNewElementName()});
769         return RefactoringStatus.createErrorStatus(msg, JavaStatusContext.create(enclosedType));
770     }
771     
772     private RefactoringStatus checkEnclosingTypes() {
773         IType enclosingType= findEnclosingType(fType, getNewElementName());
774         if (enclosingType == null)
775             return null;
776             
777         String JavaDoc msg= Messages.format(RefactoringCoreMessages.RenameTypeRefactoring_enclosed,
778                                 new String JavaDoc[]{JavaModelUtil.getFullyQualifiedName(fType), getNewElementName()});
779         return RefactoringStatus.createErrorStatus(msg, JavaStatusContext.create(enclosingType));
780     }
781     
782     private static IType findEnclosedType(IType type, String JavaDoc newName) throws CoreException {
783         IType[] enclosedTypes= type.getTypes();
784         for (int i= 0; i < enclosedTypes.length; i++){
785             if (newName.equals(enclosedTypes[i].getElementName()) || findEnclosedType(enclosedTypes[i], newName) != null)
786                 return enclosedTypes[i];
787         }
788         return null;
789     }
790         
791     private static IType findEnclosingType(IType type, String JavaDoc newName) {
792         IType enclosing= type.getDeclaringType();
793         while (enclosing != null){
794             if (newName.equals(enclosing.getElementName()))
795                 return enclosing;
796             else
797                 enclosing= enclosing.getDeclaringType();
798         }
799         return null;
800     }
801     
802     private static IImportDeclaration getImportedType(ICompilationUnit cu, String JavaDoc typeName) throws CoreException {
803         IImportDeclaration[] imports= cu.getImports();
804         String JavaDoc dotTypeName= "." + typeName; //$NON-NLS-1$
805
for (int i= 0; i < imports.length; i++){
806             if (imports[i].getElementName().endsWith(dotTypeName))
807                 return imports[i];
808         }
809         return null;
810     }
811     
812     private RefactoringStatus checkForMethodsWithConstructorNames() throws CoreException{
813         IMethod[] methods= fType.getMethods();
814         for (int i= 0; i < methods.length; i++){
815             if (methods[i].isConstructor())
816                 continue;
817             RefactoringStatus check= Checks.checkIfConstructorName(methods[i], methods[i].getElementName(), getNewElementName());
818             if (check != null)
819                 return check;
820         }
821         return null;
822     }
823     
824     private RefactoringStatus checkImportedTypes() throws CoreException {
825         RefactoringStatus result= new RefactoringStatus();
826         IImportDeclaration[] imports= fType.getCompilationUnit().getImports();
827         for (int i= 0; i < imports.length; i++)
828             analyzeImportDeclaration(imports[i], result);
829         return result;
830     }
831     
832     private RefactoringStatus checkTypesInCompilationUnit() {
833         RefactoringStatus result= new RefactoringStatus();
834         if (! Checks.isTopLevel(fType)){ //the other case checked in checkTypesInPackage
835
IType siblingType= fType.getDeclaringType().getType(getNewElementName());
836             if (siblingType.exists()){
837                 String JavaDoc msg= Messages.format(RefactoringCoreMessages.RenameTypeRefactoring_member_type_exists,
838                                                                         new String JavaDoc[]{getNewElementName(), JavaModelUtil.getFullyQualifiedName(fType.getDeclaringType())});
839                 result.addError(msg, JavaStatusContext.create(siblingType));
840             }
841         }
842         return result;
843     }
844     
845     private RefactoringStatus analyseEnclosedTypes() throws CoreException {
846         final ISourceRange typeRange= fType.getSourceRange();
847         final RefactoringStatus result= new RefactoringStatus();
848         CompilationUnit cuNode= new RefactoringASTParser(AST.JLS3).parse(fType.getCompilationUnit(), false);
849         cuNode.accept(new ASTVisitor(){
850             
851             public boolean visit(TypeDeclaration node){ // enums and annotations can't be local
852
if (node.getStartPosition() <= typeRange.getOffset())
853                     return true;
854                 if (node.getStartPosition() > typeRange.getOffset() + typeRange.getLength())
855                     return true;
856         
857                 if (getNewElementName().equals(node.getName().getIdentifier())){
858                     RefactoringStatusContext context= JavaStatusContext.create(fType.getCompilationUnit(), node);
859                     String JavaDoc msg= null;
860                     if (node.isLocalTypeDeclaration()){
861                         msg= Messages.format(RefactoringCoreMessages.RenameTypeRefactoring_local_type,
862                                     new String JavaDoc[]{JavaElementUtil.createSignature(fType), getNewElementName()});
863                     }
864                     else if (node.isMemberTypeDeclaration()){
865                         msg= Messages.format(RefactoringCoreMessages.RenameTypeRefactoring_member_type,
866                                 new String JavaDoc[]{JavaElementUtil.createSignature(fType), getNewElementName()});
867                     }
868                     if (msg != null)
869                         result.addError(msg, context);
870                 }
871         
872                 MethodDeclaration[] methods= node.getMethods();
873                 for (int i= 0; i < methods.length; i++) {
874                     if (Modifier.isNative(methods[i].getModifiers())){
875                         RefactoringStatusContext context= JavaStatusContext.create(fType.getCompilationUnit(), methods[i]);
876                         String JavaDoc msg= Messages.format(RefactoringCoreMessages.RenameTypeRefactoring_enclosed_type_native, node.getName().getIdentifier());
877                         result.addWarning(msg, context);
878                     }
879                 }
880                 return true;
881             }
882         });
883         return result;
884     }
885     
886     private static ICompilationUnit getCompilationUnit(IImportDeclaration imp) {
887         return (ICompilationUnit)imp.getParent().getParent();
888     }
889     
890     private void analyzeImportedTypes(IType[] types, RefactoringStatus result, IImportDeclaration imp) throws CoreException {
891         for (int i= 0; i < types.length; i++) {
892             //could this be a problem (same package imports)?
893
if (JdtFlags.isPublic(types[i]) && types[i].getElementName().equals(getNewElementName())){
894                 String JavaDoc msg= Messages.format(RefactoringCoreMessages.RenameTypeRefactoring_name_conflict1,
895                                                                             new Object JavaDoc[]{JavaModelUtil.getFullyQualifiedName(types[i]), getFullPath(getCompilationUnit(imp))});
896                 result.addError(msg, JavaStatusContext.create(imp));
897             }
898         }
899     }
900     
901     private static IJavaElement convertFromImportDeclaration(IImportDeclaration declaration) throws CoreException {
902             if (declaration.isOnDemand()){
903                 String JavaDoc packageName= declaration.getElementName().substring(0, declaration.getElementName().length() - 2);
904                 return JavaModelUtil.findTypeContainer(declaration.getJavaProject(), packageName);
905             } else
906                 return JavaModelUtil.findTypeContainer(declaration.getJavaProject(), declaration.getElementName());
907     }
908
909     private void analyzeImportDeclaration(IImportDeclaration imp, RefactoringStatus result) throws CoreException{
910         if (!imp.isOnDemand())
911             return; //analyzed earlier
912

913         IJavaElement imported= convertFromImportDeclaration(imp);
914         if (imported == null)
915             return;
916             
917         if (imported instanceof IPackageFragment){
918             ICompilationUnit[] cus= ((IPackageFragment)imported).getCompilationUnits();
919             for (int i= 0; i < cus.length; i++) {
920                 analyzeImportedTypes(cus[i].getTypes(), result, imp);
921             }
922         } else {
923             //cast safe: see JavaModelUtility.convertFromImportDeclaration
924
analyzeImportedTypes(((IType)imported).getTypes(), result, imp);
925         }
926     }
927     
928     /*
929      * Analyzes all compilation units in which type is referenced
930      */

931     private RefactoringStatus analyzeAffectedCompilationUnits(IProgressMonitor pm) throws CoreException {
932         RefactoringStatus result= new RefactoringStatus();
933             
934         result.merge(Checks.checkCompileErrorsInAffectedFiles(fReferences, fType.getResource()));
935         
936         pm.beginTask("", fReferences.length); //$NON-NLS-1$
937
result.merge(checkConflictingTypes(pm));
938         return result;
939     }
940     
941     private RefactoringStatus checkConflictingTypes(IProgressMonitor pm) throws CoreException {
942         RefactoringStatus result= new RefactoringStatus();
943         IJavaSearchScope scope= RefactoringScopeFactory.create(fType);
944         SearchPattern pattern= SearchPattern.createPattern(getNewElementName(),
945                 IJavaSearchConstants.TYPE, IJavaSearchConstants.ALL_OCCURRENCES, SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE);
946         ICompilationUnit[] cusWithReferencesToConflictingTypes= RefactoringSearchEngine.findAffectedCompilationUnits(pattern, scope, pm, result);
947         if (cusWithReferencesToConflictingTypes.length == 0)
948             return result;
949         ICompilationUnit[] cusWithReferencesToRenamedType= getCus(fReferences);
950
951         ICompilationUnit[] intersection= isIntersectionEmpty(cusWithReferencesToRenamedType, cusWithReferencesToConflictingTypes);
952         if (intersection.length == 0)
953             return result;
954         
955         for (int i= 0; i < intersection.length; i++) {
956             RefactoringStatusContext context= JavaStatusContext.create(intersection[i]);
957             String JavaDoc message= Messages.format(RefactoringCoreMessages.RenameTypeRefactoring_another_type,
958                 new String JavaDoc[]{getNewElementName(), intersection[i].getElementName()});
959             result.addError(message, context);
960         }
961         return result;
962     }
963     
964     private static ICompilationUnit[] isIntersectionEmpty(ICompilationUnit[] a1, ICompilationUnit[] a2){
965         Set JavaDoc set1= new HashSet JavaDoc(Arrays.asList(a1));
966         Set JavaDoc set2= new HashSet JavaDoc(Arrays.asList(a2));
967         set1.retainAll(set2);
968         return (ICompilationUnit[]) set1.toArray(new ICompilationUnit[set1.size()]);
969     }
970     
971     private static ICompilationUnit[] getCus(SearchResultGroup[] searchResultGroups){
972         List JavaDoc cus= new ArrayList JavaDoc(searchResultGroups.length);
973         for (int i= 0; i < searchResultGroups.length; i++) {
974             ICompilationUnit cu= searchResultGroups[i].getCompilationUnit();
975             if (cu != null)
976                 cus.add(cu);
977         }
978         return (ICompilationUnit[]) cus.toArray(new ICompilationUnit[cus.size()]);
979     }
980     
981     private static String JavaDoc getFullPath(ICompilationUnit cu) {
982         Assert.isTrue(cu.exists());
983         return cu.getResource().getFullPath().toString();
984     }
985
986     public Change createChange(IProgressMonitor monitor) throws CoreException {
987         try {
988             monitor.beginTask(RefactoringCoreMessages.RenameTypeRefactoring_creating_change, 4);
989             String JavaDoc project= null;
990             IJavaProject javaProject= fType.getJavaProject();
991             if (javaProject != null)
992                 project= javaProject.getElementName();
993             int flags= JavaRefactoringDescriptor.JAR_MIGRATION | JavaRefactoringDescriptor.JAR_REFACTORING | RefactoringDescriptor.STRUCTURAL_CHANGE;
994             try {
995                 if (!Flags.isPrivate(fType.getFlags()))
996                     flags|= RefactoringDescriptor.MULTI_CHANGE;
997                 if (fType.isAnonymous() || fType.isLocal())
998                     flags|= JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT;
999             } catch (JavaModelException exception) {
1000                JavaPlugin.log(exception);
1001            }
1002            final String JavaDoc description= Messages.format(RefactoringCoreMessages.RenameTypeProcessor_descriptor_description_short, fType.getElementName());
1003            final String JavaDoc header= Messages.format(RefactoringCoreMessages.RenameTypeProcessor_descriptor_description, new String JavaDoc[] { JavaElementLabels.getElementLabel(fType, JavaElementLabels.ALL_FULLY_QUALIFIED), getNewElementName()});
1004            final String JavaDoc comment= new JDTRefactoringDescriptorComment(project, this, header).asString();
1005            final RenameJavaElementDescriptor descriptor= new RenameJavaElementDescriptor(IJavaRefactorings.RENAME_TYPE);
1006            descriptor.setProject(project);
1007            descriptor.setDescription(description);
1008            descriptor.setComment(comment);
1009            descriptor.setFlags(flags);
1010            descriptor.setJavaElement(fType);
1011            descriptor.setNewName(getNewElementName());
1012            descriptor.setUpdateQualifiedNames(fUpdateQualifiedNames);
1013            descriptor.setUpdateTextualOccurrences(fUpdateTextualMatches);
1014            descriptor.setUpdateReferences(fUpdateReferences);
1015            if (fUpdateQualifiedNames && fFilePatterns != null && !"".equals(fFilePatterns)) //$NON-NLS-1$
1016
descriptor.setFileNamePatterns(fFilePatterns);
1017            descriptor.setUpdateSimilarDeclarations(fUpdateSimilarElements);
1018            descriptor.setMatchStrategy(fRenamingStrategy);
1019            final DynamicValidationRefactoringChange result= new DynamicValidationRefactoringChange(descriptor, RefactoringCoreMessages.RenameTypeProcessor_change_name);
1020            
1021            if (fChangeManager.containsChangesIn(fType.getCompilationUnit())) {
1022                TextChange textChange= fChangeManager.get(fType.getCompilationUnit());
1023                if (textChange instanceof TextFileChange) {
1024                    ((TextFileChange) textChange).setSaveMode(TextFileChange.FORCE_SAVE);
1025                }
1026            }
1027            result.addAll(fChangeManager.getAllChanges());
1028            if (willRenameCU()) {
1029                IResource resource= fType.getCompilationUnit().getResource();
1030                if (resource != null && resource.isLinked()) {
1031                    String JavaDoc ext= resource.getFileExtension();
1032                    String JavaDoc renamedResourceName;
1033                    if (ext == null)
1034                        renamedResourceName= getNewElementName();
1035                    else
1036                        renamedResourceName= getNewElementName() + '.' + ext;
1037                    result.add(new RenameResourceChange(null, fType.getCompilationUnit().getResource(), renamedResourceName, comment));
1038                } else {
1039                    String JavaDoc renamedCUName= JavaModelUtil.getRenamedCUName(fType.getCompilationUnit(), getNewElementName());
1040                    result.add(new RenameCompilationUnitChange(fType.getCompilationUnit(), renamedCUName));
1041                }
1042            }
1043            monitor.worked(1);
1044            return result;
1045        } finally {
1046            fChangeManager= null;
1047        }
1048    }
1049    
1050    public Change postCreateChange(Change[] participantChanges, IProgressMonitor pm) throws CoreException {
1051        if (fQualifiedNameSearchResult != null) {
1052            try {
1053                return fQualifiedNameSearchResult.getSingleChange(Changes.getModifiedFiles(participantChanges));
1054            } finally {
1055                fQualifiedNameSearchResult= null;
1056            }
1057        } else {
1058            return null;
1059        }
1060    }
1061    
1062    private boolean willRenameCU() throws CoreException{
1063        String JavaDoc name = JavaCore.removeJavaLikeExtension(fType.getCompilationUnit().getElementName());
1064        if (! (Checks.isTopLevel(fType) && name.equals(fType.getElementName())))
1065            return false;
1066        if (! checkNewPathValidity().isOK())
1067            return false;
1068        if (! Checks.checkCompilationUnitNewName(fType.getCompilationUnit(), getNewElementName()).isOK())
1069            return false;
1070        return true;
1071    }
1072    
1073    private void createChanges(IProgressMonitor pm) throws CoreException {
1074        try{
1075            pm.beginTask("", 12); //$NON-NLS-1$
1076
pm.setTaskName(RefactoringCoreMessages.RenameTypeProcessor_creating_changes);
1077            
1078            if (fUpdateReferences)
1079                addReferenceUpdates(fChangeManager, new SubProgressMonitor(pm, 3));
1080
1081            // Similar names updates have already been added.
1082

1083            pm.worked(1);
1084            
1085            IResource resource= fType.getCompilationUnit().getResource();
1086            // if we have a linked resource then we don't use CU renaming
1087
// directly. So we have to update the code by ourselves.
1088
if ((resource != null && resource.isLinked()) || !willRenameCU()) {
1089                addTypeDeclarationUpdate(fChangeManager);
1090                pm.worked(1);
1091                
1092                addConstructorRenames(fChangeManager);
1093                pm.worked(1);
1094            } else {
1095                pm.worked(2);
1096            }
1097            
1098            if (fUpdateTextualMatches) {
1099                pm.subTask(RefactoringCoreMessages.RenameTypeRefactoring_searching_text);
1100                TextMatchUpdater.perform(new SubProgressMonitor(pm, 1), RefactoringScopeFactory.create(fType), this, fChangeManager, fReferences);
1101                if (fUpdateSimilarElements)
1102                    addSimilarElementsTextualUpdates(fChangeManager, new SubProgressMonitor(pm, 3));
1103            }
1104            
1105        } finally{
1106            pm.done();
1107        }
1108    }
1109    
1110    private void addTypeDeclarationUpdate(TextChangeManager manager) throws CoreException {
1111        String JavaDoc name= RefactoringCoreMessages.RenameTypeRefactoring_update;
1112        int typeNameLength= fType.getElementName().length();
1113        ICompilationUnit cu= fType.getCompilationUnit();
1114        TextChangeCompatibility.addTextEdit(manager.get(cu), name, new ReplaceEdit(fType.getNameRange().getOffset(), typeNameLength, getNewElementName()));
1115    }
1116    
1117    private void addConstructorRenames(TextChangeManager manager) throws CoreException {
1118        ICompilationUnit cu= fType.getCompilationUnit();
1119        IMethod[] methods= fType.getMethods();
1120        int typeNameLength= fType.getElementName().length();
1121        for (int i= 0; i < methods.length; i++){
1122            if (methods[i].isConstructor()) {
1123                /*
1124                 * constructor declarations cannot be fully qualified so we can use simple replace here
1125                 *
1126                 * if (methods[i].getNameRange() == null), then it's a binary file so it's wrong anyway
1127                 * (checked as a precondition)
1128                 */

1129                String JavaDoc name= RefactoringCoreMessages.RenameTypeRefactoring_rename_constructor;
1130                TextChangeCompatibility.addTextEdit(manager.get(cu), name, new ReplaceEdit(methods[i].getNameRange().getOffset(), typeNameLength, getNewElementName()));
1131            }
1132        }
1133    }
1134    
1135    private void addReferenceUpdates(TextChangeManager manager, IProgressMonitor pm) {
1136        pm.beginTask("", fReferences.length); //$NON-NLS-1$
1137
for (int i= 0; i < fReferences.length; i++){
1138            ICompilationUnit cu= fReferences[i].getCompilationUnit();
1139            if (cu == null)
1140                continue;
1141                    
1142            String JavaDoc name= RefactoringCoreMessages.RenameTypeRefactoring_update_reference;
1143            SearchMatch[] results= fReferences[i].getSearchResults();
1144
1145            for (int j= 0; j < results.length; j++){
1146                SearchMatch match= results[j];
1147                ReplaceEdit replaceEdit= new ReplaceEdit(match.getOffset(), match.getLength(), getNewElementName());
1148                TextChangeCompatibility.addTextEdit(manager.get(cu), name, replaceEdit, CATEGORY_TYPE_RENAME);
1149            }
1150            pm.worked(1);
1151        }
1152    }
1153    
1154    private void computeQualifiedNameMatches(IProgressMonitor pm) throws CoreException {
1155        IPackageFragment fragment= fType.getPackageFragment();
1156        if (fQualifiedNameSearchResult == null)
1157            fQualifiedNameSearchResult= new QualifiedNameSearchResult();
1158        QualifiedNameFinder.process(fQualifiedNameSearchResult, fType.getFullyQualifiedName(),
1159            fragment.getElementName() + "." + getNewElementName(), //$NON-NLS-1$
1160
fFilePatterns, fType.getJavaProject().getProject(), pm);
1161    }
1162
1163    public RefactoringStatus initialize(RefactoringArguments arguments) {
1164        if (arguments instanceof JavaRefactoringArguments) {
1165            final JavaRefactoringArguments extended= (JavaRefactoringArguments) arguments;
1166            final String JavaDoc handle= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_INPUT);
1167            if (handle != null) {
1168                final IJavaElement element= JDTRefactoringDescriptor.handleToElement(extended.getProject(), handle, false);
1169                if (element == null || !element.exists() || element.getElementType() != IJavaElement.TYPE)
1170                    return ScriptableRefactoring.createInputFatalStatus(element, getRefactoring().getName(), IJavaRefactorings.RENAME_TYPE);
1171                else
1172                    fType= (IType) element;
1173            } else
1174                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_INPUT));
1175            final String JavaDoc name= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_NAME);
1176            if (name != null && !"".equals(name)) //$NON-NLS-1$
1177
setNewElementName(name);
1178            else
1179                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_NAME));
1180            final String JavaDoc patterns= extended.getAttribute(ATTRIBUTE_PATTERNS);
1181            if (patterns != null && !"".equals(patterns)) //$NON-NLS-1$
1182
fFilePatterns= patterns;
1183            final String JavaDoc references= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_REFERENCES);
1184            if (references != null) {
1185                fUpdateReferences= Boolean.valueOf(references).booleanValue();
1186            } else
1187                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_REFERENCES));
1188            final String JavaDoc matches= extended.getAttribute(ATTRIBUTE_TEXTUAL_MATCHES);
1189            if (matches != null) {
1190                fUpdateTextualMatches= Boolean.valueOf(matches).booleanValue();
1191            } else
1192                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_TEXTUAL_MATCHES));
1193            final String JavaDoc qualified= extended.getAttribute(ATTRIBUTE_QUALIFIED);
1194            if (qualified != null) {
1195                fUpdateQualifiedNames= Boolean.valueOf(qualified).booleanValue();
1196            } else
1197                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_QUALIFIED));
1198            final String JavaDoc similarDeclarations= extended.getAttribute(ATTRIBUTE_SIMILAR_DECLARATIONS);
1199            if (similarDeclarations != null)
1200                fUpdateSimilarElements= Boolean.valueOf(similarDeclarations).booleanValue();
1201            else
1202                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_SIMILAR_DECLARATIONS));
1203            final String JavaDoc similarDeclarationsMatchingStrategy= extended.getAttribute(ATTRIBUTE_MATCHING_STRATEGY);
1204            if (similarDeclarationsMatchingStrategy != null) {
1205                try {
1206                    fRenamingStrategy= Integer.valueOf(similarDeclarationsMatchingStrategy).intValue();
1207                } catch (NumberFormatException JavaDoc e) {
1208                    return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, new String JavaDoc[] {similarDeclarationsMatchingStrategy, ATTRIBUTE_QUALIFIED}));
1209                }
1210            } else
1211                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_MATCHING_STRATEGY));
1212        } else
1213            return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments);
1214        return new RefactoringStatus();
1215    }
1216    
1217    // --------- Similar names
1218

1219    /**
1220     * Creates and initializes the refactoring processors for similarly named elements
1221     * @param progressMonitor
1222     * @param context
1223     * @return status
1224     * @throws CoreException
1225     */

1226    private RefactoringStatus initializeSimilarElementsRenameProcessors(IProgressMonitor progressMonitor, CheckConditionsContext context) throws CoreException {
1227
1228        Assert.isNotNull(fPreloadedElementToName);
1229        Assert.isNotNull(fPreloadedElementToSelection);
1230
1231        final RefactoringStatus status= new RefactoringStatus();
1232        final Set JavaDoc handledTopLevelMethods= new HashSet JavaDoc();
1233        final Set JavaDoc warnings= new HashSet JavaDoc();
1234        final List JavaDoc processors= new ArrayList JavaDoc();
1235        fFinalSimilarElementToName= new HashMap JavaDoc();
1236        
1237        CompilationUnit currentResolvedCU= null;
1238        ICompilationUnit currentCU= null;
1239        
1240        int current= 0;
1241        final int max= fPreloadedElementToName.size();
1242
1243        progressMonitor.beginTask("", max * 3); //$NON-NLS-1$
1244
progressMonitor.setTaskName(RefactoringCoreMessages.RenameTypeProcessor_checking_similarly_named_declarations_refactoring_conditions);
1245
1246        for (Iterator JavaDoc iter= fPreloadedElementToName.keySet().iterator(); iter.hasNext();) {
1247
1248            final IJavaElement element= (IJavaElement) iter.next();
1249            
1250            current++;
1251            progressMonitor.worked(3);
1252
1253            // not selected? -> skip
1254
if (! ((Boolean JavaDoc) (fPreloadedElementToSelection.get(element))).booleanValue())
1255                continue;
1256
1257            // already registered? (may happen with overridden methods) -> skip
1258
if (fFinalSimilarElementToName.containsKey(element))
1259                continue;
1260            
1261            // CompilationUnit changed? (note: fPreloadedElementToName is sorted by CompilationUnit)
1262
ICompilationUnit newCU= (ICompilationUnit) element.getAncestor(IJavaElement.COMPILATION_UNIT);
1263            
1264            if (!newCU.equals(currentCU)) {
1265
1266                checkCUCompleteConditions(status, currentResolvedCU, currentCU, processors);
1267                
1268                if (status.hasFatalError())
1269                    return status;
1270                
1271                // reset values
1272
currentResolvedCU= null;
1273                currentCU= newCU;
1274                processors.clear();
1275            }
1276            
1277            final String JavaDoc newName= (String JavaDoc) fPreloadedElementToName.get(element);
1278            RefactoringProcessor processor= null;
1279            
1280            if (element instanceof ILocalVariable) {
1281                final ILocalVariable currentLocal= (ILocalVariable) element;
1282
1283                if (currentResolvedCU == null)
1284                    currentResolvedCU= new RefactoringASTParser(AST.JLS3).parse(currentCU, true);
1285                
1286                processor= createLocalRenameProcessor(currentLocal, newName, currentResolvedCU);
1287
1288                // don't check for conflicting rename => is done by #checkCUCompleteConditions().
1289

1290                if (status.hasFatalError())
1291                    return status;
1292                fFinalSimilarElementToName.put(currentLocal, newName);
1293            }
1294            if (element instanceof IField) {
1295                final IField currentField= (IField) element;
1296                processor= createFieldRenameProcessor(currentField, newName);
1297
1298                status.merge(checkForConflictingRename(currentField, newName));
1299                if (status.hasFatalError())
1300                    return status;
1301                fFinalSimilarElementToName.put(currentField, newName);
1302            }
1303            if (element instanceof IMethod) {
1304                IMethod currentMethod= (IMethod) element;
1305                if (MethodChecks.isVirtual(currentMethod)) {
1306                    
1307                    final IType declaringType= currentMethod.getDeclaringType();
1308                    ITypeHierarchy hierarchy= null;
1309                    if (!declaringType.isInterface())
1310                        hierarchy= declaringType.newTypeHierarchy(new NullProgressMonitor());
1311                    
1312                    final IMethod topmost= MethodChecks.getTopmostMethod(currentMethod, hierarchy, new NullProgressMonitor());
1313                    if (topmost != null)
1314                        currentMethod= topmost;
1315                    if (handledTopLevelMethods.contains(currentMethod))
1316                        continue;
1317                    handledTopLevelMethods.add(currentMethod);
1318                    final IMethod[] ripples= MethodChecks.getOverriddenMethods(currentMethod, new NullProgressMonitor());
1319
1320                    if (checkForWarnings(warnings, newName, ripples))
1321                        continue;
1322
1323                    status.merge(checkForConflictingRename(ripples, newName));
1324                    if (status.hasFatalError())
1325                        return status;
1326
1327                    processor= createVirtualMethodRenameProcessor(currentMethod, newName, ripples, hierarchy);
1328                    fFinalSimilarElementToName.put(currentMethod, newName);
1329                    for (int i= 0; i < ripples.length; i++) {
1330                        fFinalSimilarElementToName.put(ripples[i], newName);
1331                    }
1332                } else {
1333                    
1334                    status.merge(checkForConflictingRename(new IMethod[] { currentMethod }, newName));
1335                    if (status.hasFatalError())
1336                        break;
1337                    
1338                    fFinalSimilarElementToName.put(currentMethod, newName);
1339                    
1340                    processor= createNonVirtualMethodRenameProcessor(currentMethod, newName);
1341                }
1342            }
1343            
1344            progressMonitor.subTask(Messages.format(RefactoringCoreMessages.RenameTypeProcessor_progress_current_total, new Object JavaDoc[] { String.valueOf(current), String.valueOf(max)}));
1345
1346            status.merge(processor.checkInitialConditions(new NoOverrideProgressMonitor(progressMonitor, 1)));
1347
1348            if (status.hasFatalError())
1349                return status;
1350
1351            status.merge(processor.checkFinalConditions(new NoOverrideProgressMonitor(progressMonitor, 1), context));
1352
1353            if (status.hasFatalError())
1354                return status;
1355            
1356            processors.add(processor);
1357
1358            progressMonitor.worked(1);
1359            
1360            if (progressMonitor.isCanceled())
1361                throw new OperationCanceledException();
1362        }
1363
1364        // check last CU
1365
checkCUCompleteConditions(status, currentResolvedCU, currentCU, processors);
1366        
1367        status.merge(addWarnings(warnings));
1368
1369        progressMonitor.done();
1370        return status;
1371    }
1372
1373    private void checkCUCompleteConditions(final RefactoringStatus status, CompilationUnit currentResolvedCU, ICompilationUnit currentCU, List JavaDoc processors) throws CoreException {
1374
1375        // check local variable conditions
1376
List JavaDoc locals= getProcessorsOfType(processors, RenameLocalVariableProcessor.class);
1377        if (!locals.isEmpty()) {
1378            RenameAnalyzeUtil.LocalAnalyzePackage[] analyzePackages= new RenameAnalyzeUtil.LocalAnalyzePackage[locals.size()];
1379            TextChangeManager manager= new TextChangeManager();
1380            int current= 0;
1381            TextChange textChange= manager.get(currentCU);
1382            textChange.setKeepPreviewEdits(true);
1383            for (Iterator JavaDoc iterator= locals.iterator(); iterator.hasNext();) {
1384                RenameLocalVariableProcessor localProcessor= (RenameLocalVariableProcessor) iterator.next();
1385                RenameAnalyzeUtil.LocalAnalyzePackage analyzePackage= localProcessor.getLocalAnalyzePackage();
1386                analyzePackages[current]= analyzePackage;
1387                for (int i= 0; i < analyzePackage.fOccurenceEdits.length; i++) {
1388                    TextChangeCompatibility.addTextEdit(textChange, "", analyzePackage.fOccurenceEdits[i], GroupCategorySet.NONE); //$NON-NLS-1$
1389
}
1390                current++;
1391            }
1392            status.merge(RenameAnalyzeUtil.analyzeLocalRenames(analyzePackages, textChange, currentResolvedCU, false));
1393        }
1394
1395        /*
1396         * There is room for performance improvement here: One could move
1397         * shadowing analyzes out of the field and method processors and perform
1398         * it here, thus saving on working copy creation. Drawback is increased
1399         * heap consumption.
1400         */

1401    }
1402
1403    private List JavaDoc getProcessorsOfType(List JavaDoc processors, Class JavaDoc type) {
1404        List JavaDoc tmp= new ArrayList JavaDoc();
1405        for (Iterator JavaDoc iter= processors.iterator(); iter.hasNext();) {
1406            RefactoringProcessor element= (RefactoringProcessor) iter.next();
1407            if (element.getClass().equals(type))
1408                tmp.add(element);
1409        }
1410        return tmp;
1411    }
1412
1413    // ------------------ Error checking -------------
1414

1415    /**
1416     * Checks whether one of the given methods, which will all be renamed to
1417     * "newName", shares a type with another already registered method which is
1418     * renamed to the same new name and shares the same parameters.
1419     * @param methods
1420     * @param newName
1421     * @return status
1422     *
1423     * @see #checkForConflictingRename(IField, String)
1424     */

1425    private RefactoringStatus checkForConflictingRename(IMethod[] methods, String JavaDoc newName) {
1426        RefactoringStatus status= new RefactoringStatus();
1427        for (Iterator JavaDoc iter= fFinalSimilarElementToName.keySet().iterator(); iter.hasNext();) {
1428            IJavaElement element= (IJavaElement) iter.next();
1429            if (element instanceof IMethod) {
1430                IMethod alreadyRegisteredMethod= (IMethod) element;
1431                String JavaDoc alreadyRegisteredMethodName= (String JavaDoc) fFinalSimilarElementToName.get(element);
1432                for (int i= 0; i < methods.length; i++) {
1433                    IMethod method2= methods[i];
1434                    if ( (alreadyRegisteredMethodName.equals(newName)) && (method2.getDeclaringType().equals(alreadyRegisteredMethod.getDeclaringType()))
1435                            && (sameParams(alreadyRegisteredMethod, method2))) {
1436                        String JavaDoc message= Messages.format(RefactoringCoreMessages.RenameTypeProcessor_cannot_rename_methods_same_new_name, new String JavaDoc[] { alreadyRegisteredMethod.getElementName(),
1437                                method2.getElementName(), alreadyRegisteredMethod.getDeclaringType().getFullyQualifiedName(), newName });
1438                        status.addFatalError(message);
1439                        return status;
1440                    }
1441                }
1442            }
1443        }
1444        return status;
1445    }
1446
1447    private static boolean sameParams(IMethod method, IMethod method2) {
1448
1449        if (method.getNumberOfParameters() != method2.getNumberOfParameters())
1450            return false;
1451
1452        String JavaDoc[] params= method.getParameterTypes();
1453        String JavaDoc[] params2= method2.getParameterTypes();
1454
1455        for (int i= 0; i < params.length; i++) {
1456            String JavaDoc t1= Signature.getSimpleName(Signature.toString(params[i]));
1457            String JavaDoc t2= Signature.getSimpleName(Signature.toString(params2[i]));
1458            if (!t1.equals(t2)) {
1459                return false;
1460            }
1461        }
1462        return true;
1463    }
1464
1465    /**
1466     * If suffix matching is enabled, the refactoring may suggest two fields to
1467     * have the same name which reside in the same type. Same thing may also
1468     * happen if the user makes poor choices for the field names.
1469     *
1470     * Consider: FooBarThing fFooBarThing; FooBarThing fBarThing;
1471     *
1472     * Rename "FooBarThing" to "DifferentHunk". Suggestion for both fields is
1473     * "fDifferentHunk" (and rightly so).
1474     * @param currentField
1475     * @param newName
1476     * @return status
1477     */

1478    private RefactoringStatus checkForConflictingRename(IField currentField, String JavaDoc newName) {
1479        RefactoringStatus status= new RefactoringStatus();
1480        for (Iterator JavaDoc iter= fFinalSimilarElementToName.keySet().iterator(); iter.hasNext();) {
1481            IJavaElement element= (IJavaElement) iter.next();
1482            if (element instanceof IField) {
1483                IField alreadyRegisteredField= (IField) element;
1484                String JavaDoc alreadyRegisteredFieldName= (String JavaDoc) fFinalSimilarElementToName.get(element);
1485                if (alreadyRegisteredFieldName.equals(newName)) {
1486                    if (alreadyRegisteredField.getDeclaringType().equals(currentField.getDeclaringType())) {
1487                        
1488                        String JavaDoc message= Messages.format(RefactoringCoreMessages.RenameTypeProcessor_cannot_rename_fields_same_new_name, new String JavaDoc[] { alreadyRegisteredField.getElementName(),
1489                                currentField.getElementName(), alreadyRegisteredField.getDeclaringType().getFullyQualifiedName(), newName });
1490                        status.addFatalError(message);
1491                        return status;
1492                    }
1493                }
1494            }
1495        }
1496        return status;
1497    }
1498
1499    private RefactoringStatus addWarnings(final Set JavaDoc warnings) {
1500        RefactoringStatus status= new RefactoringStatus();
1501
1502        // Remove deleted ripple methods from user selection and add warnings
1503
for (Iterator JavaDoc iter= warnings.iterator(); iter.hasNext();) {
1504            final Warning warning= (Warning) iter.next();
1505            final IMethod[] elements= warning.getRipple();
1506            if (warning.isSelectionWarning()) {
1507                String JavaDoc message= Messages.format(RefactoringCoreMessages.RenameTypeProcessor_deselected_method_is_overridden,
1508                        new String JavaDoc[] { JavaElementLabels.getElementLabel(elements[0], JavaElementLabels.ALL_DEFAULT),
1509                                JavaElementLabels.getElementLabel(elements[0].getDeclaringType(), JavaElementLabels.ALL_DEFAULT) });
1510                status.addWarning(message);
1511            }
1512            if (warning.isNameWarning()) {
1513                String JavaDoc message= Messages.format(
1514                        RefactoringCoreMessages.RenameTypeProcessor_renamed_method_is_overridden, new String JavaDoc[] {
1515                                JavaElementLabels.getElementLabel(elements[0], JavaElementLabels.ALL_DEFAULT),
1516                                JavaElementLabels.getElementLabel(elements[0].getDeclaringType(), JavaElementLabels.ALL_DEFAULT) });
1517                status.addWarning(message);
1518            }
1519            for (int i= 0; i < elements.length; i++)
1520                fPreloadedElementToSelection.put(elements[i], Boolean.FALSE);
1521        }
1522        return status;
1523    }
1524
1525    /*
1526     * If one of the methods of this ripple was deselected or renamed by
1527     * the user, deselect the whole chain and add warnings.
1528     */

1529    private boolean checkForWarnings(final Set JavaDoc warnings, final String JavaDoc newName, final IMethod[] ripples) {
1530
1531        boolean addSelectionWarning= false;
1532        boolean addNameWarning= false;
1533        for (int i= 0; i < ripples.length; i++) {
1534            String JavaDoc newNameOfRipple= (String JavaDoc) fPreloadedElementToName.get(ripples[i]);
1535            Boolean JavaDoc selected= (Boolean JavaDoc) fPreloadedElementToSelection.get(ripples[i]);
1536
1537            // selected may be null here due to supermethods like
1538
// setSomeClass(Object class) (subsignature match)
1539
// Don't add a warning.
1540
if (selected == null)
1541                continue;
1542
1543            if (!selected.booleanValue())
1544                addSelectionWarning= true;
1545
1546            if (!newName.equals(newNameOfRipple))
1547                addNameWarning= true;
1548        }
1549        if (addSelectionWarning || addNameWarning)
1550            warnings.add(new Warning(ripples, addSelectionWarning, addNameWarning));
1551
1552        return (addSelectionWarning || addNameWarning);
1553    }
1554
1555    private class Warning {
1556
1557        private IMethod[] fRipple;
1558        private boolean fSelectionWarning;
1559        private boolean fNameWarning;
1560
1561        public Warning(IMethod[] ripple, boolean isSelectionWarning, boolean isNameWarning) {
1562            fRipple= ripple;
1563            fSelectionWarning= isSelectionWarning;
1564            fNameWarning= isNameWarning;
1565        }
1566
1567        public boolean isNameWarning() {
1568            return fNameWarning;
1569        }
1570
1571        public IMethod[] getRipple() {
1572            return fRipple;
1573        }
1574
1575        public boolean isSelectionWarning() {
1576            return fSelectionWarning;
1577        }
1578    }
1579
1580    // ----------------- Processor creation --------
1581

1582    private RenameMethodProcessor createVirtualMethodRenameProcessor(IMethod currentMethod, String JavaDoc newMethodName, IMethod[] ripples, ITypeHierarchy hierarchy) throws JavaModelException {
1583        RenameMethodProcessor processor= new RenameVirtualMethodProcessor(currentMethod, ripples, fChangeManager, hierarchy, CATEGORY_METHOD_RENAME);
1584        initMethodProcessor(processor, newMethodName);
1585        return processor;
1586    }
1587
1588    private RenameMethodProcessor createNonVirtualMethodRenameProcessor(IMethod currentMethod, String JavaDoc newMethodName) {
1589        RenameMethodProcessor processor= new RenameNonVirtualMethodProcessor(currentMethod, fChangeManager, CATEGORY_METHOD_RENAME);
1590        initMethodProcessor(processor, newMethodName);
1591        return processor;
1592    }
1593
1594    private void initMethodProcessor(RenameMethodProcessor processor, String JavaDoc newMethodName) {
1595        processor.setNewElementName(newMethodName);
1596        processor.setUpdateReferences(getUpdateReferences());
1597    }
1598
1599    private RenameFieldProcessor createFieldRenameProcessor(final IField field, final String JavaDoc newName) {
1600        final RenameFieldProcessor processor= new RenameFieldProcessor(field, fChangeManager, CATEGORY_FIELD_RENAME);
1601        processor.setNewElementName(newName);
1602        processor.setRenameGetter(false);
1603        processor.setRenameSetter(false);
1604        processor.setUpdateReferences(getUpdateReferences());
1605        processor.setUpdateTextualMatches(false);
1606        return processor;
1607    }
1608    
1609    private RenameLocalVariableProcessor createLocalRenameProcessor(final ILocalVariable local, final String JavaDoc newName, final CompilationUnit compilationUnit) {
1610        final RenameLocalVariableProcessor processor= new RenameLocalVariableProcessor(local, fChangeManager, compilationUnit, CATEGORY_LOCAL_RENAME);
1611        processor.setNewElementName(newName);
1612        processor.setUpdateReferences(getUpdateReferences());
1613        return processor;
1614    }
1615
1616    // ----------- Edit creation -----------
1617

1618
1619    /**
1620     * Updates textual matches for fields.
1621     *
1622     * Strategy for matching text matches: Match and replace all fully qualified
1623     * field names, but non-qualified field names only iff there are no fields
1624     * which have the same original, but a different new name. Don't add java
1625     * references; duplicate edits may be created but do not matter.
1626     * @param manager
1627     * @param monitor
1628     * @throws CoreException
1629     */

1630    private void addSimilarElementsTextualUpdates(TextChangeManager manager, IProgressMonitor monitor) throws CoreException {
1631
1632        final Map JavaDoc simpleNames= new HashMap JavaDoc();
1633        final List JavaDoc forbiddenSimpleNames= new ArrayList JavaDoc();
1634
1635        for (Iterator JavaDoc iter= fFinalSimilarElementToName.keySet().iterator(); iter.hasNext();) {
1636            final IJavaElement element= (IJavaElement) iter.next();
1637            if (element instanceof IField) {
1638
1639                if (forbiddenSimpleNames.contains(element.getElementName()))
1640                    continue;
1641
1642                final String JavaDoc registeredNewName= (String JavaDoc) simpleNames.get(element.getElementName());
1643                final String JavaDoc newNameToCheck= (String JavaDoc) fFinalSimilarElementToName.get(element);
1644                if (registeredNewName == null)
1645                    simpleNames.put(element.getElementName(), newNameToCheck);
1646                else if (!registeredNewName.equals(newNameToCheck))
1647                    forbiddenSimpleNames.add(element.getElementName());
1648            }
1649        }
1650
1651        for (Iterator JavaDoc iter= fFinalSimilarElementToName.keySet().iterator(); iter.hasNext();) {
1652            final IJavaElement element= (IJavaElement) iter.next();
1653            if (element instanceof IField) {
1654                final IField field= (IField) element;
1655                final String JavaDoc newName= (String JavaDoc) fFinalSimilarElementToName.get(field);
1656                TextMatchUpdater.perform(monitor, RefactoringScopeFactory.create(field), field.getElementName(), field.getDeclaringType().getFullyQualifiedName(), newName, manager,
1657                        new SearchResultGroup[0], forbiddenSimpleNames.contains(field.getElementName()));
1658            }
1659        }
1660    }
1661
1662    // ------ UI interaction
1663

1664    /**
1665     * @return the map of similarly named elements (IJavaElement -> String with new name)
1666     * This map is live. Callers may change the new names of the elements; they
1667     * may not change the key set.
1668     */

1669    public Map JavaDoc/* <IJavaElement, String> */getSimilarElementsToNewNames() {
1670        return fPreloadedElementToName;
1671    }
1672
1673    /**
1674     * @return the map of similarly named elements (IJavaElement -> Boolean if selected) This
1675     * map is live. Callers may change the selection status of the elements;
1676     * they may not change the key set.
1677     */

1678    public Map JavaDoc/* <IJavaElement, Boolean> */getSimilarElementsToSelection() {
1679        return fPreloadedElementToSelection;
1680    }
1681
1682    /**
1683     * Resets the element maps back to the original status. This affects the
1684     * maps returned in {@link #getSimilarElementsToNewNames() } and
1685     * {@link #getSimilarElementsToSelection() }. All new names are reset to
1686     * the calculated ones and every element gets selected.
1687     */

1688    public void resetSelectedSimilarElements() {
1689        Assert.isNotNull(fPreloadedElementToName);
1690        for (Iterator JavaDoc iter= fPreloadedElementToNameDefault.keySet().iterator(); iter.hasNext();) {
1691            final IJavaElement element= (IJavaElement) iter.next();
1692            fPreloadedElementToName.put(element, fPreloadedElementToNameDefault.get(element));
1693            fPreloadedElementToSelection.put(element, Boolean.TRUE);
1694        }
1695    }
1696
1697    /**
1698     * @return true iff the "update similarly named elements" flag is set AND the
1699     * search yielded some elements to be renamed.
1700     */

1701    public boolean hasSimilarElementsToRename() {
1702        if (!fUpdateSimilarElements)
1703            return false;
1704        if (fPreloadedElementToName == null)
1705            return false;
1706        if (fPreloadedElementToName.size() == 0)
1707            return false;
1708        return true;
1709    }
1710}
1711
Popular Tags