Source Code Cross Referenced for RenameTypeProcessor.java in  » IDE-Eclipse » jdt » org » eclipse » jdt » internal » corext » refactoring » rename » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Eclipse » jdt » org.eclipse.jdt.internal.corext.refactoring.rename 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*******************************************************************************
0002:         * Copyright (c) 2000, 2007 IBM Corporation and others.
0003:         * All rights reserved. This program and the accompanying materials
0004:         * are made available under the terms of the Eclipse Public License v1.0
0005:         * which accompanies this distribution, and is available at
0006:         * http://www.eclipse.org/legal/epl-v10.html
0007:         *
0008:         * Contributors:
0009:         *     IBM Corporation - initial API and implementation
0010:         *     Matt Chapman, mpchapman@gmail.com - 89977 Make JDT .java agnostic
0011:         *******************************************************************************/package org.eclipse.jdt.internal.corext.refactoring.rename;
0012:
0013:        import java.util.ArrayList;
0014:        import java.util.Arrays;
0015:        import java.util.HashMap;
0016:        import java.util.HashSet;
0017:        import java.util.Iterator;
0018:        import java.util.LinkedHashMap;
0019:        import java.util.List;
0020:        import java.util.Map;
0021:        import java.util.Set;
0022:
0023:        import org.eclipse.text.edits.ReplaceEdit;
0024:
0025:        import org.eclipse.core.runtime.Assert;
0026:        import org.eclipse.core.runtime.CoreException;
0027:        import org.eclipse.core.runtime.IConfigurationElement;
0028:        import org.eclipse.core.runtime.IProduct;
0029:        import org.eclipse.core.runtime.IProgressMonitor;
0030:        import org.eclipse.core.runtime.IStatus;
0031:        import org.eclipse.core.runtime.NullProgressMonitor;
0032:        import org.eclipse.core.runtime.OperationCanceledException;
0033:        import org.eclipse.core.runtime.Platform;
0034:        import org.eclipse.core.runtime.SubProgressMonitor;
0035:
0036:        import org.eclipse.core.resources.IContainer;
0037:        import org.eclipse.core.resources.IFile;
0038:        import org.eclipse.core.resources.IResource;
0039:
0040:        import org.eclipse.ltk.core.refactoring.Change;
0041:        import org.eclipse.ltk.core.refactoring.GroupCategory;
0042:        import org.eclipse.ltk.core.refactoring.GroupCategorySet;
0043:        import org.eclipse.ltk.core.refactoring.IResourceMapper;
0044:        import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
0045:        import org.eclipse.ltk.core.refactoring.RefactoringStatus;
0046:        import org.eclipse.ltk.core.refactoring.RefactoringStatusContext;
0047:        import org.eclipse.ltk.core.refactoring.TextChange;
0048:        import org.eclipse.ltk.core.refactoring.TextFileChange;
0049:        import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
0050:        import org.eclipse.ltk.core.refactoring.participants.IParticipantDescriptorFilter;
0051:        import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments;
0052:        import org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor;
0053:        import org.eclipse.ltk.core.refactoring.participants.RenameArguments;
0054:
0055:        import org.eclipse.jdt.core.Flags;
0056:        import org.eclipse.jdt.core.ICompilationUnit;
0057:        import org.eclipse.jdt.core.IField;
0058:        import org.eclipse.jdt.core.IImportDeclaration;
0059:        import org.eclipse.jdt.core.IJavaElement;
0060:        import org.eclipse.jdt.core.IJavaProject;
0061:        import org.eclipse.jdt.core.ILocalVariable;
0062:        import org.eclipse.jdt.core.IMember;
0063:        import org.eclipse.jdt.core.IMethod;
0064:        import org.eclipse.jdt.core.IPackageFragment;
0065:        import org.eclipse.jdt.core.ISourceRange;
0066:        import org.eclipse.jdt.core.IType;
0067:        import org.eclipse.jdt.core.ITypeHierarchy;
0068:        import org.eclipse.jdt.core.JavaCore;
0069:        import org.eclipse.jdt.core.JavaModelException;
0070:        import org.eclipse.jdt.core.Signature;
0071:        import org.eclipse.jdt.core.dom.AST;
0072:        import org.eclipse.jdt.core.dom.ASTVisitor;
0073:        import org.eclipse.jdt.core.dom.CompilationUnit;
0074:        import org.eclipse.jdt.core.dom.MethodDeclaration;
0075:        import org.eclipse.jdt.core.dom.Modifier;
0076:        import org.eclipse.jdt.core.dom.TypeDeclaration;
0077:        import org.eclipse.jdt.core.refactoring.IJavaElementMapper;
0078:        import org.eclipse.jdt.core.refactoring.IJavaRefactorings;
0079:        import org.eclipse.jdt.core.refactoring.RenameTypeArguments;
0080:        import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor;
0081:        import org.eclipse.jdt.core.refactoring.descriptors.RenameJavaElementDescriptor;
0082:        import org.eclipse.jdt.core.search.IJavaSearchConstants;
0083:        import org.eclipse.jdt.core.search.IJavaSearchScope;
0084:        import org.eclipse.jdt.core.search.SearchMatch;
0085:        import org.eclipse.jdt.core.search.SearchPattern;
0086:        import org.eclipse.jdt.core.search.TypeReferenceMatch;
0087:
0088:        import org.eclipse.jdt.internal.corext.refactoring.Checks;
0089:        import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment;
0090:        import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments;
0091:        import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringDescriptorUtil;
0092:        import org.eclipse.jdt.internal.corext.refactoring.RefactoringAvailabilityTester;
0093:        import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
0094:        import org.eclipse.jdt.internal.corext.refactoring.RefactoringScopeFactory;
0095:        import org.eclipse.jdt.internal.corext.refactoring.RefactoringSearchEngine;
0096:        import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup;
0097:        import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext;
0098:        import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange;
0099:        import org.eclipse.jdt.internal.corext.refactoring.changes.RenameCompilationUnitChange;
0100:        import org.eclipse.jdt.internal.corext.refactoring.changes.RenameResourceChange;
0101:        import org.eclipse.jdt.internal.corext.refactoring.changes.TextChangeCompatibility;
0102:        import org.eclipse.jdt.internal.corext.refactoring.code.ScriptableRefactoring;
0103:        import org.eclipse.jdt.internal.corext.refactoring.participants.JavaProcessors;
0104:        import org.eclipse.jdt.internal.corext.refactoring.tagging.IQualifiedNameUpdating;
0105:        import org.eclipse.jdt.internal.corext.refactoring.tagging.IReferenceUpdating;
0106:        import org.eclipse.jdt.internal.corext.refactoring.tagging.ISimilarDeclarationUpdating;
0107:        import org.eclipse.jdt.internal.corext.refactoring.tagging.ITextUpdating;
0108:        import org.eclipse.jdt.internal.corext.refactoring.util.Changes;
0109:        import org.eclipse.jdt.internal.corext.refactoring.util.JavaElementUtil;
0110:        import org.eclipse.jdt.internal.corext.refactoring.util.QualifiedNameFinder;
0111:        import org.eclipse.jdt.internal.corext.refactoring.util.QualifiedNameSearchResult;
0112:        import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
0113:        import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
0114:        import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager;
0115:        import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
0116:        import org.eclipse.jdt.internal.corext.util.JdtFlags;
0117:        import org.eclipse.jdt.internal.corext.util.Messages;
0118:        import org.eclipse.jdt.internal.corext.util.SearchUtils;
0119:
0120:        import org.eclipse.jdt.ui.JavaElementLabels;
0121:        import org.eclipse.jdt.ui.refactoring.IRefactoringProcessorIds;
0122:
0123:        import org.eclipse.jdt.internal.ui.JavaPlugin;
0124:        import org.eclipse.jdt.internal.ui.refactoring.RefactoringSaveHelper;
0125:
0126:        public class RenameTypeProcessor extends JavaRenameProcessor implements 
0127:                ITextUpdating, IReferenceUpdating, IQualifiedNameUpdating,
0128:                ISimilarDeclarationUpdating, IResourceMapper,
0129:                IJavaElementMapper {
0130:
0131:            private static final String ATTRIBUTE_QUALIFIED = "qualified"; //$NON-NLS-1$
0132:            private static final String ATTRIBUTE_TEXTUAL_MATCHES = "textual"; //$NON-NLS-1$
0133:            private static final String ATTRIBUTE_PATTERNS = "patterns"; //$NON-NLS-1$
0134:            private static final String ATTRIBUTE_SIMILAR_DECLARATIONS = "similarDeclarations"; //$NON-NLS-1$
0135:            private static final String ATTRIBUTE_MATCHING_STRATEGY = "matchStrategy"; //$NON-NLS-1$
0136:
0137:            private static final GroupCategorySet CATEGORY_TYPE_RENAME = new GroupCategorySet(
0138:                    new GroupCategory(
0139:                            "org.eclipse.jdt.internal.corext.refactoring.rename.renameType.type", RefactoringCoreMessages.RenameTypeProcessor_changeCategory_type, RefactoringCoreMessages.RenameTypeProcessor_changeCategory_type_description)); //$NON-NLS-1$
0140:            private static final GroupCategorySet CATEGORY_METHOD_RENAME = new GroupCategorySet(
0141:                    new GroupCategory(
0142:                            "org.eclipse.jdt.internal.corext.refactoring.rename.renameType.method", RefactoringCoreMessages.RenameTypeProcessor_changeCategory_method, RefactoringCoreMessages.RenameTypeProcessor_changeCategory_method_description)); //$NON-NLS-1$
0143:            private static final GroupCategorySet CATEGORY_FIELD_RENAME = new GroupCategorySet(
0144:                    new GroupCategory(
0145:                            "org.eclipse.jdt.internal.corext.refactoring.rename.renameType.field", RefactoringCoreMessages.RenameTypeProcessor_changeCategory_fields, RefactoringCoreMessages.RenameTypeProcessor_changeCategory_fields_description)); //$NON-NLS-1$ 
0146:            private static final GroupCategorySet CATEGORY_LOCAL_RENAME = new GroupCategorySet(
0147:                    new GroupCategory(
0148:                            "org.eclipse.jdt.internal.corext.refactoring.rename.renameType.local", RefactoringCoreMessages.RenameTypeProcessor_changeCategory_local_variables, RefactoringCoreMessages.RenameTypeProcessor_changeCategory_local_variables_description)); //$NON-NLS-1$			
0149:
0150:            private IType fType;
0151:            private SearchResultGroup[] fReferences;
0152:            private TextChangeManager fChangeManager;
0153:            private QualifiedNameSearchResult fQualifiedNameSearchResult;
0154:
0155:            private boolean fUpdateReferences;
0156:
0157:            private boolean fUpdateTextualMatches;
0158:
0159:            private boolean fUpdateQualifiedNames;
0160:            private String fFilePatterns;
0161:
0162:            // --- similar elements
0163:
0164:            private boolean fUpdateSimilarElements;
0165:            private Map/* <IJavaElement, String> */fFinalSimilarElementToName = null;
0166:            private int fRenamingStrategy;
0167:
0168:            // Preloaded information for the UI.
0169:            private LinkedHashMap/* <IJavaElement, String> */fPreloadedElementToName = null;
0170:            private Map/* <IJavaElement, Boolean> */fPreloadedElementToSelection = null;
0171:            private LinkedHashMap/* <IJavaElement, String> */fPreloadedElementToNameDefault = null;
0172:
0173:            // Cache information to decide whether to
0174:            // re-update references and preload info
0175:            private String fCachedNewName = null;
0176:            private boolean fCachedRenameSimilarElements = false;
0177:            private int fCachedRenamingStrategy = -1;
0178:            private RefactoringStatus fCachedRefactoringStatus = null;
0179:
0180:            public static final class ParticipantDescriptorFilter implements 
0181:                    IParticipantDescriptorFilter {
0182:
0183:                public boolean select(IConfigurationElement element,
0184:                        RefactoringStatus status) {
0185:                    IConfigurationElement[] params = element.getChildren(PARAM);
0186:                    for (int i = 0; i < params.length; i++) {
0187:                        IConfigurationElement param = params[i];
0188:                        if ("handlesSimilarDeclarations".equals(param.getAttribute(NAME)) && //$NON-NLS-1$
0189:                                "false".equals(param.getAttribute(VALUE))) { //$NON-NLS-1$
0190:                            return false;
0191:                        }
0192:                    }
0193:                    return true;
0194:                }
0195:            }
0196:
0197:            private class NoOverrideProgressMonitor extends SubProgressMonitor {
0198:                public NoOverrideProgressMonitor(IProgressMonitor monitor,
0199:                        int ticks) {
0200:                    super (monitor, ticks,
0201:                            SubProgressMonitor.SUPPRESS_SUBTASK_LABEL);
0202:                }
0203:
0204:                public void setTaskName(String name) {
0205:                    // do nothing
0206:                }
0207:            }
0208:
0209:            /**
0210:             * Creates a new rename type processor.
0211:             * @param type the type, or <code>null</code> if invoked by scripting
0212:             */
0213:            public RenameTypeProcessor(IType type) {
0214:                fType = type;
0215:                if (type != null)
0216:                    setNewElementName(type.getElementName());
0217:                fUpdateReferences = true; //default is yes
0218:                fUpdateTextualMatches = false;
0219:                fUpdateSimilarElements = false; // default is no
0220:                fRenamingStrategy = RenamingNameSuggestor.STRATEGY_EXACT;
0221:            }
0222:
0223:            public IType getType() {
0224:                return fType;
0225:            }
0226:
0227:            public String getIdentifier() {
0228:                return IRefactoringProcessorIds.RENAME_TYPE_PROCESSOR;
0229:            }
0230:
0231:            public boolean isApplicable() throws CoreException {
0232:                return RefactoringAvailabilityTester.isRenameAvailable(fType);
0233:            }
0234:
0235:            public String getProcessorName() {
0236:                return RefactoringCoreMessages.RenameTypeRefactoring_name;
0237:            }
0238:
0239:            protected String[] getAffectedProjectNatures() throws CoreException {
0240:                return JavaProcessors.computeAffectedNatures(fType);
0241:            }
0242:
0243:            public Object[] getElements() {
0244:                return new Object[] { fType };
0245:            }
0246:
0247:            protected RenameModifications computeRenameModifications() {
0248:                RenameModifications result = new RenameModifications();
0249:                result.rename(fType, new RenameTypeArguments(
0250:                        getNewElementName(), getUpdateReferences(),
0251:                        getUpdateSimilarDeclarations(), getSimilarElements()),
0252:                        createParticipantDescriptorFilter());
0253:                if (isPrimaryType()) {
0254:                    ICompilationUnit cu = fType.getCompilationUnit();
0255:                    String newCUName = getNewCompilationUnit().getElementName();
0256:                    result.rename(cu, new RenameArguments(newCUName,
0257:                            getUpdateReferences()));
0258:                }
0259:                return result;
0260:            }
0261:
0262:            /*
0263:             * Note: this is a handle-only method!
0264:             */
0265:            private boolean isPrimaryType() {
0266:                String cuName = fType.getCompilationUnit().getElementName();
0267:                String typeName = fType.getElementName();
0268:                return Checks.isTopLevel(fType)
0269:                        && JavaCore.removeJavaLikeExtension(cuName).equals(
0270:                                typeName);
0271:            }
0272:
0273:            //---- IRenameProcessor ----------------------------------------------
0274:
0275:            public String getCurrentElementName() {
0276:                return fType.getElementName();
0277:            }
0278:
0279:            public String getCurrentElementQualifier() {
0280:                return JavaModelUtil.getTypeContainerName(fType);
0281:            }
0282:
0283:            public RefactoringStatus checkNewElementName(String newName) {
0284:                Assert.isNotNull(newName, "new name"); //$NON-NLS-1$
0285:                RefactoringStatus result = Checks.checkTypeName(newName, fType);
0286:                if (Checks.isAlreadyNamed(fType, newName))
0287:                    result
0288:                            .addFatalError(RefactoringCoreMessages.RenameTypeRefactoring_choose_another_name);
0289:                return result;
0290:            }
0291:
0292:            public Object getNewElement() {
0293:                if (Checks.isTopLevel(fType)) {
0294:                    return getNewCompilationUnit().getType(getNewElementName());
0295:                } else {
0296:                    return fType.getDeclaringType()
0297:                            .getType(getNewElementName());
0298:                }
0299:            }
0300:
0301:            private ICompilationUnit getNewCompilationUnit() {
0302:                ICompilationUnit cu = fType.getCompilationUnit();
0303:                if (isPrimaryType()) {
0304:                    IPackageFragment parent = fType.getPackageFragment();
0305:                    String renamedCUName = JavaModelUtil.getRenamedCUName(cu,
0306:                            getNewElementName());
0307:                    return parent.getCompilationUnit(renamedCUName);
0308:                } else {
0309:                    return cu;
0310:                }
0311:            }
0312:
0313:            //---- JavaRenameProcessor -------------------------------------------
0314:
0315:            protected RenameArguments createRenameArguments() {
0316:                return new RenameTypeArguments(getNewElementName(),
0317:                        getUpdateReferences(), getUpdateSimilarDeclarations(),
0318:                        getSimilarElements());
0319:            }
0320:
0321:            protected IParticipantDescriptorFilter createParticipantDescriptorFilter() {
0322:                if (!getUpdateSimilarDeclarations())
0323:                    return null;
0324:                return new ParticipantDescriptorFilter();
0325:            }
0326:
0327:            protected IFile[] getChangedFiles() throws CoreException {
0328:                List result = new ArrayList();
0329:                result.addAll(Arrays.asList(ResourceUtil
0330:                        .getFiles(fChangeManager.getAllCompilationUnits())));
0331:                if (fQualifiedNameSearchResult != null)
0332:                    result.addAll(Arrays.asList(fQualifiedNameSearchResult
0333:                            .getAllFiles()));
0334:                if (willRenameCU())
0335:                    result
0336:                            .add(ResourceUtil.getFile(fType
0337:                                    .getCompilationUnit()));
0338:                return (IFile[]) result.toArray(new IFile[result.size()]);
0339:            }
0340:
0341:            public int getSaveMode() {
0342:                return RefactoringSaveHelper.SAVE_NON_JAVA_UPDATES;
0343:            }
0344:
0345:            //---- ITextUpdating -------------------------------------------------
0346:
0347:            public boolean canEnableTextUpdating() {
0348:                return true;
0349:            }
0350:
0351:            public boolean getUpdateTextualMatches() {
0352:                return fUpdateTextualMatches;
0353:            }
0354:
0355:            public void setUpdateTextualMatches(boolean update) {
0356:                fUpdateTextualMatches = update;
0357:            }
0358:
0359:            //---- IReferenceUpdating --------------------------------------
0360:
0361:            public void setUpdateReferences(boolean update) {
0362:                fUpdateReferences = update;
0363:            }
0364:
0365:            public boolean canEnableUpdateReferences() {
0366:                return true;
0367:            }
0368:
0369:            public boolean getUpdateReferences() {
0370:                return fUpdateReferences;
0371:            }
0372:
0373:            //---- IQualifiedNameUpdating ----------------------------------
0374:
0375:            public boolean canEnableQualifiedNameUpdating() {
0376:                return !fType.getPackageFragment().isDefaultPackage()
0377:                        && !(fType.getParent() instanceof  IType);
0378:            }
0379:
0380:            public boolean getUpdateQualifiedNames() {
0381:                return fUpdateQualifiedNames;
0382:            }
0383:
0384:            public void setUpdateQualifiedNames(boolean update) {
0385:                fUpdateQualifiedNames = update;
0386:            }
0387:
0388:            public String getFilePatterns() {
0389:                return fFilePatterns;
0390:            }
0391:
0392:            public void setFilePatterns(String patterns) {
0393:                Assert.isNotNull(patterns);
0394:                fFilePatterns = patterns;
0395:            }
0396:
0397:            // ---- ISimilarDeclarationUpdating
0398:
0399:            public boolean canEnableSimilarDeclarationUpdating() {
0400:
0401:                IProduct product = Platform.getProduct();
0402:                if (product != null) {
0403:                    String property = product
0404:                            .getProperty("org.eclipse.jdt.ui.refactoring.handlesSimilarDeclarations"); //$NON-NLS-1$
0405:                    if ("false".equalsIgnoreCase(property)) //$NON-NLS-1$
0406:                        return false;
0407:                }
0408:
0409:                return true;
0410:            }
0411:
0412:            public void setUpdateSimilarDeclarations(boolean update) {
0413:                fUpdateSimilarElements = update;
0414:            }
0415:
0416:            public boolean getUpdateSimilarDeclarations() {
0417:                return fUpdateSimilarElements;
0418:            }
0419:
0420:            public int getMatchStrategy() {
0421:                return fRenamingStrategy;
0422:
0423:            }
0424:
0425:            public void setMatchStrategy(int selectedStrategy) {
0426:                fRenamingStrategy = selectedStrategy;
0427:            }
0428:
0429:            /**
0430:             * @return the similar elements of the type, i.e. IFields, IMethods, and
0431:             * ILocalVariables. Returns <code>null</code> iff similar declaration updating
0432:             * is not requested.
0433:             */
0434:            public IJavaElement[] getSimilarElements() {
0435:                if (fFinalSimilarElementToName == null)
0436:                    return null;
0437:                Set keys = fFinalSimilarElementToName.keySet();
0438:                return (IJavaElement[]) keys.toArray(new IJavaElement[keys
0439:                        .size()]);
0440:            }
0441:
0442:            /**
0443:             * {@inheritDoc}
0444:             */
0445:            public IResource getRefactoredResource(IResource element) {
0446:                if (element instanceof  IFile) {
0447:                    if (Checks.isTopLevel(fType)
0448:                            && element.equals(fType.getResource()))
0449:                        return getNewCompilationUnit().getResource();
0450:                }
0451:                return element;
0452:            }
0453:
0454:            /**
0455:             * {@inheritDoc}
0456:             */
0457:            public IJavaElement getRefactoredJavaElement(IJavaElement element) {
0458:                if (element instanceof  ICompilationUnit) {
0459:                    if (Checks.isTopLevel(fType)
0460:                            && element.equals(fType.getCompilationUnit()))
0461:                        return getNewCompilationUnit();
0462:                } else if (element instanceof  IMember) {
0463:                    final IType newType = (IType) getNewElement();
0464:                    final RefactoringHandleTransplanter transplanter = new RefactoringHandleTransplanter(
0465:                            fType, newType, fFinalSimilarElementToName);
0466:                    return transplanter.transplantHandle((IMember) element);
0467:                }
0468:                return element;
0469:            }
0470:
0471:            public RefactoringStatus checkInitialConditions(IProgressMonitor pm)
0472:                    throws CoreException {
0473:                IType primary = (IType) fType.getPrimaryElement();
0474:                if (primary == null || !primary.exists()) {
0475:                    String message = Messages
0476:                            .format(
0477:                                    RefactoringCoreMessages.RenameTypeRefactoring_does_not_exist,
0478:                                    new String[] {
0479:                                            JavaModelUtil
0480:                                                    .getFullyQualifiedName(fType),
0481:                                            fType.getCompilationUnit()
0482:                                                    .getElementName() });
0483:                    return RefactoringStatus.createFatalErrorStatus(message);
0484:                }
0485:                fType = primary;
0486:                return Checks.checkIfCuBroken(fType);
0487:            }
0488:
0489:            protected RefactoringStatus doCheckFinalConditions(
0490:                    IProgressMonitor pm, CheckConditionsContext context)
0491:                    throws CoreException {
0492:                Assert.isNotNull(fType, "type"); //$NON-NLS-1$
0493:                Assert.isNotNull(getNewElementName(), "newName"); //$NON-NLS-1$
0494:                RefactoringStatus result = new RefactoringStatus();
0495:
0496:                int referenceSearchTicks = fUpdateReferences
0497:                        || fUpdateSimilarElements ? 15 : 0;
0498:                int affectedCusTicks = fUpdateReferences
0499:                        || fUpdateSimilarElements ? 10 : 1;
0500:                int similarElementTicks = fUpdateSimilarElements ? 85 : 0;
0501:                int createChangeTicks = 5;
0502:                int qualifiedNamesTicks = fUpdateQualifiedNames ? 50 : 0;
0503:
0504:                try {
0505:                    pm
0506:                            .beginTask(
0507:                                    "", 12  + referenceSearchTicks + affectedCusTicks + similarElementTicks + createChangeTicks + qualifiedNamesTicks); //$NON-NLS-1$
0508:                    pm
0509:                            .setTaskName(RefactoringCoreMessages.RenameTypeRefactoring_checking);
0510:
0511:                    fChangeManager = new TextChangeManager(true);
0512:
0513:                    result.merge(checkNewElementName(getNewElementName()));
0514:                    if (result.hasFatalError())
0515:                        return result;
0516:                    result.merge(Checks.checkIfCuBroken(fType));
0517:                    if (result.hasFatalError())
0518:                        return result;
0519:                    pm.worked(1);
0520:
0521:                    result.merge(checkTypesInCompilationUnit());
0522:                    pm.worked(1);
0523:
0524:                    result.merge(checkForMethodsWithConstructorNames());
0525:                    pm.worked(1);
0526:
0527:                    result.merge(checkImportedTypes());
0528:                    pm.worked(1);
0529:
0530:                    if (Checks.isTopLevel(fType) && (JdtFlags.isPublic(fType)))
0531:                        result.merge(Checks.checkCompilationUnitNewName(fType
0532:                                .getCompilationUnit(), getNewElementName()));
0533:                    pm.worked(1);
0534:
0535:                    if (isPrimaryType())
0536:                        result.merge(checkNewPathValidity());
0537:                    pm.worked(1);
0538:
0539:                    result.merge(checkEnclosingTypes());
0540:                    pm.worked(1);
0541:
0542:                    result.merge(checkEnclosedTypes());
0543:                    pm.worked(1);
0544:
0545:                    result.merge(checkTypesInPackage());
0546:                    pm.worked(1);
0547:
0548:                    result.merge(checkTypesImportedInCu());
0549:                    pm.worked(1);
0550:
0551:                    result.merge(Checks.checkForMainAndNativeMethods(fType));
0552:                    pm.worked(1);
0553:
0554:                    // before doing any expensive analysis
0555:                    if (result.hasFatalError())
0556:                        return result;
0557:
0558:                    result.merge(analyseEnclosedTypes());
0559:                    pm.worked(1);
0560:                    // before doing _the really_ expensive analysis
0561:                    if (result.hasFatalError())
0562:                        return result;
0563:
0564:                    // Load references, including similarly named elements
0565:                    if (fUpdateReferences || fUpdateSimilarElements) {
0566:                        pm
0567:                                .setTaskName(RefactoringCoreMessages.RenameTypeRefactoring_searching);
0568:                        result
0569:                                .merge(initializeReferences(new SubProgressMonitor(
0570:                                        pm, referenceSearchTicks)));
0571:                    } else {
0572:                        fReferences = new SearchResultGroup[0];
0573:                    }
0574:
0575:                    pm
0576:                            .setTaskName(RefactoringCoreMessages.RenameTypeRefactoring_checking);
0577:                    if (pm.isCanceled())
0578:                        throw new OperationCanceledException();
0579:
0580:                    if (fUpdateReferences || fUpdateSimilarElements) {
0581:                        result
0582:                                .merge(analyzeAffectedCompilationUnits(new SubProgressMonitor(
0583:                                        pm, affectedCusTicks)));
0584:                    } else {
0585:                        Checks.checkCompileErrorsInAffectedFile(result, fType
0586:                                .getResource());
0587:                        pm.worked(affectedCusTicks);
0588:                    }
0589:
0590:                    if (result.hasFatalError())
0591:                        return result;
0592:
0593:                    if (fUpdateSimilarElements) {
0594:                        result
0595:                                .merge(initializeSimilarElementsRenameProcessors(
0596:                                        new SubProgressMonitor(pm,
0597:                                                similarElementTicks), context));
0598:                        if (result.hasFatalError())
0599:                            return result;
0600:                    }
0601:
0602:                    createChanges(new SubProgressMonitor(pm, createChangeTicks));
0603:
0604:                    if (fUpdateQualifiedNames)
0605:                        computeQualifiedNameMatches(new SubProgressMonitor(pm,
0606:                                qualifiedNamesTicks));
0607:
0608:                    return result;
0609:                } finally {
0610:                    pm.done();
0611:                }
0612:            }
0613:
0614:            /**
0615:             * Initializes the references to the type and the similarly named elements. This
0616:             * method creates both the fReferences and the fPreloadedElementToName
0617:             * fields.
0618:             * 
0619:             * May be called from the UI.
0620:             * @param monitor 
0621:             * @return initialization status 
0622:             * @throws JavaModelException some fundamental error with the underlying model
0623:             * @throws OperationCanceledException if user canceled the task
0624:             * 
0625:             */
0626:            public RefactoringStatus initializeReferences(
0627:                    IProgressMonitor monitor) throws JavaModelException,
0628:                    OperationCanceledException {
0629:
0630:                Assert.isNotNull(fType);
0631:                Assert.isNotNull(getNewElementName());
0632:
0633:                // Do not search again if the preconditions have not changed.
0634:                // Search depends on the type, the new name, the similarly named elements, and
0635:                // the strategy
0636:
0637:                if (fReferences != null
0638:                        && (getNewElementName().equals(fCachedNewName))
0639:                        && (fCachedRenameSimilarElements == getUpdateSimilarDeclarations())
0640:                        && (fCachedRenamingStrategy == fRenamingStrategy))
0641:                    return fCachedRefactoringStatus;
0642:
0643:                fCachedNewName = getNewElementName();
0644:                fCachedRenameSimilarElements = fUpdateSimilarElements;
0645:                fCachedRenamingStrategy = fRenamingStrategy;
0646:                fCachedRefactoringStatus = new RefactoringStatus();
0647:
0648:                try {
0649:                    SearchPattern pattern = SearchPattern.createPattern(fType,
0650:                            IJavaSearchConstants.REFERENCES,
0651:                            SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE);
0652:                    fReferences = RefactoringSearchEngine.search(pattern,
0653:                            RefactoringScopeFactory.create(fType),
0654:                            new TypeOccurrenceCollector(fType), monitor,
0655:                            fCachedRefactoringStatus);
0656:                    fReferences = Checks.excludeCompilationUnits(fReferences,
0657:                            fCachedRefactoringStatus);
0658:
0659:                    fPreloadedElementToName = new LinkedHashMap();
0660:                    fPreloadedElementToSelection = new HashMap();
0661:
0662:                    final String unQualifiedTypeName = fType.getElementName();
0663:
0664:                    monitor.beginTask("", fReferences.length); //$NON-NLS-1$
0665:
0666:                    if (getUpdateSimilarDeclarations()) {
0667:
0668:                        RenamingNameSuggestor sugg = new RenamingNameSuggestor(
0669:                                fRenamingStrategy);
0670:
0671:                        for (int i = 0; i < fReferences.length; i++) {
0672:                            final ICompilationUnit cu = fReferences[i]
0673:                                    .getCompilationUnit();
0674:                            if (cu == null)
0675:                                continue;
0676:
0677:                            final SearchMatch[] results = fReferences[i]
0678:                                    .getSearchResults();
0679:
0680:                            for (int j = 0; j < results.length; j++) {
0681:
0682:                                if (!(results[j] instanceof  TypeReferenceMatch))
0683:                                    continue;
0684:
0685:                                final TypeReferenceMatch match = (TypeReferenceMatch) results[j];
0686:                                final List matches = new ArrayList();
0687:
0688:                                if (match.getLocalElement() != null)
0689:                                    matches.add(match.getLocalElement());
0690:                                else
0691:                                    matches.add(match.getElement());
0692:
0693:                                final IJavaElement[] others = match
0694:                                        .getOtherElements();
0695:                                if (others != null)
0696:                                    matches.addAll(Arrays.asList(others));
0697:
0698:                                for (Iterator iter = matches.iterator(); iter
0699:                                        .hasNext();) {
0700:                                    final IJavaElement element = (IJavaElement) iter
0701:                                            .next();
0702:
0703:                                    if (!(element instanceof  IMethod)
0704:                                            && !(element instanceof  IField)
0705:                                            && !(element instanceof  ILocalVariable))
0706:                                        continue;
0707:
0708:                                    if (!isInDeclaredType(match.getOffset(),
0709:                                            element))
0710:                                        continue;
0711:
0712:                                    if (element instanceof  IField) {
0713:                                        final IField currentField = (IField) element;
0714:                                        final String newFieldName = sugg
0715:                                                .suggestNewFieldName(
0716:                                                        currentField
0717:                                                                .getJavaProject(),
0718:                                                        currentField
0719:                                                                .getElementName(),
0720:                                                        Flags
0721:                                                                .isStatic(currentField
0722:                                                                        .getFlags()),
0723:                                                        unQualifiedTypeName,
0724:                                                        getNewElementName());
0725:
0726:                                        if (newFieldName != null)
0727:                                            fPreloadedElementToName.put(
0728:                                                    currentField, newFieldName);
0729:                                    }
0730:
0731:                                    if (element instanceof  IMethod) {
0732:                                        final IMethod currentMethod = (IMethod) element;
0733:                                        addMethodRename(unQualifiedTypeName,
0734:                                                sugg, currentMethod);
0735:                                    }
0736:
0737:                                    if (element instanceof  ILocalVariable) {
0738:                                        final ILocalVariable currentLocal = (ILocalVariable) element;
0739:                                        final boolean isParameter;
0740:
0741:                                        if (JavaModelUtil
0742:                                                .isParameter(currentLocal)) {
0743:                                            addMethodRename(
0744:                                                    unQualifiedTypeName, sugg,
0745:                                                    (IMethod) currentLocal
0746:                                                            .getParent());
0747:                                            isParameter = true;
0748:                                        } else
0749:                                            isParameter = false;
0750:
0751:                                        final String newLocalName = sugg
0752:                                                .suggestNewLocalName(
0753:                                                        currentLocal
0754:                                                                .getJavaProject(),
0755:                                                        currentLocal
0756:                                                                .getElementName(),
0757:                                                        isParameter,
0758:                                                        unQualifiedTypeName,
0759:                                                        getNewElementName());
0760:
0761:                                        if (newLocalName != null)
0762:                                            fPreloadedElementToName.put(
0763:                                                    currentLocal, newLocalName);
0764:                                    }
0765:                                }
0766:                            }
0767:                            if (monitor.isCanceled())
0768:                                throw new OperationCanceledException();
0769:                        }
0770:                    }
0771:
0772:                    for (Iterator iter = fPreloadedElementToName.keySet()
0773:                            .iterator(); iter.hasNext();) {
0774:                        IJavaElement element = (IJavaElement) iter.next();
0775:                        fPreloadedElementToSelection.put(element, Boolean.TRUE);
0776:                    }
0777:                    fPreloadedElementToNameDefault = (LinkedHashMap) fPreloadedElementToName
0778:                            .clone();
0779:
0780:                } catch (OperationCanceledException e) {
0781:                    fReferences = null;
0782:                    fPreloadedElementToName = null;
0783:                    throw new OperationCanceledException();
0784:                }
0785:                return fCachedRefactoringStatus;
0786:            }
0787:
0788:            /**
0789:             * @param matchOffset 
0790:             * @param parentElement 
0791:             * @return true iff the given search match offset (must be a match of a type
0792:             * reference) lies before the element name of its enclosing java element,
0793:             * false if not. In other words: If this method returns true, the match is
0794:             * the declared type (or return type) of the enclosing element.
0795:             * @throws JavaModelException 
0796:             * 
0797:             */
0798:            private boolean isInDeclaredType(int matchOffset,
0799:                    IJavaElement parentElement) throws JavaModelException {
0800:                if (parentElement != null) {
0801:                    int enclosingNameOffset = 0;
0802:                    if (parentElement instanceof  IMethod
0803:                            || parentElement instanceof  IField)
0804:                        enclosingNameOffset = ((IMember) parentElement)
0805:                                .getNameRange().getOffset();
0806:                    else if (parentElement instanceof  ILocalVariable)
0807:                        enclosingNameOffset = ((ILocalVariable) parentElement)
0808:                                .getNameRange().getOffset();
0809:
0810:                    return (matchOffset < enclosingNameOffset);
0811:                }
0812:                return false;
0813:            }
0814:
0815:            private void addMethodRename(final String unQualifiedTypeName,
0816:                    RenamingNameSuggestor sugg, final IMethod currentMethod)
0817:                    throws JavaModelException {
0818:                if (!currentMethod.isConstructor()) {
0819:                    final String newMethodName = sugg.suggestNewMethodName(
0820:                            currentMethod.getElementName(),
0821:                            unQualifiedTypeName, getNewElementName());
0822:
0823:                    if (newMethodName != null)
0824:                        fPreloadedElementToName.put(currentMethod,
0825:                                newMethodName);
0826:                }
0827:            }
0828:
0829:            private RefactoringStatus checkNewPathValidity() {
0830:                IContainer c = fType.getCompilationUnit().getResource()
0831:                        .getParent();
0832:
0833:                String notRename = RefactoringCoreMessages.RenameTypeRefactoring_will_not_rename;
0834:                IStatus status = c.getWorkspace().validateName(
0835:                        getNewElementName(), IResource.FILE);
0836:                if (status.getSeverity() == IStatus.ERROR)
0837:                    return RefactoringStatus.createWarningStatus(status
0838:                            .getMessage()
0839:                            + ". " + notRename); //$NON-NLS-1$
0840:
0841:                status = c.getWorkspace().validatePath(
0842:                        createNewPath(getNewElementName()), IResource.FILE);
0843:                if (status.getSeverity() == IStatus.ERROR)
0844:                    return RefactoringStatus.createWarningStatus(status
0845:                            .getMessage()
0846:                            + ". " + notRename); //$NON-NLS-1$
0847:
0848:                return new RefactoringStatus();
0849:            }
0850:
0851:            private String createNewPath(String newName) {
0852:                return fType.getCompilationUnit().getResource().getFullPath()
0853:                        .removeLastSegments(1).append(newName).toString();
0854:            }
0855:
0856:            private RefactoringStatus checkTypesImportedInCu()
0857:                    throws CoreException {
0858:                IImportDeclaration imp = getImportedType(fType
0859:                        .getCompilationUnit(), getNewElementName());
0860:
0861:                if (imp == null)
0862:                    return null;
0863:
0864:                String msg = Messages.format(
0865:                        RefactoringCoreMessages.RenameTypeRefactoring_imported,
0866:                        new Object[] {
0867:                                getNewElementName(),
0868:                                fType.getCompilationUnit().getResource()
0869:                                        .getFullPath() });
0870:                IJavaElement grandParent = imp.getParent().getParent();
0871:                if (grandParent instanceof  ICompilationUnit)
0872:                    return RefactoringStatus.createErrorStatus(msg,
0873:                            JavaStatusContext.create(imp));
0874:
0875:                return null;
0876:            }
0877:
0878:            private RefactoringStatus checkTypesInPackage()
0879:                    throws CoreException {
0880:                IType type = Checks.findTypeInPackage(fType
0881:                        .getPackageFragment(), getNewElementName());
0882:                if (type == null || !type.exists())
0883:                    return null;
0884:                String msg = Messages.format(
0885:                        RefactoringCoreMessages.RenameTypeRefactoring_exists,
0886:                        new String[] { getNewElementName(),
0887:                                fType.getPackageFragment().getElementName() });
0888:                return RefactoringStatus.createErrorStatus(msg,
0889:                        JavaStatusContext.create(type));
0890:            }
0891:
0892:            private RefactoringStatus checkEnclosedTypes() throws CoreException {
0893:                IType enclosedType = findEnclosedType(fType,
0894:                        getNewElementName());
0895:                if (enclosedType == null)
0896:                    return null;
0897:                String msg = Messages.format(
0898:                        RefactoringCoreMessages.RenameTypeRefactoring_encloses,
0899:                        new String[] {
0900:                                JavaModelUtil.getFullyQualifiedName(fType),
0901:                                getNewElementName() });
0902:                return RefactoringStatus.createErrorStatus(msg,
0903:                        JavaStatusContext.create(enclosedType));
0904:            }
0905:
0906:            private RefactoringStatus checkEnclosingTypes() {
0907:                IType enclosingType = findEnclosingType(fType,
0908:                        getNewElementName());
0909:                if (enclosingType == null)
0910:                    return null;
0911:
0912:                String msg = Messages.format(
0913:                        RefactoringCoreMessages.RenameTypeRefactoring_enclosed,
0914:                        new String[] {
0915:                                JavaModelUtil.getFullyQualifiedName(fType),
0916:                                getNewElementName() });
0917:                return RefactoringStatus.createErrorStatus(msg,
0918:                        JavaStatusContext.create(enclosingType));
0919:            }
0920:
0921:            private static IType findEnclosedType(IType type, String newName)
0922:                    throws CoreException {
0923:                IType[] enclosedTypes = type.getTypes();
0924:                for (int i = 0; i < enclosedTypes.length; i++) {
0925:                    if (newName.equals(enclosedTypes[i].getElementName())
0926:                            || findEnclosedType(enclosedTypes[i], newName) != null)
0927:                        return enclosedTypes[i];
0928:                }
0929:                return null;
0930:            }
0931:
0932:            private static IType findEnclosingType(IType type, String newName) {
0933:                IType enclosing = type.getDeclaringType();
0934:                while (enclosing != null) {
0935:                    if (newName.equals(enclosing.getElementName()))
0936:                        return enclosing;
0937:                    else
0938:                        enclosing = enclosing.getDeclaringType();
0939:                }
0940:                return null;
0941:            }
0942:
0943:            private static IImportDeclaration getImportedType(
0944:                    ICompilationUnit cu, String typeName) throws CoreException {
0945:                IImportDeclaration[] imports = cu.getImports();
0946:                String dotTypeName = "." + typeName; //$NON-NLS-1$
0947:                for (int i = 0; i < imports.length; i++) {
0948:                    if (imports[i].getElementName().endsWith(dotTypeName))
0949:                        return imports[i];
0950:                }
0951:                return null;
0952:            }
0953:
0954:            private RefactoringStatus checkForMethodsWithConstructorNames()
0955:                    throws CoreException {
0956:                IMethod[] methods = fType.getMethods();
0957:                for (int i = 0; i < methods.length; i++) {
0958:                    if (methods[i].isConstructor())
0959:                        continue;
0960:                    RefactoringStatus check = Checks.checkIfConstructorName(
0961:                            methods[i], methods[i].getElementName(),
0962:                            getNewElementName());
0963:                    if (check != null)
0964:                        return check;
0965:                }
0966:                return null;
0967:            }
0968:
0969:            private RefactoringStatus checkImportedTypes() throws CoreException {
0970:                RefactoringStatus result = new RefactoringStatus();
0971:                IImportDeclaration[] imports = fType.getCompilationUnit()
0972:                        .getImports();
0973:                for (int i = 0; i < imports.length; i++)
0974:                    analyzeImportDeclaration(imports[i], result);
0975:                return result;
0976:            }
0977:
0978:            private RefactoringStatus checkTypesInCompilationUnit() {
0979:                RefactoringStatus result = new RefactoringStatus();
0980:                if (!Checks.isTopLevel(fType)) { //the other case checked in checkTypesInPackage
0981:                    IType siblingType = fType.getDeclaringType().getType(
0982:                            getNewElementName());
0983:                    if (siblingType.exists()) {
0984:                        String msg = Messages
0985:                                .format(
0986:                                        RefactoringCoreMessages.RenameTypeRefactoring_member_type_exists,
0987:                                        new String[] {
0988:                                                getNewElementName(),
0989:                                                JavaModelUtil
0990:                                                        .getFullyQualifiedName(fType
0991:                                                                .getDeclaringType()) });
0992:                        result.addError(msg, JavaStatusContext
0993:                                .create(siblingType));
0994:                    }
0995:                }
0996:                return result;
0997:            }
0998:
0999:            private RefactoringStatus analyseEnclosedTypes()
1000:                    throws CoreException {
1001:                final ISourceRange typeRange = fType.getSourceRange();
1002:                final RefactoringStatus result = new RefactoringStatus();
1003:                CompilationUnit cuNode = new RefactoringASTParser(AST.JLS3)
1004:                        .parse(fType.getCompilationUnit(), false);
1005:                cuNode.accept(new ASTVisitor() {
1006:
1007:                    public boolean visit(TypeDeclaration node) { // enums and annotations can't be local
1008:                        if (node.getStartPosition() <= typeRange.getOffset())
1009:                            return true;
1010:                        if (node.getStartPosition() > typeRange.getOffset()
1011:                                + typeRange.getLength())
1012:                            return true;
1013:
1014:                        if (getNewElementName().equals(
1015:                                node.getName().getIdentifier())) {
1016:                            RefactoringStatusContext context = JavaStatusContext
1017:                                    .create(fType.getCompilationUnit(), node);
1018:                            String msg = null;
1019:                            if (node.isLocalTypeDeclaration()) {
1020:                                msg = Messages
1021:                                        .format(
1022:                                                RefactoringCoreMessages.RenameTypeRefactoring_local_type,
1023:                                                new String[] {
1024:                                                        JavaElementUtil
1025:                                                                .createSignature(fType),
1026:                                                        getNewElementName() });
1027:                            } else if (node.isMemberTypeDeclaration()) {
1028:                                msg = Messages
1029:                                        .format(
1030:                                                RefactoringCoreMessages.RenameTypeRefactoring_member_type,
1031:                                                new String[] {
1032:                                                        JavaElementUtil
1033:                                                                .createSignature(fType),
1034:                                                        getNewElementName() });
1035:                            }
1036:                            if (msg != null)
1037:                                result.addError(msg, context);
1038:                        }
1039:
1040:                        MethodDeclaration[] methods = node.getMethods();
1041:                        for (int i = 0; i < methods.length; i++) {
1042:                            if (Modifier.isNative(methods[i].getModifiers())) {
1043:                                RefactoringStatusContext context = JavaStatusContext
1044:                                        .create(fType.getCompilationUnit(),
1045:                                                methods[i]);
1046:                                String msg = Messages
1047:                                        .format(
1048:                                                RefactoringCoreMessages.RenameTypeRefactoring_enclosed_type_native,
1049:                                                node.getName().getIdentifier());
1050:                                result.addWarning(msg, context);
1051:                            }
1052:                        }
1053:                        return true;
1054:                    }
1055:                });
1056:                return result;
1057:            }
1058:
1059:            private static ICompilationUnit getCompilationUnit(
1060:                    IImportDeclaration imp) {
1061:                return (ICompilationUnit) imp.getParent().getParent();
1062:            }
1063:
1064:            private void analyzeImportedTypes(IType[] types,
1065:                    RefactoringStatus result, IImportDeclaration imp)
1066:                    throws CoreException {
1067:                for (int i = 0; i < types.length; i++) {
1068:                    //could this be a problem (same package imports)?
1069:                    if (JdtFlags.isPublic(types[i])
1070:                            && types[i].getElementName().equals(
1071:                                    getNewElementName())) {
1072:                        String msg = Messages
1073:                                .format(
1074:                                        RefactoringCoreMessages.RenameTypeRefactoring_name_conflict1,
1075:                                        new Object[] {
1076:                                                JavaModelUtil
1077:                                                        .getFullyQualifiedName(types[i]),
1078:                                                getFullPath(getCompilationUnit(imp)) });
1079:                        result.addError(msg, JavaStatusContext.create(imp));
1080:                    }
1081:                }
1082:            }
1083:
1084:            private static IJavaElement convertFromImportDeclaration(
1085:                    IImportDeclaration declaration) throws CoreException {
1086:                if (declaration.isOnDemand()) {
1087:                    String packageName = declaration.getElementName()
1088:                            .substring(0,
1089:                                    declaration.getElementName().length() - 2);
1090:                    return JavaModelUtil.findTypeContainer(declaration
1091:                            .getJavaProject(), packageName);
1092:                } else
1093:                    return JavaModelUtil.findTypeContainer(declaration
1094:                            .getJavaProject(), declaration.getElementName());
1095:            }
1096:
1097:            private void analyzeImportDeclaration(IImportDeclaration imp,
1098:                    RefactoringStatus result) throws CoreException {
1099:                if (!imp.isOnDemand())
1100:                    return; //analyzed earlier
1101:
1102:                IJavaElement imported = convertFromImportDeclaration(imp);
1103:                if (imported == null)
1104:                    return;
1105:
1106:                if (imported instanceof  IPackageFragment) {
1107:                    ICompilationUnit[] cus = ((IPackageFragment) imported)
1108:                            .getCompilationUnits();
1109:                    for (int i = 0; i < cus.length; i++) {
1110:                        analyzeImportedTypes(cus[i].getTypes(), result, imp);
1111:                    }
1112:                } else {
1113:                    //cast safe: see JavaModelUtility.convertFromImportDeclaration
1114:                    analyzeImportedTypes(((IType) imported).getTypes(), result,
1115:                            imp);
1116:                }
1117:            }
1118:
1119:            /*
1120:             * Analyzes all compilation units in which type is referenced
1121:             */
1122:            private RefactoringStatus analyzeAffectedCompilationUnits(
1123:                    IProgressMonitor pm) throws CoreException {
1124:                RefactoringStatus result = new RefactoringStatus();
1125:
1126:                result.merge(Checks.checkCompileErrorsInAffectedFiles(
1127:                        fReferences, fType.getResource()));
1128:
1129:                pm.beginTask("", fReferences.length); //$NON-NLS-1$
1130:                result.merge(checkConflictingTypes(pm));
1131:                return result;
1132:            }
1133:
1134:            private RefactoringStatus checkConflictingTypes(IProgressMonitor pm)
1135:                    throws CoreException {
1136:                RefactoringStatus result = new RefactoringStatus();
1137:                IJavaSearchScope scope = RefactoringScopeFactory.create(fType);
1138:                SearchPattern pattern = SearchPattern.createPattern(
1139:                        getNewElementName(), IJavaSearchConstants.TYPE,
1140:                        IJavaSearchConstants.ALL_OCCURRENCES,
1141:                        SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE);
1142:                ICompilationUnit[] cusWithReferencesToConflictingTypes = RefactoringSearchEngine
1143:                        .findAffectedCompilationUnits(pattern, scope, pm,
1144:                                result);
1145:                if (cusWithReferencesToConflictingTypes.length == 0)
1146:                    return result;
1147:                ICompilationUnit[] cusWithReferencesToRenamedType = getCus(fReferences);
1148:
1149:                ICompilationUnit[] intersection = isIntersectionEmpty(
1150:                        cusWithReferencesToRenamedType,
1151:                        cusWithReferencesToConflictingTypes);
1152:                if (intersection.length == 0)
1153:                    return result;
1154:
1155:                for (int i = 0; i < intersection.length; i++) {
1156:                    RefactoringStatusContext context = JavaStatusContext
1157:                            .create(intersection[i]);
1158:                    String message = Messages
1159:                            .format(
1160:                                    RefactoringCoreMessages.RenameTypeRefactoring_another_type,
1161:                                    new String[] { getNewElementName(),
1162:                                            intersection[i].getElementName() });
1163:                    result.addError(message, context);
1164:                }
1165:                return result;
1166:            }
1167:
1168:            private static ICompilationUnit[] isIntersectionEmpty(
1169:                    ICompilationUnit[] a1, ICompilationUnit[] a2) {
1170:                Set set1 = new HashSet(Arrays.asList(a1));
1171:                Set set2 = new HashSet(Arrays.asList(a2));
1172:                set1.retainAll(set2);
1173:                return (ICompilationUnit[]) set1
1174:                        .toArray(new ICompilationUnit[set1.size()]);
1175:            }
1176:
1177:            private static ICompilationUnit[] getCus(
1178:                    SearchResultGroup[] searchResultGroups) {
1179:                List cus = new ArrayList(searchResultGroups.length);
1180:                for (int i = 0; i < searchResultGroups.length; i++) {
1181:                    ICompilationUnit cu = searchResultGroups[i]
1182:                            .getCompilationUnit();
1183:                    if (cu != null)
1184:                        cus.add(cu);
1185:                }
1186:                return (ICompilationUnit[]) cus
1187:                        .toArray(new ICompilationUnit[cus.size()]);
1188:            }
1189:
1190:            private static String getFullPath(ICompilationUnit cu) {
1191:                Assert.isTrue(cu.exists());
1192:                return cu.getResource().getFullPath().toString();
1193:            }
1194:
1195:            public Change createChange(IProgressMonitor monitor)
1196:                    throws CoreException {
1197:                try {
1198:                    monitor
1199:                            .beginTask(
1200:                                    RefactoringCoreMessages.RenameTypeRefactoring_creating_change,
1201:                                    4);
1202:                    String project = null;
1203:                    IJavaProject javaProject = fType.getJavaProject();
1204:                    if (javaProject != null)
1205:                        project = javaProject.getElementName();
1206:                    int flags = JavaRefactoringDescriptor.JAR_MIGRATION
1207:                            | JavaRefactoringDescriptor.JAR_REFACTORING
1208:                            | RefactoringDescriptor.STRUCTURAL_CHANGE;
1209:                    try {
1210:                        if (!Flags.isPrivate(fType.getFlags()))
1211:                            flags |= RefactoringDescriptor.MULTI_CHANGE;
1212:                        if (fType.isAnonymous() || fType.isLocal())
1213:                            flags |= JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT;
1214:                    } catch (JavaModelException exception) {
1215:                        JavaPlugin.log(exception);
1216:                    }
1217:                    final String description = Messages
1218:                            .format(
1219:                                    RefactoringCoreMessages.RenameTypeProcessor_descriptor_description_short,
1220:                                    fType.getElementName());
1221:                    final String header = Messages
1222:                            .format(
1223:                                    RefactoringCoreMessages.RenameTypeProcessor_descriptor_description,
1224:                                    new String[] {
1225:                                            JavaElementLabels
1226:                                                    .getElementLabel(
1227:                                                            fType,
1228:                                                            JavaElementLabels.ALL_FULLY_QUALIFIED),
1229:                                            getNewElementName() });
1230:                    final String comment = new JDTRefactoringDescriptorComment(
1231:                            project, this , header).asString();
1232:                    final RenameJavaElementDescriptor descriptor = new RenameJavaElementDescriptor(
1233:                            IJavaRefactorings.RENAME_TYPE);
1234:                    descriptor.setProject(project);
1235:                    descriptor.setDescription(description);
1236:                    descriptor.setComment(comment);
1237:                    descriptor.setFlags(flags);
1238:                    descriptor.setJavaElement(fType);
1239:                    descriptor.setNewName(getNewElementName());
1240:                    descriptor.setUpdateQualifiedNames(fUpdateQualifiedNames);
1241:                    descriptor
1242:                            .setUpdateTextualOccurrences(fUpdateTextualMatches);
1243:                    descriptor.setUpdateReferences(fUpdateReferences);
1244:                    if (fUpdateQualifiedNames && fFilePatterns != null
1245:                            && !"".equals(fFilePatterns)) //$NON-NLS-1$
1246:                        descriptor.setFileNamePatterns(fFilePatterns);
1247:                    descriptor
1248:                            .setUpdateSimilarDeclarations(fUpdateSimilarElements);
1249:                    descriptor.setMatchStrategy(fRenamingStrategy);
1250:                    final DynamicValidationRefactoringChange result = new DynamicValidationRefactoringChange(
1251:                            descriptor,
1252:                            RefactoringCoreMessages.RenameTypeProcessor_change_name);
1253:
1254:                    if (fChangeManager.containsChangesIn(fType
1255:                            .getCompilationUnit())) {
1256:                        TextChange textChange = fChangeManager.get(fType
1257:                                .getCompilationUnit());
1258:                        if (textChange instanceof  TextFileChange) {
1259:                            ((TextFileChange) textChange)
1260:                                    .setSaveMode(TextFileChange.FORCE_SAVE);
1261:                        }
1262:                    }
1263:                    result.addAll(fChangeManager.getAllChanges());
1264:                    if (willRenameCU()) {
1265:                        IResource resource = fType.getCompilationUnit()
1266:                                .getResource();
1267:                        if (resource != null && resource.isLinked()) {
1268:                            String ext = resource.getFileExtension();
1269:                            String renamedResourceName;
1270:                            if (ext == null)
1271:                                renamedResourceName = getNewElementName();
1272:                            else
1273:                                renamedResourceName = getNewElementName() + '.'
1274:                                        + ext;
1275:                            result.add(new RenameResourceChange(null, fType
1276:                                    .getCompilationUnit().getResource(),
1277:                                    renamedResourceName, comment));
1278:                        } else {
1279:                            String renamedCUName = JavaModelUtil
1280:                                    .getRenamedCUName(fType
1281:                                            .getCompilationUnit(),
1282:                                            getNewElementName());
1283:                            result.add(new RenameCompilationUnitChange(fType
1284:                                    .getCompilationUnit(), renamedCUName));
1285:                        }
1286:                    }
1287:                    monitor.worked(1);
1288:                    return result;
1289:                } finally {
1290:                    fChangeManager = null;
1291:                }
1292:            }
1293:
1294:            public Change postCreateChange(Change[] participantChanges,
1295:                    IProgressMonitor pm) throws CoreException {
1296:                if (fQualifiedNameSearchResult != null) {
1297:                    try {
1298:                        return fQualifiedNameSearchResult
1299:                                .getSingleChange(Changes
1300:                                        .getModifiedFiles(participantChanges));
1301:                    } finally {
1302:                        fQualifiedNameSearchResult = null;
1303:                    }
1304:                } else {
1305:                    return null;
1306:                }
1307:            }
1308:
1309:            private boolean willRenameCU() throws CoreException {
1310:                String name = JavaCore.removeJavaLikeExtension(fType
1311:                        .getCompilationUnit().getElementName());
1312:                if (!(Checks.isTopLevel(fType) && name.equals(fType
1313:                        .getElementName())))
1314:                    return false;
1315:                if (!checkNewPathValidity().isOK())
1316:                    return false;
1317:                if (!Checks.checkCompilationUnitNewName(
1318:                        fType.getCompilationUnit(), getNewElementName()).isOK())
1319:                    return false;
1320:                return true;
1321:            }
1322:
1323:            private void createChanges(IProgressMonitor pm)
1324:                    throws CoreException {
1325:                try {
1326:                    pm.beginTask("", 12); //$NON-NLS-1$
1327:                    pm
1328:                            .setTaskName(RefactoringCoreMessages.RenameTypeProcessor_creating_changes);
1329:
1330:                    if (fUpdateReferences)
1331:                        addReferenceUpdates(fChangeManager,
1332:                                new SubProgressMonitor(pm, 3));
1333:
1334:                    // Similar names updates have already been added.
1335:
1336:                    pm.worked(1);
1337:
1338:                    IResource resource = fType.getCompilationUnit()
1339:                            .getResource();
1340:                    // if we have a linked resource then we don't use CU renaming 
1341:                    // directly. So we have to update the code by ourselves.
1342:                    if ((resource != null && resource.isLinked())
1343:                            || !willRenameCU()) {
1344:                        addTypeDeclarationUpdate(fChangeManager);
1345:                        pm.worked(1);
1346:
1347:                        addConstructorRenames(fChangeManager);
1348:                        pm.worked(1);
1349:                    } else {
1350:                        pm.worked(2);
1351:                    }
1352:
1353:                    if (fUpdateTextualMatches) {
1354:                        pm
1355:                                .subTask(RefactoringCoreMessages.RenameTypeRefactoring_searching_text);
1356:                        TextMatchUpdater.perform(new SubProgressMonitor(pm, 1),
1357:                                RefactoringScopeFactory.create(fType), this ,
1358:                                fChangeManager, fReferences);
1359:                        if (fUpdateSimilarElements)
1360:                            addSimilarElementsTextualUpdates(fChangeManager,
1361:                                    new SubProgressMonitor(pm, 3));
1362:                    }
1363:
1364:                } finally {
1365:                    pm.done();
1366:                }
1367:            }
1368:
1369:            private void addTypeDeclarationUpdate(TextChangeManager manager)
1370:                    throws CoreException {
1371:                String name = RefactoringCoreMessages.RenameTypeRefactoring_update;
1372:                int typeNameLength = fType.getElementName().length();
1373:                ICompilationUnit cu = fType.getCompilationUnit();
1374:                TextChangeCompatibility.addTextEdit(manager.get(cu), name,
1375:                        new ReplaceEdit(fType.getNameRange().getOffset(),
1376:                                typeNameLength, getNewElementName()));
1377:            }
1378:
1379:            private void addConstructorRenames(TextChangeManager manager)
1380:                    throws CoreException {
1381:                ICompilationUnit cu = fType.getCompilationUnit();
1382:                IMethod[] methods = fType.getMethods();
1383:                int typeNameLength = fType.getElementName().length();
1384:                for (int i = 0; i < methods.length; i++) {
1385:                    if (methods[i].isConstructor()) {
1386:                        /*
1387:                         * constructor declarations cannot be fully qualified so we can use simple replace here
1388:                         *
1389:                         * if (methods[i].getNameRange() == null), then it's a binary file so it's wrong anyway 
1390:                         * (checked as a precondition)
1391:                         */
1392:                        String name = RefactoringCoreMessages.RenameTypeRefactoring_rename_constructor;
1393:                        TextChangeCompatibility.addTextEdit(manager.get(cu),
1394:                                name, new ReplaceEdit(methods[i].getNameRange()
1395:                                        .getOffset(), typeNameLength,
1396:                                        getNewElementName()));
1397:                    }
1398:                }
1399:            }
1400:
1401:            private void addReferenceUpdates(TextChangeManager manager,
1402:                    IProgressMonitor pm) {
1403:                pm.beginTask("", fReferences.length); //$NON-NLS-1$
1404:                for (int i = 0; i < fReferences.length; i++) {
1405:                    ICompilationUnit cu = fReferences[i].getCompilationUnit();
1406:                    if (cu == null)
1407:                        continue;
1408:
1409:                    String name = RefactoringCoreMessages.RenameTypeRefactoring_update_reference;
1410:                    SearchMatch[] results = fReferences[i].getSearchResults();
1411:
1412:                    for (int j = 0; j < results.length; j++) {
1413:                        SearchMatch match = results[j];
1414:                        ReplaceEdit replaceEdit = new ReplaceEdit(match
1415:                                .getOffset(), match.getLength(),
1416:                                getNewElementName());
1417:                        TextChangeCompatibility.addTextEdit(manager.get(cu),
1418:                                name, replaceEdit, CATEGORY_TYPE_RENAME);
1419:                    }
1420:                    pm.worked(1);
1421:                }
1422:            }
1423:
1424:            private void computeQualifiedNameMatches(IProgressMonitor pm)
1425:                    throws CoreException {
1426:                IPackageFragment fragment = fType.getPackageFragment();
1427:                if (fQualifiedNameSearchResult == null)
1428:                    fQualifiedNameSearchResult = new QualifiedNameSearchResult();
1429:                QualifiedNameFinder.process(fQualifiedNameSearchResult, fType
1430:                        .getFullyQualifiedName(), fragment.getElementName()
1431:                        + "." + getNewElementName(), //$NON-NLS-1$
1432:                        fFilePatterns, fType.getJavaProject().getProject(), pm);
1433:            }
1434:
1435:            public RefactoringStatus initialize(RefactoringArguments arguments) {
1436:                if (arguments instanceof  JavaRefactoringArguments) {
1437:                    final JavaRefactoringArguments extended = (JavaRefactoringArguments) arguments;
1438:                    final String handle = extended
1439:                            .getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT);
1440:                    if (handle != null) {
1441:                        final IJavaElement element = JavaRefactoringDescriptorUtil
1442:                                .handleToElement(extended.getProject(), handle,
1443:                                        false);
1444:                        if (element == null
1445:                                || !element.exists()
1446:                                || element.getElementType() != IJavaElement.TYPE)
1447:                            return ScriptableRefactoring
1448:                                    .createInputFatalStatus(element,
1449:                                            getRefactoring().getName(),
1450:                                            IJavaRefactorings.RENAME_TYPE);
1451:                        else
1452:                            fType = (IType) element;
1453:                    } else
1454:                        return RefactoringStatus
1455:                                .createFatalErrorStatus(Messages
1456:                                        .format(
1457:                                                RefactoringCoreMessages.InitializableRefactoring_argument_not_exist,
1458:                                                JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT));
1459:                    final String name = extended
1460:                            .getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME);
1461:                    if (name != null && !"".equals(name)) //$NON-NLS-1$
1462:                        setNewElementName(name);
1463:                    else
1464:                        return RefactoringStatus
1465:                                .createFatalErrorStatus(Messages
1466:                                        .format(
1467:                                                RefactoringCoreMessages.InitializableRefactoring_argument_not_exist,
1468:                                                JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME));
1469:                    final String patterns = extended
1470:                            .getAttribute(ATTRIBUTE_PATTERNS);
1471:                    if (patterns != null && !"".equals(patterns)) //$NON-NLS-1$
1472:                        fFilePatterns = patterns;
1473:                    final String references = extended
1474:                            .getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_REFERENCES);
1475:                    if (references != null) {
1476:                        fUpdateReferences = Boolean.valueOf(references)
1477:                                .booleanValue();
1478:                    } else
1479:                        return RefactoringStatus
1480:                                .createFatalErrorStatus(Messages
1481:                                        .format(
1482:                                                RefactoringCoreMessages.InitializableRefactoring_argument_not_exist,
1483:                                                JavaRefactoringDescriptorUtil.ATTRIBUTE_REFERENCES));
1484:                    final String matches = extended
1485:                            .getAttribute(ATTRIBUTE_TEXTUAL_MATCHES);
1486:                    if (matches != null) {
1487:                        fUpdateTextualMatches = Boolean.valueOf(matches)
1488:                                .booleanValue();
1489:                    } else
1490:                        return RefactoringStatus
1491:                                .createFatalErrorStatus(Messages
1492:                                        .format(
1493:                                                RefactoringCoreMessages.InitializableRefactoring_argument_not_exist,
1494:                                                ATTRIBUTE_TEXTUAL_MATCHES));
1495:                    final String qualified = extended
1496:                            .getAttribute(ATTRIBUTE_QUALIFIED);
1497:                    if (qualified != null) {
1498:                        fUpdateQualifiedNames = Boolean.valueOf(qualified)
1499:                                .booleanValue();
1500:                    } else
1501:                        return RefactoringStatus
1502:                                .createFatalErrorStatus(Messages
1503:                                        .format(
1504:                                                RefactoringCoreMessages.InitializableRefactoring_argument_not_exist,
1505:                                                ATTRIBUTE_QUALIFIED));
1506:                    final String similarDeclarations = extended
1507:                            .getAttribute(ATTRIBUTE_SIMILAR_DECLARATIONS);
1508:                    if (similarDeclarations != null)
1509:                        fUpdateSimilarElements = Boolean.valueOf(
1510:                                similarDeclarations).booleanValue();
1511:                    else
1512:                        return RefactoringStatus
1513:                                .createFatalErrorStatus(Messages
1514:                                        .format(
1515:                                                RefactoringCoreMessages.InitializableRefactoring_argument_not_exist,
1516:                                                ATTRIBUTE_SIMILAR_DECLARATIONS));
1517:                    final String similarDeclarationsMatchingStrategy = extended
1518:                            .getAttribute(ATTRIBUTE_MATCHING_STRATEGY);
1519:                    if (similarDeclarationsMatchingStrategy != null) {
1520:                        try {
1521:                            fRenamingStrategy = Integer.valueOf(
1522:                                    similarDeclarationsMatchingStrategy)
1523:                                    .intValue();
1524:                        } catch (NumberFormatException e) {
1525:                            return RefactoringStatus
1526:                                    .createFatalErrorStatus(Messages
1527:                                            .format(
1528:                                                    RefactoringCoreMessages.InitializableRefactoring_illegal_argument,
1529:                                                    new String[] {
1530:                                                            similarDeclarationsMatchingStrategy,
1531:                                                            ATTRIBUTE_QUALIFIED }));
1532:                        }
1533:                    } else
1534:                        return RefactoringStatus
1535:                                .createFatalErrorStatus(Messages
1536:                                        .format(
1537:                                                RefactoringCoreMessages.InitializableRefactoring_argument_not_exist,
1538:                                                ATTRIBUTE_MATCHING_STRATEGY));
1539:                } else
1540:                    return RefactoringStatus
1541:                            .createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments);
1542:                return new RefactoringStatus();
1543:            }
1544:
1545:            // --------- Similar names
1546:
1547:            /**
1548:             * Creates and initializes the refactoring processors for similarly named elements
1549:             * @param progressMonitor 
1550:             * @param context 
1551:             * @return status
1552:             * @throws CoreException 
1553:             */
1554:            private RefactoringStatus initializeSimilarElementsRenameProcessors(
1555:                    IProgressMonitor progressMonitor,
1556:                    CheckConditionsContext context) throws CoreException {
1557:
1558:                Assert.isNotNull(fPreloadedElementToName);
1559:                Assert.isNotNull(fPreloadedElementToSelection);
1560:
1561:                final RefactoringStatus status = new RefactoringStatus();
1562:                final Set handledTopLevelMethods = new HashSet();
1563:                final Set warnings = new HashSet();
1564:                final List processors = new ArrayList();
1565:                fFinalSimilarElementToName = new HashMap();
1566:
1567:                CompilationUnit currentResolvedCU = null;
1568:                ICompilationUnit currentCU = null;
1569:
1570:                int current = 0;
1571:                final int max = fPreloadedElementToName.size();
1572:
1573:                progressMonitor.beginTask("", max * 3); //$NON-NLS-1$
1574:                progressMonitor
1575:                        .setTaskName(RefactoringCoreMessages.RenameTypeProcessor_checking_similarly_named_declarations_refactoring_conditions);
1576:
1577:                for (Iterator iter = fPreloadedElementToName.keySet()
1578:                        .iterator(); iter.hasNext();) {
1579:
1580:                    final IJavaElement element = (IJavaElement) iter.next();
1581:
1582:                    current++;
1583:                    progressMonitor.worked(3);
1584:
1585:                    // not selected? -> skip
1586:                    if (!((Boolean) (fPreloadedElementToSelection.get(element)))
1587:                            .booleanValue())
1588:                        continue;
1589:
1590:                    // already registered? (may happen with overridden methods) -> skip
1591:                    if (fFinalSimilarElementToName.containsKey(element))
1592:                        continue;
1593:
1594:                    // CompilationUnit changed? (note: fPreloadedElementToName is sorted by CompilationUnit)
1595:                    ICompilationUnit newCU = (ICompilationUnit) element
1596:                            .getAncestor(IJavaElement.COMPILATION_UNIT);
1597:
1598:                    if (!newCU.equals(currentCU)) {
1599:
1600:                        checkCUCompleteConditions(status, currentResolvedCU,
1601:                                currentCU, processors);
1602:
1603:                        if (status.hasFatalError())
1604:                            return status;
1605:
1606:                        // reset values
1607:                        currentResolvedCU = null;
1608:                        currentCU = newCU;
1609:                        processors.clear();
1610:                    }
1611:
1612:                    final String newName = (String) fPreloadedElementToName
1613:                            .get(element);
1614:                    RefactoringProcessor processor = null;
1615:
1616:                    if (element instanceof  ILocalVariable) {
1617:                        final ILocalVariable currentLocal = (ILocalVariable) element;
1618:
1619:                        if (currentResolvedCU == null)
1620:                            currentResolvedCU = new RefactoringASTParser(
1621:                                    AST.JLS3).parse(currentCU, true);
1622:
1623:                        processor = createLocalRenameProcessor(currentLocal,
1624:                                newName, currentResolvedCU);
1625:
1626:                        // don't check for conflicting rename => is done by #checkCUCompleteConditions().
1627:
1628:                        if (status.hasFatalError())
1629:                            return status;
1630:                        fFinalSimilarElementToName.put(currentLocal, newName);
1631:                    }
1632:                    if (element instanceof  IField) {
1633:                        final IField currentField = (IField) element;
1634:                        processor = createFieldRenameProcessor(currentField,
1635:                                newName);
1636:
1637:                        status.merge(checkForConflictingRename(currentField,
1638:                                newName));
1639:                        if (status.hasFatalError())
1640:                            return status;
1641:                        fFinalSimilarElementToName.put(currentField, newName);
1642:                    }
1643:                    if (element instanceof  IMethod) {
1644:                        IMethod currentMethod = (IMethod) element;
1645:                        if (MethodChecks.isVirtual(currentMethod)) {
1646:
1647:                            final IType declaringType = currentMethod
1648:                                    .getDeclaringType();
1649:                            ITypeHierarchy hierarchy = null;
1650:                            if (!declaringType.isInterface())
1651:                                hierarchy = declaringType
1652:                                        .newTypeHierarchy(new NullProgressMonitor());
1653:
1654:                            final IMethod topmost = MethodChecks
1655:                                    .getTopmostMethod(currentMethod, hierarchy,
1656:                                            new NullProgressMonitor());
1657:                            if (topmost != null)
1658:                                currentMethod = topmost;
1659:                            if (handledTopLevelMethods.contains(currentMethod))
1660:                                continue;
1661:                            handledTopLevelMethods.add(currentMethod);
1662:                            final IMethod[] ripples = MethodChecks
1663:                                    .getOverriddenMethods(currentMethod,
1664:                                            new NullProgressMonitor());
1665:
1666:                            if (checkForWarnings(warnings, newName, ripples))
1667:                                continue;
1668:
1669:                            status.merge(checkForConflictingRename(ripples,
1670:                                    newName));
1671:                            if (status.hasFatalError())
1672:                                return status;
1673:
1674:                            processor = createVirtualMethodRenameProcessor(
1675:                                    currentMethod, newName, ripples, hierarchy);
1676:                            fFinalSimilarElementToName.put(currentMethod,
1677:                                    newName);
1678:                            for (int i = 0; i < ripples.length; i++) {
1679:                                fFinalSimilarElementToName.put(ripples[i],
1680:                                        newName);
1681:                            }
1682:                        } else {
1683:
1684:                            status.merge(checkForConflictingRename(
1685:                                    new IMethod[] { currentMethod }, newName));
1686:                            if (status.hasFatalError())
1687:                                break;
1688:
1689:                            fFinalSimilarElementToName.put(currentMethod,
1690:                                    newName);
1691:
1692:                            processor = createNonVirtualMethodRenameProcessor(
1693:                                    currentMethod, newName);
1694:                        }
1695:                    }
1696:
1697:                    progressMonitor
1698:                            .subTask(Messages
1699:                                    .format(
1700:                                            RefactoringCoreMessages.RenameTypeProcessor_progress_current_total,
1701:                                            new Object[] {
1702:                                                    String.valueOf(current),
1703:                                                    String.valueOf(max) }));
1704:
1705:                    status
1706:                            .merge(processor
1707:                                    .checkInitialConditions(new NoOverrideProgressMonitor(
1708:                                            progressMonitor, 1)));
1709:
1710:                    if (status.hasFatalError())
1711:                        return status;
1712:
1713:                    status.merge(processor.checkFinalConditions(
1714:                            new NoOverrideProgressMonitor(progressMonitor, 1),
1715:                            context));
1716:
1717:                    if (status.hasFatalError())
1718:                        return status;
1719:
1720:                    processors.add(processor);
1721:
1722:                    progressMonitor.worked(1);
1723:
1724:                    if (progressMonitor.isCanceled())
1725:                        throw new OperationCanceledException();
1726:                }
1727:
1728:                // check last CU
1729:                checkCUCompleteConditions(status, currentResolvedCU, currentCU,
1730:                        processors);
1731:
1732:                status.merge(addWarnings(warnings));
1733:
1734:                progressMonitor.done();
1735:                return status;
1736:            }
1737:
1738:            private void checkCUCompleteConditions(
1739:                    final RefactoringStatus status,
1740:                    CompilationUnit currentResolvedCU,
1741:                    ICompilationUnit currentCU, List processors)
1742:                    throws CoreException {
1743:
1744:                // check local variable conditions
1745:                List locals = getProcessorsOfType(processors,
1746:                        RenameLocalVariableProcessor.class);
1747:                if (!locals.isEmpty()) {
1748:                    RenameAnalyzeUtil.LocalAnalyzePackage[] analyzePackages = new RenameAnalyzeUtil.LocalAnalyzePackage[locals
1749:                            .size()];
1750:                    TextChangeManager manager = new TextChangeManager();
1751:                    int current = 0;
1752:                    TextChange textChange = manager.get(currentCU);
1753:                    textChange.setKeepPreviewEdits(true);
1754:                    for (Iterator iterator = locals.iterator(); iterator
1755:                            .hasNext();) {
1756:                        RenameLocalVariableProcessor localProcessor = (RenameLocalVariableProcessor) iterator
1757:                                .next();
1758:                        RenameAnalyzeUtil.LocalAnalyzePackage analyzePackage = localProcessor
1759:                                .getLocalAnalyzePackage();
1760:                        analyzePackages[current] = analyzePackage;
1761:                        for (int i = 0; i < analyzePackage.fOccurenceEdits.length; i++) {
1762:                            TextChangeCompatibility
1763:                                    .addTextEdit(
1764:                                            textChange,
1765:                                            "", analyzePackage.fOccurenceEdits[i], GroupCategorySet.NONE); //$NON-NLS-1$
1766:                        }
1767:                        current++;
1768:                    }
1769:                    status.merge(RenameAnalyzeUtil.analyzeLocalRenames(
1770:                            analyzePackages, textChange, currentResolvedCU,
1771:                            false));
1772:                }
1773:
1774:                /*
1775:                 * There is room for performance improvement here: One could move
1776:                 * shadowing analyzes out of the field and method processors and perform
1777:                 * it here, thus saving on working copy creation. Drawback is increased
1778:                 * heap consumption.
1779:                 */
1780:            }
1781:
1782:            private List getProcessorsOfType(List processors, Class type) {
1783:                List tmp = new ArrayList();
1784:                for (Iterator iter = processors.iterator(); iter.hasNext();) {
1785:                    RefactoringProcessor element = (RefactoringProcessor) iter
1786:                            .next();
1787:                    if (element.getClass().equals(type))
1788:                        tmp.add(element);
1789:                }
1790:                return tmp;
1791:            }
1792:
1793:            // ------------------ Error checking -------------
1794:
1795:            /**
1796:             * Checks whether one of the given methods, which will all be renamed to
1797:             * "newName", shares a type with another already registered method which is
1798:             * renamed to the same new name and shares the same parameters.
1799:             * @param methods 
1800:             * @param newName 
1801:             * @return status
1802:             * 
1803:             * @see #checkForConflictingRename(IField, String)
1804:             */
1805:            private RefactoringStatus checkForConflictingRename(
1806:                    IMethod[] methods, String newName) {
1807:                RefactoringStatus status = new RefactoringStatus();
1808:                for (Iterator iter = fFinalSimilarElementToName.keySet()
1809:                        .iterator(); iter.hasNext();) {
1810:                    IJavaElement element = (IJavaElement) iter.next();
1811:                    if (element instanceof  IMethod) {
1812:                        IMethod alreadyRegisteredMethod = (IMethod) element;
1813:                        String alreadyRegisteredMethodName = (String) fFinalSimilarElementToName
1814:                                .get(element);
1815:                        for (int i = 0; i < methods.length; i++) {
1816:                            IMethod method2 = methods[i];
1817:                            if ((alreadyRegisteredMethodName.equals(newName))
1818:                                    && (method2.getDeclaringType()
1819:                                            .equals(alreadyRegisteredMethod
1820:                                                    .getDeclaringType()))
1821:                                    && (sameParams(alreadyRegisteredMethod,
1822:                                            method2))) {
1823:                                String message = Messages
1824:                                        .format(
1825:                                                RefactoringCoreMessages.RenameTypeProcessor_cannot_rename_methods_same_new_name,
1826:                                                new String[] {
1827:                                                        alreadyRegisteredMethod
1828:                                                                .getElementName(),
1829:                                                        method2
1830:                                                                .getElementName(),
1831:                                                        alreadyRegisteredMethod
1832:                                                                .getDeclaringType()
1833:                                                                .getFullyQualifiedName(),
1834:                                                        newName });
1835:                                status.addFatalError(message);
1836:                                return status;
1837:                            }
1838:                        }
1839:                    }
1840:                }
1841:                return status;
1842:            }
1843:
1844:            private static boolean sameParams(IMethod method, IMethod method2) {
1845:
1846:                if (method.getNumberOfParameters() != method2
1847:                        .getNumberOfParameters())
1848:                    return false;
1849:
1850:                String[] params = method.getParameterTypes();
1851:                String[] params2 = method2.getParameterTypes();
1852:
1853:                for (int i = 0; i < params.length; i++) {
1854:                    String t1 = Signature.getSimpleName(Signature
1855:                            .toString(params[i]));
1856:                    String t2 = Signature.getSimpleName(Signature
1857:                            .toString(params2[i]));
1858:                    if (!t1.equals(t2)) {
1859:                        return false;
1860:                    }
1861:                }
1862:                return true;
1863:            }
1864:
1865:            /**
1866:             * If suffix matching is enabled, the refactoring may suggest two fields to
1867:             * have the same name which reside in the same type. Same thing may also
1868:             * happen if the user makes poor choices for the field names.
1869:             * 
1870:             * Consider: FooBarThing fFooBarThing; FooBarThing fBarThing;
1871:             * 
1872:             * Rename "FooBarThing" to "DifferentHunk". Suggestion for both fields is
1873:             * "fDifferentHunk" (and rightly so).
1874:             * @param currentField 
1875:             * @param newName 
1876:             * @return status
1877:             */
1878:            private RefactoringStatus checkForConflictingRename(
1879:                    IField currentField, String newName) {
1880:                RefactoringStatus status = new RefactoringStatus();
1881:                for (Iterator iter = fFinalSimilarElementToName.keySet()
1882:                        .iterator(); iter.hasNext();) {
1883:                    IJavaElement element = (IJavaElement) iter.next();
1884:                    if (element instanceof  IField) {
1885:                        IField alreadyRegisteredField = (IField) element;
1886:                        String alreadyRegisteredFieldName = (String) fFinalSimilarElementToName
1887:                                .get(element);
1888:                        if (alreadyRegisteredFieldName.equals(newName)) {
1889:                            if (alreadyRegisteredField.getDeclaringType()
1890:                                    .equals(currentField.getDeclaringType())) {
1891:
1892:                                String message = Messages
1893:                                        .format(
1894:                                                RefactoringCoreMessages.RenameTypeProcessor_cannot_rename_fields_same_new_name,
1895:                                                new String[] {
1896:                                                        alreadyRegisteredField
1897:                                                                .getElementName(),
1898:                                                        currentField
1899:                                                                .getElementName(),
1900:                                                        alreadyRegisteredField
1901:                                                                .getDeclaringType()
1902:                                                                .getFullyQualifiedName(),
1903:                                                        newName });
1904:                                status.addFatalError(message);
1905:                                return status;
1906:                            }
1907:                        }
1908:                    }
1909:                }
1910:                return status;
1911:            }
1912:
1913:            private RefactoringStatus addWarnings(final Set warnings) {
1914:                RefactoringStatus status = new RefactoringStatus();
1915:
1916:                // Remove deleted ripple methods from user selection and add warnings
1917:                for (Iterator iter = warnings.iterator(); iter.hasNext();) {
1918:                    final Warning warning = (Warning) iter.next();
1919:                    final IMethod[] elements = warning.getRipple();
1920:                    if (warning.isSelectionWarning()) {
1921:                        String message = Messages
1922:                                .format(
1923:                                        RefactoringCoreMessages.RenameTypeProcessor_deselected_method_is_overridden,
1924:                                        new String[] {
1925:                                                JavaElementLabels
1926:                                                        .getElementLabel(
1927:                                                                elements[0],
1928:                                                                JavaElementLabels.ALL_DEFAULT),
1929:                                                JavaElementLabels
1930:                                                        .getElementLabel(
1931:                                                                elements[0]
1932:                                                                        .getDeclaringType(),
1933:                                                                JavaElementLabels.ALL_DEFAULT) });
1934:                        status.addWarning(message);
1935:                    }
1936:                    if (warning.isNameWarning()) {
1937:                        String message = Messages
1938:                                .format(
1939:                                        RefactoringCoreMessages.RenameTypeProcessor_renamed_method_is_overridden,
1940:                                        new String[] {
1941:                                                JavaElementLabels
1942:                                                        .getElementLabel(
1943:                                                                elements[0],
1944:                                                                JavaElementLabels.ALL_DEFAULT),
1945:                                                JavaElementLabels
1946:                                                        .getElementLabel(
1947:                                                                elements[0]
1948:                                                                        .getDeclaringType(),
1949:                                                                JavaElementLabels.ALL_DEFAULT) });
1950:                        status.addWarning(message);
1951:                    }
1952:                    for (int i = 0; i < elements.length; i++)
1953:                        fPreloadedElementToSelection.put(elements[i],
1954:                                Boolean.FALSE);
1955:                }
1956:                return status;
1957:            }
1958:
1959:            /*
1960:             * If one of the methods of this ripple was deselected or renamed by
1961:             * the user, deselect the whole chain and add warnings.
1962:             */
1963:            private boolean checkForWarnings(final Set warnings,
1964:                    final String newName, final IMethod[] ripples) {
1965:
1966:                boolean addSelectionWarning = false;
1967:                boolean addNameWarning = false;
1968:                for (int i = 0; i < ripples.length; i++) {
1969:                    String newNameOfRipple = (String) fPreloadedElementToName
1970:                            .get(ripples[i]);
1971:                    Boolean selected = (Boolean) fPreloadedElementToSelection
1972:                            .get(ripples[i]);
1973:
1974:                    // selected may be null here due to supermethods like
1975:                    // setSomeClass(Object class) (subsignature match)
1976:                    // Don't add a warning.
1977:                    if (selected == null)
1978:                        continue;
1979:
1980:                    if (!selected.booleanValue())
1981:                        addSelectionWarning = true;
1982:
1983:                    if (!newName.equals(newNameOfRipple))
1984:                        addNameWarning = true;
1985:                }
1986:                if (addSelectionWarning || addNameWarning)
1987:                    warnings.add(new Warning(ripples, addSelectionWarning,
1988:                            addNameWarning));
1989:
1990:                return (addSelectionWarning || addNameWarning);
1991:            }
1992:
1993:            private class Warning {
1994:
1995:                private IMethod[] fRipple;
1996:                private boolean fSelectionWarning;
1997:                private boolean fNameWarning;
1998:
1999:                public Warning(IMethod[] ripple, boolean isSelectionWarning,
2000:                        boolean isNameWarning) {
2001:                    fRipple = ripple;
2002:                    fSelectionWarning = isSelectionWarning;
2003:                    fNameWarning = isNameWarning;
2004:                }
2005:
2006:                public boolean isNameWarning() {
2007:                    return fNameWarning;
2008:                }
2009:
2010:                public IMethod[] getRipple() {
2011:                    return fRipple;
2012:                }
2013:
2014:                public boolean isSelectionWarning() {
2015:                    return fSelectionWarning;
2016:                }
2017:            }
2018:
2019:            // ----------------- Processor creation --------
2020:
2021:            private RenameMethodProcessor createVirtualMethodRenameProcessor(
2022:                    IMethod currentMethod, String newMethodName,
2023:                    IMethod[] ripples, ITypeHierarchy hierarchy)
2024:                    throws JavaModelException {
2025:                RenameMethodProcessor processor = new RenameVirtualMethodProcessor(
2026:                        currentMethod, ripples, fChangeManager, hierarchy,
2027:                        CATEGORY_METHOD_RENAME);
2028:                initMethodProcessor(processor, newMethodName);
2029:                return processor;
2030:            }
2031:
2032:            private RenameMethodProcessor createNonVirtualMethodRenameProcessor(
2033:                    IMethod currentMethod, String newMethodName) {
2034:                RenameMethodProcessor processor = new RenameNonVirtualMethodProcessor(
2035:                        currentMethod, fChangeManager, CATEGORY_METHOD_RENAME);
2036:                initMethodProcessor(processor, newMethodName);
2037:                return processor;
2038:            }
2039:
2040:            private void initMethodProcessor(RenameMethodProcessor processor,
2041:                    String newMethodName) {
2042:                processor.setNewElementName(newMethodName);
2043:                processor.setUpdateReferences(getUpdateReferences());
2044:            }
2045:
2046:            private RenameFieldProcessor createFieldRenameProcessor(
2047:                    final IField field, final String newName) {
2048:                final RenameFieldProcessor processor = new RenameFieldProcessor(
2049:                        field, fChangeManager, CATEGORY_FIELD_RENAME);
2050:                processor.setNewElementName(newName);
2051:                processor.setRenameGetter(false);
2052:                processor.setRenameSetter(false);
2053:                processor.setUpdateReferences(getUpdateReferences());
2054:                processor.setUpdateTextualMatches(false);
2055:                return processor;
2056:            }
2057:
2058:            private RenameLocalVariableProcessor createLocalRenameProcessor(
2059:                    final ILocalVariable local, final String newName,
2060:                    final CompilationUnit compilationUnit) {
2061:                final RenameLocalVariableProcessor processor = new RenameLocalVariableProcessor(
2062:                        local, fChangeManager, compilationUnit,
2063:                        CATEGORY_LOCAL_RENAME);
2064:                processor.setNewElementName(newName);
2065:                processor.setUpdateReferences(getUpdateReferences());
2066:                return processor;
2067:            }
2068:
2069:            // ----------- Edit creation -----------
2070:
2071:            /**
2072:             * Updates textual matches for fields.
2073:             * 
2074:             * Strategy for matching text matches: Match and replace all fully qualified
2075:             * field names, but non-qualified field names only iff there are no fields
2076:             * which have the same original, but a different new name. Don't add java
2077:             * references; duplicate edits may be created but do not matter.
2078:             * @param manager 
2079:             * @param monitor 
2080:             * @throws CoreException 
2081:             */
2082:            private void addSimilarElementsTextualUpdates(
2083:                    TextChangeManager manager, IProgressMonitor monitor)
2084:                    throws CoreException {
2085:
2086:                final Map simpleNames = new HashMap();
2087:                final List forbiddenSimpleNames = new ArrayList();
2088:
2089:                for (Iterator iter = fFinalSimilarElementToName.keySet()
2090:                        .iterator(); iter.hasNext();) {
2091:                    final IJavaElement element = (IJavaElement) iter.next();
2092:                    if (element instanceof  IField) {
2093:
2094:                        if (forbiddenSimpleNames.contains(element
2095:                                .getElementName()))
2096:                            continue;
2097:
2098:                        final String registeredNewName = (String) simpleNames
2099:                                .get(element.getElementName());
2100:                        final String newNameToCheck = (String) fFinalSimilarElementToName
2101:                                .get(element);
2102:                        if (registeredNewName == null)
2103:                            simpleNames.put(element.getElementName(),
2104:                                    newNameToCheck);
2105:                        else if (!registeredNewName.equals(newNameToCheck))
2106:                            forbiddenSimpleNames.add(element.getElementName());
2107:                    }
2108:                }
2109:
2110:                for (Iterator iter = fFinalSimilarElementToName.keySet()
2111:                        .iterator(); iter.hasNext();) {
2112:                    final IJavaElement element = (IJavaElement) iter.next();
2113:                    if (element instanceof  IField) {
2114:                        final IField field = (IField) element;
2115:                        final String newName = (String) fFinalSimilarElementToName
2116:                                .get(field);
2117:                        TextMatchUpdater.perform(monitor,
2118:                                RefactoringScopeFactory.create(field), field
2119:                                        .getElementName(), field
2120:                                        .getDeclaringType()
2121:                                        .getFullyQualifiedName(), newName,
2122:                                manager, new SearchResultGroup[0],
2123:                                forbiddenSimpleNames.contains(field
2124:                                        .getElementName()));
2125:                    }
2126:                }
2127:            }
2128:
2129:            // ------ UI interaction
2130:
2131:            /**
2132:             * @return the map of similarly named elements (IJavaElement -> String with new name)
2133:             * This map is live. Callers may change the new names of the elements; they
2134:             * may not change the key set.
2135:             */
2136:            public Map/* <IJavaElement, String> */getSimilarElementsToNewNames() {
2137:                return fPreloadedElementToName;
2138:            }
2139:
2140:            /**
2141:             * @return the map of similarly named elements (IJavaElement -> Boolean if selected) This
2142:             * map is live. Callers may change the selection status of the elements;
2143:             * they may not change the key set.
2144:             */
2145:            public Map/* <IJavaElement, Boolean> */getSimilarElementsToSelection() {
2146:                return fPreloadedElementToSelection;
2147:            }
2148:
2149:            /**
2150:             * Resets the element maps back to the original status. This affects the
2151:             * maps returned in {@link #getSimilarElementsToNewNames() } and
2152:             * {@link #getSimilarElementsToSelection() }. All new names are reset to
2153:             * the calculated ones and every element gets selected.
2154:             */
2155:            public void resetSelectedSimilarElements() {
2156:                Assert.isNotNull(fPreloadedElementToName);
2157:                for (Iterator iter = fPreloadedElementToNameDefault.keySet()
2158:                        .iterator(); iter.hasNext();) {
2159:                    final IJavaElement element = (IJavaElement) iter.next();
2160:                    fPreloadedElementToName.put(element,
2161:                            fPreloadedElementToNameDefault.get(element));
2162:                    fPreloadedElementToSelection.put(element, Boolean.TRUE);
2163:                }
2164:            }
2165:
2166:            /**
2167:             * @return true iff the "update similarly named elements" flag is set AND the
2168:             * search yielded some elements to be renamed.
2169:             */
2170:            public boolean hasSimilarElementsToRename() {
2171:                if (!fUpdateSimilarElements)
2172:                    return false;
2173:                if (fPreloadedElementToName == null)
2174:                    return false;
2175:                if (fPreloadedElementToName.size() == 0)
2176:                    return false;
2177:                return true;
2178:            }
2179:        }
w__w_w_.__j___ava_2s_.c_om___ | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.